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