// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/allocation-site-scopes-inl.h"
#include "src/arguments-inl.h"
#include "src/ast/ast.h"
#include "src/isolate-inl.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/heap-object-inl.h"
#include "src/objects/js-regexp-inl.h"
#include "src/objects/literal-objects-inl.h"
#include "src/runtime/runtime-utils.h"
#include "src/runtime/runtime.h"

namespace v8 {
namespace internal {

namespace {

bool IsUninitializedLiteralSite(Object* literal_site) {
  return literal_site == Smi::kZero;
}

bool HasBoilerplate(Handle<Object> literal_site) {
  return !literal_site->IsSmi();
}

void PreInitializeLiteralSite(Handle<FeedbackVector> vector,
                              FeedbackSlot slot) {
  vector->Set(slot, Smi::FromInt(1));
}

Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
                                      Handle<Object> description,
                                      PretenureFlag pretenure_flag);

enum DeepCopyHints { kNoHints = 0, kObjectIsShallow = 1 };

template <class ContextObject>
class JSObjectWalkVisitor {
 public:
  JSObjectWalkVisitor(ContextObject* site_context, DeepCopyHints hints)
      : site_context_(site_context), hints_(hints) {}

  V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> StructureWalk(
      Handle<JSObject> object);

 protected:
  V8_WARN_UNUSED_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
      Handle<JSObject> object, Handle<JSObject> value) {
    // Dont create allocation sites for nested object literals
    if (!value->IsJSArray()) {
      return StructureWalk(value);
    }

    Handle<AllocationSite> current_site = site_context()->EnterNewScope();
    MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
    site_context()->ExitScope(current_site, value);
    return copy_of_value;
  }

  inline ContextObject* site_context() { return site_context_; }
  inline Isolate* isolate() { return site_context()->isolate(); }

 private:
  ContextObject* site_context_;
  const DeepCopyHints hints_;
};

template <class ContextObject>
MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
    Handle<JSObject> object) {
  Isolate* isolate = this->isolate();
  bool copying = ContextObject::kCopying;
  bool shallow = hints_ == kObjectIsShallow;

  if (!shallow) {
    StackLimitCheck check(isolate);

    if (check.HasOverflowed()) {
      isolate->StackOverflow();
      return MaybeHandle<JSObject>();
    }
  }

  if (object->map()->is_deprecated()) {
    JSObject::MigrateInstance(object);
  }

  Handle<JSObject> copy;
  if (copying) {
    // JSFunction objects are not allowed to be in normal boilerplates at all.
    DCHECK(!object->IsJSFunction());
    Handle<AllocationSite> site_to_pass;
    if (site_context()->ShouldCreateMemento(object)) {
      site_to_pass = site_context()->current();
    }
    copy = isolate->factory()->CopyJSObjectWithAllocationSite(object,
                                                              site_to_pass);
  } else {
    copy = object;
  }

  DCHECK(copying || copy.is_identical_to(object));

  if (shallow) return copy;

  HandleScope scope(isolate);

  // Deep copy own properties. Arrays only have 1 property "length".
  if (!copy->IsJSArray()) {
    if (copy->HasFastProperties()) {
      Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors(),
                                          isolate);
      int limit = copy->map()->NumberOfOwnDescriptors();
      for (int i = 0; i < limit; i++) {
        DCHECK_EQ(kField, descriptors->GetDetails(i).location());
        DCHECK_EQ(kData, descriptors->GetDetails(i).kind());
        FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
        if (copy->IsUnboxedDoubleField(index)) continue;
        Object* raw = copy->RawFastPropertyAt(index);
        if (raw->IsJSObject()) {
          Handle<JSObject> value(JSObject::cast(raw), isolate);
          ASSIGN_RETURN_ON_EXCEPTION(
              isolate, value, VisitElementOrProperty(copy, value), JSObject);
          if (copying) copy->FastPropertyAtPut(index, *value);
        } else if (copying && raw->IsMutableHeapNumber()) {
          DCHECK(descriptors->GetDetails(i).representation().IsDouble());
          uint64_t double_value = MutableHeapNumber::cast(raw)->value_as_bits();
          auto value =
              isolate->factory()->NewMutableHeapNumberFromBits(double_value);
          copy->FastPropertyAtPut(index, *value);
        }
      }
    } else {
      Handle<NameDictionary> dict(copy->property_dictionary(), isolate);
      for (int i = 0; i < dict->Capacity(); i++) {
        Object* raw = dict->ValueAt(i);
        if (!raw->IsJSObject()) continue;
        DCHECK(dict->KeyAt(i)->IsName());
        Handle<JSObject> value(JSObject::cast(raw), isolate);
        ASSIGN_RETURN_ON_EXCEPTION(
            isolate, value, VisitElementOrProperty(copy, value), JSObject);
        if (copying) dict->ValueAtPut(i, *value);
      }
    }

    // Assume non-arrays don't end up having elements.
    if (copy->elements()->length() == 0) return copy;
  }

  // Deep copy own elements.
  switch (copy->GetElementsKind()) {
    case PACKED_ELEMENTS:
    case HOLEY_ELEMENTS: {
      Handle<FixedArray> elements(FixedArray::cast(copy->elements()), isolate);
      if (elements->map() == ReadOnlyRoots(isolate).fixed_cow_array_map()) {
#ifdef DEBUG
        for (int i = 0; i < elements->length(); i++) {
          DCHECK(!elements->get(i)->IsJSObject());
        }
#endif
      } else {
        for (int i = 0; i < elements->length(); i++) {
          Object* raw = elements->get(i);
          if (!raw->IsJSObject()) continue;
          Handle<JSObject> value(JSObject::cast(raw), isolate);
          ASSIGN_RETURN_ON_EXCEPTION(
              isolate, value, VisitElementOrProperty(copy, value), JSObject);
          if (copying) elements->set(i, *value);
        }
      }
      break;
    }
    case DICTIONARY_ELEMENTS: {
      Handle<NumberDictionary> element_dictionary(copy->element_dictionary(),
                                                  isolate);
      int capacity = element_dictionary->Capacity();
      for (int i = 0; i < capacity; i++) {
        Object* raw = element_dictionary->ValueAt(i);
        if (!raw->IsJSObject()) continue;
        Handle<JSObject> value(JSObject::cast(raw), isolate);
        ASSIGN_RETURN_ON_EXCEPTION(
            isolate, value, VisitElementOrProperty(copy, value), JSObject);
        if (copying) element_dictionary->ValueAtPut(i, *value);
      }
      break;
    }
    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
      UNIMPLEMENTED();
      break;
    case FAST_STRING_WRAPPER_ELEMENTS:
    case SLOW_STRING_WRAPPER_ELEMENTS:
      UNREACHABLE();
      break;

#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:

      TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
      // Typed elements cannot be created using an object literal.
      UNREACHABLE();
      break;

    case PACKED_SMI_ELEMENTS:
    case HOLEY_SMI_ELEMENTS:
    case PACKED_DOUBLE_ELEMENTS:
    case HOLEY_DOUBLE_ELEMENTS:
    case NO_ELEMENTS:
      // No contained objects, nothing to do.
      break;
  }

  return copy;
}

