• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/allocation-site-scopes.h"
6 #include "src/arguments-inl.h"
7 #include "src/ast/ast.h"
8 #include "src/isolate-inl.h"
9 #include "src/objects/hash-table-inl.h"
10 #include "src/objects/js-regexp-inl.h"
11 #include "src/objects/literal-objects-inl.h"
12 #include "src/runtime/runtime-utils.h"
13 #include "src/runtime/runtime.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 namespace {
19 
IsUninitializedLiteralSite(Object * literal_site)20 bool IsUninitializedLiteralSite(Object* literal_site) {
21   return literal_site == Smi::kZero;
22 }
23 
HasBoilerplate(Handle<Object> literal_site)24 bool HasBoilerplate(Handle<Object> literal_site) {
25   return !literal_site->IsSmi();
26 }
27 
PreInitializeLiteralSite(Handle<FeedbackVector> vector,FeedbackSlot slot)28 void PreInitializeLiteralSite(Handle<FeedbackVector> vector,
29                               FeedbackSlot slot) {
30   vector->Set(slot, Smi::FromInt(1));
31 }
32 
33 Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
34                                       Handle<Object> description,
35                                       PretenureFlag pretenure_flag);
36 
37 enum DeepCopyHints { kNoHints = 0, kObjectIsShallow = 1 };
38 
39 template <class ContextObject>
40 class JSObjectWalkVisitor {
41  public:
JSObjectWalkVisitor(ContextObject * site_context,DeepCopyHints hints)42   JSObjectWalkVisitor(ContextObject* site_context, DeepCopyHints hints)
43       : site_context_(site_context), hints_(hints) {}
44 
45   V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> StructureWalk(
46       Handle<JSObject> object);
47 
48  protected:
VisitElementOrProperty(Handle<JSObject> object,Handle<JSObject> value)49   V8_WARN_UNUSED_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
50       Handle<JSObject> object, Handle<JSObject> value) {
51     // Dont create allocation sites for nested object literals
52     if (!value->IsJSArray()) {
53       return StructureWalk(value);
54     }
55 
56     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
57     MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
58     site_context()->ExitScope(current_site, value);
59     return copy_of_value;
60   }
61 
site_context()62   inline ContextObject* site_context() { return site_context_; }
isolate()63   inline Isolate* isolate() { return site_context()->isolate(); }
64 
65  private:
66   ContextObject* site_context_;
67   const DeepCopyHints hints_;
68 };
69 
70 template <class ContextObject>
StructureWalk(Handle<JSObject> object)71 MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
72     Handle<JSObject> object) {
73   Isolate* isolate = this->isolate();
74   bool copying = ContextObject::kCopying;
75   bool shallow = hints_ == kObjectIsShallow;
76 
77   if (!shallow) {
78     StackLimitCheck check(isolate);
79 
80     if (check.HasOverflowed()) {
81       isolate->StackOverflow();
82       return MaybeHandle<JSObject>();
83     }
84   }
85 
86   if (object->map()->is_deprecated()) {
87     JSObject::MigrateInstance(object);
88   }
89 
90   Handle<JSObject> copy;
91   if (copying) {
92     // JSFunction objects are not allowed to be in normal boilerplates at all.
93     DCHECK(!object->IsJSFunction());
94     Handle<AllocationSite> site_to_pass;
95     if (site_context()->ShouldCreateMemento(object)) {
96       site_to_pass = site_context()->current();
97     }
98     copy = isolate->factory()->CopyJSObjectWithAllocationSite(object,
99                                                               site_to_pass);
100   } else {
101     copy = object;
102   }
103 
104   DCHECK(copying || copy.is_identical_to(object));
105 
106   if (shallow) return copy;
107 
108   HandleScope scope(isolate);
109 
110   // Deep copy own properties. Arrays only have 1 property "length".
111   if (!copy->IsJSArray()) {
112     if (copy->HasFastProperties()) {
113       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors(),
114                                           isolate);
115       int limit = copy->map()->NumberOfOwnDescriptors();
116       for (int i = 0; i < limit; i++) {
117         DCHECK_EQ(kField, descriptors->GetDetails(i).location());
118         DCHECK_EQ(kData, descriptors->GetDetails(i).kind());
119         FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
120         if (copy->IsUnboxedDoubleField(index)) continue;
121         Object* raw = copy->RawFastPropertyAt(index);
122         if (raw->IsJSObject()) {
123           Handle<JSObject> value(JSObject::cast(raw), isolate);
124           ASSIGN_RETURN_ON_EXCEPTION(
125               isolate, value, VisitElementOrProperty(copy, value), JSObject);
126           if (copying) copy->FastPropertyAtPut(index, *value);
127         } else if (copying && raw->IsMutableHeapNumber()) {
128           DCHECK(descriptors->GetDetails(i).representation().IsDouble());
129           uint64_t double_value = MutableHeapNumber::cast(raw)->value_as_bits();
130           auto value =
131               isolate->factory()->NewMutableHeapNumberFromBits(double_value);
132           copy->FastPropertyAtPut(index, *value);
133         }
134       }
135     } else {
136       Handle<NameDictionary> dict(copy->property_dictionary(), isolate);
137       for (int i = 0; i < dict->Capacity(); i++) {
138         Object* raw = dict->ValueAt(i);
139         if (!raw->IsJSObject()) continue;
140         DCHECK(dict->KeyAt(i)->IsName());
141         Handle<JSObject> value(JSObject::cast(raw), isolate);
142         ASSIGN_RETURN_ON_EXCEPTION(
143             isolate, value, VisitElementOrProperty(copy, value), JSObject);
144         if (copying) dict->ValueAtPut(i, *value);
145       }
146     }
147 
148     // Assume non-arrays don't end up having elements.
149     if (copy->elements()->length() == 0) return copy;
150   }
151 
152   // Deep copy own elements.
153   switch (copy->GetElementsKind()) {
154     case PACKED_ELEMENTS:
155     case HOLEY_ELEMENTS: {
156       Handle<FixedArray> elements(FixedArray::cast(copy->elements()), isolate);
157       if (elements->map() == ReadOnlyRoots(isolate).fixed_cow_array_map()) {
158 #ifdef DEBUG
159         for (int i = 0; i < elements->length(); i++) {
160           DCHECK(!elements->get(i)->IsJSObject());
161         }
162 #endif
163       } else {
164         for (int i = 0; i < elements->length(); i++) {
165           Object* raw = elements->get(i);
166           if (!raw->IsJSObject()) continue;
167           Handle<JSObject> value(JSObject::cast(raw), isolate);
168           ASSIGN_RETURN_ON_EXCEPTION(
169               isolate, value, VisitElementOrProperty(copy, value), JSObject);
170           if (copying) elements->set(i, *value);
171         }
172       }
173       break;
174     }
175     case DICTIONARY_ELEMENTS: {
176       Handle<NumberDictionary> element_dictionary(copy->element_dictionary(),
177                                                   isolate);
178       int capacity = element_dictionary->Capacity();
179       for (int i = 0; i < capacity; i++) {
180         Object* raw = element_dictionary->ValueAt(i);
181         if (!raw->IsJSObject()) continue;
182         Handle<JSObject> value(JSObject::cast(raw), isolate);
183         ASSIGN_RETURN_ON_EXCEPTION(
184             isolate, value, VisitElementOrProperty(copy, value), JSObject);
185         if (copying) element_dictionary->ValueAtPut(i, *value);
186       }
187       break;
188     }
189     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
190     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
191       UNIMPLEMENTED();
192       break;
193     case FAST_STRING_WRAPPER_ELEMENTS:
194     case SLOW_STRING_WRAPPER_ELEMENTS:
195       UNREACHABLE();
196       break;
197 
198 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
199 
200       TYPED_ARRAYS(TYPED_ARRAY_CASE)
201 #undef TYPED_ARRAY_CASE
202       // Typed elements cannot be created using an object literal.
203       UNREACHABLE();
204       break;
205 
206     case PACKED_SMI_ELEMENTS:
207     case HOLEY_SMI_ELEMENTS:
208     case PACKED_DOUBLE_ELEMENTS:
209     case HOLEY_DOUBLE_ELEMENTS:
210     case NO_ELEMENTS:
211       // No contained objects, nothing to do.
212       break;
213   }
214 
215   return copy;
216 }
217 
218 class DeprecationUpdateContext {
219  public:
DeprecationUpdateContext(Isolate * isolate)220   explicit DeprecationUpdateContext(Isolate* isolate) { isolate_ = isolate; }
isolate()221   Isolate* isolate() { return isolate_; }
ShouldCreateMemento(Handle<JSObject> object)222   bool ShouldCreateMemento(Handle<JSObject> object) { return false; }
ExitScope(Handle<AllocationSite> scope_site,Handle<JSObject> object)223   inline void ExitScope(Handle<AllocationSite> scope_site,
224                         Handle<JSObject> object) {}
EnterNewScope()225   Handle<AllocationSite> EnterNewScope() { return Handle<AllocationSite>(); }
current()226   Handle<AllocationSite> current() {
227     UNREACHABLE();
228     return Handle<AllocationSite>();
229   }
230 
231   static const bool kCopying = false;
232 
233  private:
234   Isolate* isolate_;
235 };
236 
237 // AllocationSiteCreationContext aids in the creation of AllocationSites to
238 // accompany object literals.
239 class AllocationSiteCreationContext : public AllocationSiteContext {
240  public:
AllocationSiteCreationContext(Isolate * isolate)241   explicit AllocationSiteCreationContext(Isolate* isolate)
242       : AllocationSiteContext(isolate) {}
243 
EnterNewScope()244   Handle<AllocationSite> EnterNewScope() {
245     Handle<AllocationSite> scope_site;
246     if (top().is_null()) {
247       // We are creating the top level AllocationSite as opposed to a nested
248       // AllocationSite.
249       InitializeTraversal(isolate()->factory()->NewAllocationSite(true));
250       scope_site = Handle<AllocationSite>(*top(), isolate());
251       if (FLAG_trace_creation_allocation_sites) {
252         PrintF("*** Creating top level %s AllocationSite %p\n", "Fat",
253                static_cast<void*>(*scope_site));
254       }
255     } else {
256       DCHECK(!current().is_null());
257       scope_site = isolate()->factory()->NewAllocationSite(false);
258       if (FLAG_trace_creation_allocation_sites) {
259         PrintF(
260             "*** Creating nested %s AllocationSite (top, current, new) (%p, "
261             "%p, "
262             "%p)\n",
263             "Slim", static_cast<void*>(*top()), static_cast<void*>(*current()),
264             static_cast<void*>(*scope_site));
265       }
266       current()->set_nested_site(*scope_site);
267       update_current_site(*scope_site);
268     }
269     DCHECK(!scope_site.is_null());
270     return scope_site;
271   }
ExitScope(Handle<AllocationSite> scope_site,Handle<JSObject> object)272   void ExitScope(Handle<AllocationSite> scope_site, Handle<JSObject> object) {
273     if (object.is_null()) return;
274     scope_site->set_boilerplate(*object);
275     if (FLAG_trace_creation_allocation_sites) {
276       bool top_level =
277           !scope_site.is_null() && top().is_identical_to(scope_site);
278       if (top_level) {
279         PrintF("*** Setting AllocationSite %p transition_info %p\n",
280                static_cast<void*>(*scope_site), static_cast<void*>(*object));
281       } else {
282         PrintF("*** Setting AllocationSite (%p, %p) transition_info %p\n",
283                static_cast<void*>(*top()), static_cast<void*>(*scope_site),
284                static_cast<void*>(*object));
285       }
286     }
287   }
288   static const bool kCopying = false;
289 };
290 
DeepWalk(Handle<JSObject> object,DeprecationUpdateContext * site_context)291 MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
292                                DeprecationUpdateContext* site_context) {
293   JSObjectWalkVisitor<DeprecationUpdateContext> v(site_context, kNoHints);
294   MaybeHandle<JSObject> result = v.StructureWalk(object);
295   Handle<JSObject> for_assert;
296   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
297   return result;
298 }
299 
DeepWalk(Handle<JSObject> object,AllocationSiteCreationContext * site_context)300 MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
301                                AllocationSiteCreationContext* site_context) {
302   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, kNoHints);
303   MaybeHandle<JSObject> result = v.StructureWalk(object);
304   Handle<JSObject> for_assert;
305   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
306   return result;
307 }
308 
DeepCopy(Handle<JSObject> object,AllocationSiteUsageContext * site_context,DeepCopyHints hints)309 MaybeHandle<JSObject> DeepCopy(Handle<JSObject> object,
310                                AllocationSiteUsageContext* site_context,
311                                DeepCopyHints hints) {
312   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, hints);
313   MaybeHandle<JSObject> copy = v.StructureWalk(object);
314   Handle<JSObject> for_assert;
315   DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
316   return copy;
317 }
318 
319 struct ObjectLiteralHelper {
Createv8::internal::__anond0b108660111::ObjectLiteralHelper320   static Handle<JSObject> Create(Isolate* isolate,
321                                  Handle<HeapObject> description, int flags,
322                                  PretenureFlag pretenure_flag) {
323     Handle<NativeContext> native_context = isolate->native_context();
324     Handle<ObjectBoilerplateDescription> object_boilerplate_description =
325         Handle<ObjectBoilerplateDescription>::cast(description);
326     bool use_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
327     bool has_null_prototype = (flags & ObjectLiteral::kHasNullPrototype) != 0;
328 
329     // In case we have function literals, we want the object to be in
330     // slow properties mode for now. We don't go in the map cache because
331     // maps with constant functions can't be shared if the functions are
332     // not the same (which is the common case).
333     int number_of_properties =
334         object_boilerplate_description->backing_store_size();
335 
336     // Ignoring number_of_properties for force dictionary map with
337     // __proto__:null.
338     Handle<Map> map =
339         has_null_prototype
340             ? handle(native_context->slow_object_with_null_prototype_map(),
341                      isolate)
342             : isolate->factory()->ObjectLiteralMapFromCache(
343                   native_context, number_of_properties);
344 
345     Handle<JSObject> boilerplate =
346         map->is_dictionary_map()
347             ? isolate->factory()->NewSlowJSObjectFromMap(
348                   map, number_of_properties, pretenure_flag)
349             : isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);
350 
351     // Normalize the elements of the boilerplate to save space if needed.
352     if (!use_fast_elements) JSObject::NormalizeElements(boilerplate);
353 
354     // Add the constant properties to the boilerplate.
355     int length = object_boilerplate_description->size();
356     // TODO(verwaest): Support tracking representations in the boilerplate.
357     for (int index = 0; index < length; index++) {
358       Handle<Object> key(object_boilerplate_description->name(index), isolate);
359       Handle<Object> value(object_boilerplate_description->value(index),
360                            isolate);
361 
362       if (value->IsObjectBoilerplateDescription() ||
363           value->IsArrayBoilerplateDescription()) {
364         value = InnerCreateBoilerplate(isolate, value, pretenure_flag);
365       }
366       uint32_t element_index = 0;
367       if (key->ToArrayIndex(&element_index)) {
368         // Array index (uint32).
369         if (value->IsUninitialized(isolate)) {
370           value = handle(Smi::kZero, isolate);
371         }
372         JSObject::SetOwnElementIgnoreAttributes(boilerplate, element_index,
373                                                 value, NONE)
374             .Check();
375       } else {
376         Handle<String> name = Handle<String>::cast(key);
377         DCHECK(!name->AsArrayIndex(&element_index));
378         JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name, value, NONE)
379             .Check();
380       }
381     }
382 
383     if (map->is_dictionary_map() && !has_null_prototype) {
384       // TODO(cbruni): avoid making the boilerplate fast again, the clone stub
385       // supports dict-mode objects directly.
386       JSObject::MigrateSlowToFast(boilerplate,
387                                   boilerplate->map()->UnusedPropertyFields(),
388                                   "FastLiteral");
389     }
390     return boilerplate;
391   }
392 };
393 
394 struct ArrayLiteralHelper {
Createv8::internal::__anond0b108660111::ArrayLiteralHelper395   static Handle<JSObject> Create(Isolate* isolate,
396                                  Handle<HeapObject> description, int flags,
397                                  PretenureFlag pretenure_flag) {
398     Handle<ArrayBoilerplateDescription> array_boilerplate_description =
399         Handle<ArrayBoilerplateDescription>::cast(description);
400 
401     ElementsKind constant_elements_kind =
402         array_boilerplate_description->elements_kind();
403 
404     Handle<FixedArrayBase> constant_elements_values(
405         array_boilerplate_description->constant_elements(), isolate);
406 
407     // Create the JSArray.
408     Handle<FixedArrayBase> copied_elements_values;
409     if (IsDoubleElementsKind(constant_elements_kind)) {
410       copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
411           Handle<FixedDoubleArray>::cast(constant_elements_values));
412     } else {
413       DCHECK(IsSmiOrObjectElementsKind(constant_elements_kind));
414       const bool is_cow = (constant_elements_values->map() ==
415                            ReadOnlyRoots(isolate).fixed_cow_array_map());
416       if (is_cow) {
417         copied_elements_values = constant_elements_values;
418 #if DEBUG
419         Handle<FixedArray> fixed_array_values =
420             Handle<FixedArray>::cast(copied_elements_values);
421         for (int i = 0; i < fixed_array_values->length(); i++) {
422           DCHECK(!fixed_array_values->get(i)->IsFixedArray());
423         }
424 #endif
425       } else {
426         Handle<FixedArray> fixed_array_values =
427             Handle<FixedArray>::cast(constant_elements_values);
428         Handle<FixedArray> fixed_array_values_copy =
429             isolate->factory()->CopyFixedArray(fixed_array_values);
430         copied_elements_values = fixed_array_values_copy;
431         FOR_WITH_HANDLE_SCOPE(
432             isolate, int, i = 0, i, i < fixed_array_values->length(), i++, {
433               Handle<Object> value(fixed_array_values->get(i), isolate);
434 
435               if (value->IsArrayBoilerplateDescription() ||
436                   value->IsObjectBoilerplateDescription()) {
437                 Handle<Object> result =
438                     InnerCreateBoilerplate(isolate, value, pretenure_flag);
439                 fixed_array_values_copy->set(i, *result);
440               }
441             });
442       }
443     }
444 
445     return isolate->factory()->NewJSArrayWithElements(
446         copied_elements_values, constant_elements_kind,
447         copied_elements_values->length(), pretenure_flag);
448   }
449 };
450 
InnerCreateBoilerplate(Isolate * isolate,Handle<Object> description,PretenureFlag pretenure_flag)451 Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
452                                       Handle<Object> description,
453                                       PretenureFlag pretenure_flag) {
454   if (description->IsObjectBoilerplateDescription()) {
455     Handle<ObjectBoilerplateDescription> object_boilerplate_description =
456         Handle<ObjectBoilerplateDescription>::cast(description);
457     return ObjectLiteralHelper::Create(isolate, object_boilerplate_description,
458                                        object_boilerplate_description->flags(),
459                                        pretenure_flag);
460   } else {
461     DCHECK(description->IsArrayBoilerplateDescription());
462     Handle<ArrayBoilerplateDescription> array_boilerplate_description =
463         Handle<ArrayBoilerplateDescription>::cast(description);
464     return ArrayLiteralHelper::Create(
465         isolate, array_boilerplate_description,
466         array_boilerplate_description->elements_kind(), pretenure_flag);
467   }
468 }
469 
DecodeCopyHints(int flags)470 inline DeepCopyHints DecodeCopyHints(int flags) {
471   DeepCopyHints copy_hints =
472       (flags & AggregateLiteral::kIsShallow) ? kObjectIsShallow : kNoHints;
473   if (FLAG_track_double_fields && !FLAG_unbox_double_fields) {
474     // Make sure we properly clone mutable heap numbers on 32-bit platforms.
475     copy_hints = kNoHints;
476   }
477   return copy_hints;
478 }
479 
480 template <typename LiteralHelper>
CreateLiteralWithoutAllocationSite(Isolate * isolate,Handle<HeapObject> description,int flags)481 MaybeHandle<JSObject> CreateLiteralWithoutAllocationSite(
482     Isolate* isolate, Handle<HeapObject> description, int flags) {
483   Handle<JSObject> literal =
484       LiteralHelper::Create(isolate, description, flags, NOT_TENURED);
485   DeepCopyHints copy_hints = DecodeCopyHints(flags);
486   if (copy_hints == kNoHints) {
487     DeprecationUpdateContext update_context(isolate);
488     RETURN_ON_EXCEPTION(isolate, DeepWalk(literal, &update_context), JSObject);
489   }
490   return literal;
491 }
492 
493 template <typename LiteralHelper>
CreateLiteral(Isolate * isolate,Handle<FeedbackVector> vector,int literals_index,Handle<HeapObject> description,int flags)494 MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
495                                     Handle<FeedbackVector> vector,
496                                     int literals_index,
497                                     Handle<HeapObject> description, int flags) {
498   FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
499   CHECK(literals_slot.ToInt() < vector->length());
500   Handle<Object> literal_site(vector->Get(literals_slot)->ToObject(), isolate);
501   DeepCopyHints copy_hints = DecodeCopyHints(flags);
502 
503   Handle<AllocationSite> site;
504   Handle<JSObject> boilerplate;
505 
506   if (HasBoilerplate(literal_site)) {
507     site = Handle<AllocationSite>::cast(literal_site);
508     boilerplate = Handle<JSObject>(site->boilerplate(), isolate);
509   } else {
510     // Eagerly create AllocationSites for literals that contain an Array.
511     bool needs_initial_allocation_site =
512         (flags & AggregateLiteral::kNeedsInitialAllocationSite) != 0;
513     if (!needs_initial_allocation_site &&
514         IsUninitializedLiteralSite(*literal_site)) {
515       PreInitializeLiteralSite(vector, literals_slot);
516       return CreateLiteralWithoutAllocationSite<LiteralHelper>(
517           isolate, description, flags);
518     } else {
519       boilerplate = LiteralHelper::Create(isolate, description, flags, TENURED);
520     }
521     // Install AllocationSite objects.
522     AllocationSiteCreationContext creation_context(isolate);
523     site = creation_context.EnterNewScope();
524     RETURN_ON_EXCEPTION(isolate, DeepWalk(boilerplate, &creation_context),
525                         JSObject);
526     creation_context.ExitScope(site, boilerplate);
527 
528     vector->Set(literals_slot, *site);
529   }
530 
531   STATIC_ASSERT(static_cast<int>(ObjectLiteral::kDisableMementos) ==
532                 static_cast<int>(ArrayLiteral::kDisableMementos));
533   bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0;
534 
535   // Copy the existing boilerplate.
536   AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
537   usage_context.EnterNewScope();
538   MaybeHandle<JSObject> copy =
539       DeepCopy(boilerplate, &usage_context, copy_hints);
540   usage_context.ExitScope(site, boilerplate);
541   return copy;
542 }
543 }  // namespace
544 
RUNTIME_FUNCTION(Runtime_CreateObjectLiteral)545 RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
546   HandleScope scope(isolate);
547   DCHECK_EQ(4, args.length());
548   CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
549   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
550   CONVERT_ARG_HANDLE_CHECKED(ObjectBoilerplateDescription, description, 2);
551   CONVERT_SMI_ARG_CHECKED(flags, 3);
552   RETURN_RESULT_OR_FAILURE(
553       isolate, CreateLiteral<ObjectLiteralHelper>(
554                    isolate, vector, literals_index, description, flags));
555 }
556 
RUNTIME_FUNCTION(Runtime_CreateObjectLiteralWithoutAllocationSite)557 RUNTIME_FUNCTION(Runtime_CreateObjectLiteralWithoutAllocationSite) {
558   HandleScope scope(isolate);
559   DCHECK_EQ(2, args.length());
560   CONVERT_ARG_HANDLE_CHECKED(ObjectBoilerplateDescription, description, 0);
561   CONVERT_SMI_ARG_CHECKED(flags, 1);
562   RETURN_RESULT_OR_FAILURE(
563       isolate, CreateLiteralWithoutAllocationSite<ObjectLiteralHelper>(
564                    isolate, description, flags));
565 }
566 
RUNTIME_FUNCTION(Runtime_CreateArrayLiteralWithoutAllocationSite)567 RUNTIME_FUNCTION(Runtime_CreateArrayLiteralWithoutAllocationSite) {
568   HandleScope scope(isolate);
569   DCHECK_EQ(2, args.length());
570   CONVERT_ARG_HANDLE_CHECKED(ArrayBoilerplateDescription, description, 0);
571   CONVERT_SMI_ARG_CHECKED(flags, 1);
572   RETURN_RESULT_OR_FAILURE(
573       isolate, CreateLiteralWithoutAllocationSite<ArrayLiteralHelper>(
574                    isolate, description, flags));
575 }
576 
RUNTIME_FUNCTION(Runtime_CreateArrayLiteral)577 RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
578   HandleScope scope(isolate);
579   DCHECK_EQ(4, args.length());
580   CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
581   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
582   CONVERT_ARG_HANDLE_CHECKED(ArrayBoilerplateDescription, elements, 2);
583   CONVERT_SMI_ARG_CHECKED(flags, 3);
584   RETURN_RESULT_OR_FAILURE(
585       isolate, CreateLiteral<ArrayLiteralHelper>(
586                    isolate, vector, literals_index, elements, flags));
587 }
588 
RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral)589 RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) {
590   HandleScope scope(isolate);
591   DCHECK_EQ(4, args.length());
592   CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
593   CONVERT_SMI_ARG_CHECKED(index, 1);
594   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
595   CONVERT_SMI_ARG_CHECKED(flags, 3);
596 
597   FeedbackSlot literal_slot(FeedbackVector::ToSlot(index));
598 
599   // Check if boilerplate exists. If not, create it first.
600   Handle<Object> literal_site(vector->Get(literal_slot)->ToObject(), isolate);
601   Handle<Object> boilerplate;
602   if (!HasBoilerplate(literal_site)) {
603     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
604         isolate, boilerplate,
605         JSRegExp::New(isolate, pattern, JSRegExp::Flags(flags)));
606     if (IsUninitializedLiteralSite(*literal_site)) {
607       PreInitializeLiteralSite(vector, literal_slot);
608       return *boilerplate;
609     }
610     vector->Set(literal_slot, *boilerplate);
611   }
612   return *JSRegExp::Copy(Handle<JSRegExp>::cast(boilerplate));
613 }
614 
615 }  // namespace internal
616 }  // namespace v8
617