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