class DeprecationUpdateContext {
 public:
  explicit DeprecationUpdateContext(Isolate* isolate) { isolate_ = isolate; }
  Isolate* isolate() { return isolate_; }
  bool ShouldCreateMemento(Handle<JSObject> object) { return false; }
  inline void ExitScope(Handle<AllocationSite> scope_site,
                        Handle<JSObject> object) {}
  Handle<AllocationSite> EnterNewScope() { return Handle<AllocationSite>(); }
  Handle<AllocationSite> current() {
    UNREACHABLE();
    return Handle<AllocationSite>();
  }

  static const bool kCopying = false;

 private:
  Isolate* isolate_;
};

// AllocationSiteCreationContext aids in the creation of AllocationSites to
// accompany object literals.
class AllocationSiteCreationContext : public AllocationSiteContext {
 public:
  explicit AllocationSiteCreationContext(Isolate* isolate)
      : AllocationSiteContext(isolate) {}

  Handle<AllocationSite> EnterNewScope() {
    Handle<AllocationSite> scope_site;
    if (top().is_null()) {
      // We are creating the top level AllocationSite as opposed to a nested
      // AllocationSite.
      InitializeTraversal(isolate()->factory()->NewAllocationSite(true));
      scope_site = Handle<AllocationSite>(*top(), isolate());
      if (FLAG_trace_creation_allocation_sites) {
        PrintF("*** Creating top level %s AllocationSite %p\n", "Fat",
               static_cast<void*>(*scope_site));
      }
    } else {
      DCHECK(!current().is_null());
      scope_site = isolate()->factory()->NewAllocationSite(false);
      if (FLAG_trace_creation_allocation_sites) {
        PrintF(
            "*** Creating nested %s AllocationSite (top, current, new) (%p, "
            "%p, "
            "%p)\n",
            "Slim", static_cast<void*>(*top()), static_cast<void*>(*current()),
            static_cast<void*>(*scope_site));
      }
      current()->set_nested_site(*scope_site);
      update_current_site(*scope_site);
    }
    DCHECK(!scope_site.is_null());
    return scope_site;
  }
  void ExitScope(Handle<AllocationSite> scope_site, Handle<JSObject> object) {
    if (object.is_null()) return;
    scope_site->set_boilerplate(*object);
    if (FLAG_trace_creation_allocation_sites) {
      bool top_level =
          !scope_site.is_null() && top().is_identical_to(scope_site);
      if (top_level) {
        PrintF("*** Setting AllocationSite %p transition_info %p\n",
               static_cast<void*>(*scope_site), static_cast<void*>(*object));
      } else {
        PrintF("*** Setting AllocationSite (%p, %p) transition_info %p\n",
               static_cast<void*>(*top()), static_cast<void*>(*scope_site),
               static_cast<void*>(*object));
      }
    }
  }
  static const bool kCopying = false;
};

MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
                               DeprecationUpdateContext* site_context) {
  JSObjectWalkVisitor<DeprecationUpdateContext> v(site_context, kNoHints);
  MaybeHandle<JSObject> result = v.StructureWalk(object);
  Handle<JSObject> for_assert;
  DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
  return result;
}

MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
                               AllocationSiteCreationContext* site_context) {
  JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, kNoHints);
  MaybeHandle<JSObject> result = v.StructureWalk(object);
  Handle<JSObject> for_assert;
  DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
  return result;
}

MaybeHandle<JSObject> DeepCopy(Handle<JSObject> object,
                               AllocationSiteUsageContext* site_context,
                               DeepCopyHints hints) {
  JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, hints);
  MaybeHandle<JSObject> copy = v.StructureWalk(object);
  Handle<JSObject> for_assert;
  DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
  return copy;
}

struct ObjectLiteralHelper {
  static Handle<JSObject> Create(Isolate* isolate,
                                 Handle<HeapObject> description, int flags,
                                 PretenureFlag pretenure_flag) {
    Handle<NativeContext> native_context = isolate->native_context();
    Handle<ObjectBoilerplateDescription> object_boilerplate_description =
        Handle<ObjectBoilerplateDescription>::cast(description);
    bool use_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
    bool has_null_prototype = (flags & ObjectLiteral::kHasNullPrototype) != 0;

    // In case we have function literals, we want the object to be in
    // slow properties mode for now. We don't go in the map cache because
    // maps with constant functions can't be shared if the functions are
    // not the same (which is the common case).
    int number_of_properties =
        object_boilerplate_description->backing_store_size();

    // Ignoring number_of_properties for force dictionary map with
    // __proto__:null.
    Handle<Map> map =
        has_null_prototype
            ? handle(native_context->slow_object_with_null_prototype_map(),
                     isolate)
            : isolate->factory()->ObjectLiteralMapFromCache(
                  native_context, number_of_properties);

    Handle<JSObject> boilerplate =
        map->is_dictionary_map()
            ? isolate->factory()->NewSlowJSObjectFromMap(
                  map, number_of_properties, pretenure_flag)
            : isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);

    // Normalize the elements of the boilerplate to save space if needed.
    if (!use_fast_elements) JSObject::NormalizeElements(boilerplate);

    // Add the constant properties to the boilerplate.
    int length = object_boilerplate_description->size();
    // TODO(verwaest): Support tracking representations in the boilerplate.
    for (int index = 0; index < length; index++) {
      Handle<Object> key(object_boilerplate_description->name(index), isolate);
      Handle<Object> value(object_boilerplate_description->value(index),
                           isolate);

      if (value->IsObjectBoilerplateDescription() ||
          value->IsArrayBoilerplateDescription()) {
        value = InnerCreateBoilerplate(isolate, value, pretenure_flag);
      }
      uint32_t element_index = 0;
      if (key->ToArrayIndex(&element_index)) {
        // Array index (uint32).
        if (value->IsUninitialized(isolate)) {
          value = handle(Smi::kZero, isolate);
        }
        JSObject::SetOwnElementIgnoreAttributes(boilerplate, element_index,
                                                value, NONE)
            .Check();
      } else {
        Handle<String> name = Handle<String>::cast(key);
        DCHECK(!name->AsArrayIndex(&element_index));
        JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name, value, NONE)
            .Check();
      }
    }

    if (map->is_dictionary_map() && !has_null_prototype) {
      // TODO(cbruni): avoid making the boilerplate fast again, the clone stub
      // supports dict-mode objects directly.
      JSObject::MigrateSlowToFast(boilerplate,
                                  boilerplate->map()->UnusedPropertyFields(),
                                  "FastLiteral");
    }
    return boilerplate;
  }
};

