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