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