struct ArrayLiteralHelper {
  static Handle<JSObject> Create(Isolate* isolate,
                                 Handle<HeapObject> description, int flags,
                                 PretenureFlag pretenure_flag) {
    Handle<ArrayBoilerplateDescription> array_boilerplate_description =
        Handle<ArrayBoilerplateDescription>::cast(description);

    ElementsKind constant_elements_kind =
        array_boilerplate_description->elements_kind();

    Handle<FixedArrayBase> constant_elements_values(
        array_boilerplate_description->constant_elements(), isolate);

    // Create the JSArray.
    Handle<FixedArrayBase> copied_elements_values;
    if (IsDoubleElementsKind(constant_elements_kind)) {
      copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
          Handle<FixedDoubleArray>::cast(constant_elements_values));
    } else {
      DCHECK(IsSmiOrObjectElementsKind(constant_elements_kind));
      const bool is_cow = (constant_elements_values->map() ==
                           ReadOnlyRoots(isolate).fixed_cow_array_map());
      if (is_cow) {
        copied_elements_values = constant_elements_values;
#if DEBUG
        Handle<FixedArray> fixed_array_values =
            Handle<FixedArray>::cast(copied_elements_values);
        for (int i = 0; i < fixed_array_values->length(); i++) {
          DCHECK(!fixed_array_values->get(i)->IsFixedArray());
        }
#endif
      } else {
        Handle<FixedArray> fixed_array_values =
            Handle<FixedArray>::cast(constant_elements_values);
        Handle<FixedArray> fixed_array_values_copy =
            isolate->factory()->CopyFixedArray(fixed_array_values);
        copied_elements_values = fixed_array_values_copy;
        FOR_WITH_HANDLE_SCOPE(
            isolate, int, i = 0, i, i < fixed_array_values->length(), i++, {
              Handle<Object> value(fixed_array_values->get(i), isolate);

              if (value->IsArrayBoilerplateDescription() ||
                  value->IsObjectBoilerplateDescription()) {
                Handle<Object> result =
                    InnerCreateBoilerplate(isolate, value, pretenure_flag);
                fixed_array_values_copy->set(i, *result);
              }
            });
      }
    }

    return isolate->factory()->NewJSArrayWithElements(
        copied_elements_values, constant_elements_kind,
        copied_elements_values->length(), pretenure_flag);
  }
};

Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
                                      Handle<Object> description,
                                      PretenureFlag pretenure_flag) {
  if (description->IsObjectBoilerplateDescription()) {
    Handle<ObjectBoilerplateDescription> object_boilerplate_description =
        Handle<ObjectBoilerplateDescription>::cast(description);
    return ObjectLiteralHelper::Create(isolate, object_boilerplate_description,
                                       object_boilerplate_description->flags(),
                                       pretenure_flag);
  } else {
    DCHECK(description->IsArrayBoilerplateDescription());
    Handle<ArrayBoilerplateDescription> array_boilerplate_description =
        Handle<ArrayBoilerplateDescription>::cast(description);
    return ArrayLiteralHelper::Create(
        isolate, array_boilerplate_description,
        array_boilerplate_description->elements_kind(), pretenure_flag);
  }
}

inline DeepCopyHints DecodeCopyHints(int flags) {
  DeepCopyHints copy_hints =
      (flags & AggregateLiteral::kIsShallow) ? kObjectIsShallow : kNoHints;
  if (FLAG_track_double_fields && !FLAG_unbox_double_fields) {
    // Make sure we properly clone mutable heap numbers on 32-bit platforms.
    copy_hints = kNoHints;
  }
  return copy_hints;
}

template <typename LiteralHelper>
MaybeHandle<JSObject> CreateLiteralWithoutAllocationSite(
    Isolate* isolate, Handle<HeapObject> description, int flags) {
  Handle<JSObject> literal =
      LiteralHelper::Create(isolate, description, flags, NOT_TENURED);
  DeepCopyHints copy_hints = DecodeCopyHints(flags);
  if (copy_hints == kNoHints) {
    DeprecationUpdateContext update_context(isolate);
    RETURN_ON_EXCEPTION(isolate, DeepWalk(literal, &update_context), JSObject);
  }
  return literal;
}

template <typename LiteralHelper>
MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
                                    Handle<FeedbackVector> vector,
                                    int literals_index,
                                    Handle<HeapObject> description, int flags) {
  FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
  CHECK(literals_slot.ToInt() < vector->length());
  Handle<Object> literal_site(vector->Get(literals_slot)->cast<Object>(),
                              isolate);
  DeepCopyHints copy_hints = DecodeCopyHints(flags);

  Handle<AllocationSite> site;
  Handle<JSObject> boilerplate;

  if (HasBoilerplate(literal_site)) {
    site = Handle<AllocationSite>::cast(literal_site);
    boilerplate = Handle<JSObject>(site->boilerplate(), isolate);
  } else {
    // Eagerly create AllocationSites for literals that contain an Array.
    bool needs_initial_allocation_site =
        (flags & AggregateLiteral::kNeedsInitialAllocationSite) != 0;
    if (!needs_initial_allocation_site &&
        IsUninitializedLiteralSite(*literal_site)) {
      PreInitializeLiteralSite(vector, literals_slot);
      return CreateLiteralWithoutAllocationSite<LiteralHelper>(
          isolate, description, flags);
    } else {
      boilerplate = LiteralHelper::Create(isolate, description, flags, TENURED);
    }
    // Install AllocationSite objects.
    AllocationSiteCreationContext creation_context(isolate);
    site = creation_context.EnterNewScope();
    RETURN_ON_EXCEPTION(isolate, DeepWalk(boilerplate, &creation_context),
                        JSObject);
    creation_context.ExitScope(site, boilerplate);

    vector->Set(literals_slot, *site);
  }

  STATIC_ASSERT(static_cast<int>(ObjectLiteral::kDisableMementos) ==
                static_cast<int>(ArrayLiteral::kDisableMementos));
  bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0;

  // Copy the existing boilerplate.
  AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
  usage_context.EnterNewScope();
  MaybeHandle<JSObject> copy =
      DeepCopy(boilerplate, &usage_context, copy_hints);
  usage_context.ExitScope(site, boilerplate);
  return copy;
}
}  // namespace

RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
  HandleScope scope(isolate);
  DCHECK_EQ(4, args.length());
  CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
  CONVERT_ARG_HANDLE_CHECKED(ObjectBoilerplateDescription, description, 2);
  CONVERT_SMI_ARG_CHECKED(flags, 3);
  RETURN_RESULT_OR_FAILURE(
      isolate, CreateLiteral<ObjectLiteralHelper>(
                   isolate, vector, literals_index, description, flags));
}

RUNTIME_FUNCTION(Runtime_CreateObjectLiteralWithoutAllocationSite) {
  HandleScope scope(isolate);
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_HANDLE_CHECKED(ObjectBoilerplateDescription, description, 0);
  CONVERT_SMI_ARG_CHECKED(flags, 1);
  RETURN_RESULT_OR_FAILURE(
      isolate, CreateLiteralWithoutAllocationSite<ObjectLiteralHelper>(
                   isolate, description, flags));
}

RUNTIME_FUNCTION(Runtime_CreateArrayLiteralWithoutAllocationSite) {
  HandleScope scope(isolate);
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_HANDLE_CHECKED(ArrayBoilerplateDescription, description, 0);
  CONVERT_SMI_ARG_CHECKED(flags, 1);
  RETURN_RESULT_OR_FAILURE(
      isolate, CreateLiteralWithoutAllocationSite<ArrayLiteralHelper>(
                   isolate, description, flags));
}

RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
  HandleScope scope(isolate);
  DCHECK_EQ(4, args.length());
  CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
  CONVERT_ARG_HANDLE_CHECKED(ArrayBoilerplateDescription, elements, 2);
  CONVERT_SMI_ARG_CHECKED(flags, 3);
  RETURN_RESULT_OR_FAILURE(
      isolate, CreateLiteral<ArrayLiteralHelper>(
                   isolate, vector, literals_index, elements, flags));
}

RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) {
  HandleScope scope(isolate);
  DCHECK_EQ(4, args.length());
  CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
  CONVERT_SMI_ARG_CHECKED(index, 1);
  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
  CONVERT_SMI_ARG_CHECKED(flags, 3);

  FeedbackSlot literal_slot(FeedbackVector::ToSlot(index));

  // Check if boilerplate exists. If not, create it first.
  Handle<Object> literal_site(vector->Get(literal_slot)->cast<Object>(),
                              isolate);
  Handle<Object> boilerplate;
  if (!HasBoilerplate(literal_site)) {
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
        isolate, boilerplate,
        JSRegExp::New(isolate, pattern, JSRegExp::Flags(flags)));
    if (IsUninitializedLiteralSite(*literal_site)) {
      PreInitializeLiteralSite(vector, literal_slot);
      return *boilerplate;
    }
    vector->Set(literal_slot, *boilerplate);
  }
  return *JSRegExp::Copy(Handle<JSRegExp>::cast(boilerplate));
}

}  // namespace internal
}  // namespace v8
