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 : bool IsUninitializedLiteralSite(Object literal_site) {
24 : return literal_site == Smi::kZero;
25 : }
26 :
27 : bool HasBoilerplate(Handle<Object> literal_site) {
28 : return !literal_site->IsSmi();
29 : }
30 :
31 : void PreInitializeLiteralSite(Handle<FeedbackVector> vector,
32 : FeedbackSlot slot) {
33 292427 : vector->Set(slot, Smi::FromInt(1));
34 : }
35 :
36 : Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
37 : Handle<Object> description,
38 : AllocationType allocation);
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 846526 : : site_context_(site_context), hints_(hints) {}
47 :
48 : V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> StructureWalk(
49 : Handle<JSObject> object);
50 :
51 : protected:
52 977750 : V8_WARN_UNUSED_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
53 : Handle<JSObject> object, Handle<JSObject> value) {
54 : // Dont create allocation sites for nested object literals
55 977750 : if (!value->IsJSArray()) {
56 319050 : return StructureWalk(value);
57 : }
58 :
59 632374 : Handle<AllocationSite> current_site = site_context()->EnterNewScope();
60 658700 : MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
61 : site_context()->ExitScope(current_site, value);
62 658700 : return copy_of_value;
63 : }
64 :
65 : inline ContextObject* site_context() { return site_context_; }
66 : 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 1824274 : MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
75 : Handle<JSObject> object) {
76 : Isolate* isolate = this->isolate();
77 : bool copying = ContextObject::kCopying;
78 1824274 : bool shallow = hints_ == kObjectIsShallow;
79 :
80 1824274 : if (!shallow) {
81 : StackLimitCheck check(isolate);
82 :
83 1722722 : if (check.HasOverflowed()) {
84 38 : isolate->StackOverflow();
85 38 : return MaybeHandle<JSObject>();
86 : }
87 : }
88 :
89 1824234 : if (object->map()->is_deprecated()) {
90 108 : 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 1623524 : if (site_context()->ShouldCreateMemento(object)) {
99 1499640 : site_to_pass = site_context()->current();
100 : }
101 1623524 : 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 1824237 : if (shallow) return copy;
110 :
111 : HandleScope scope(isolate);
112 :
113 : // Deep copy own properties. Arrays only have 1 property "length".
114 1722682 : if (!copy->IsJSArray()) {
115 662328 : if (copy->HasFastProperties()) {
116 : Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors(),
117 : isolate);
118 : int limit = copy->map()->NumberOfOwnDescriptors();
119 2136282 : for (int i = 0; i < limit; i++) {
120 : DCHECK_EQ(kField, descriptors->GetDetails(i).location());
121 : DCHECK_EQ(kData, descriptors->GetDetails(i).kind());
122 737086 : FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
123 742119 : if (copy->IsUnboxedDoubleField(index)) continue;
124 732053 : Object raw = copy->RawFastPropertyAt(index);
125 732053 : if (raw->IsJSObject()) {
126 : Handle<JSObject> value(JSObject::cast(raw), isolate);
127 716990 : ASSIGN_RETURN_ON_EXCEPTION(
128 : isolate, value, VisitElementOrProperty(copy, value), JSObject);
129 648434 : if (copying) copy->FastPropertyAtPut(index, *value);
130 132293 : } 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 : 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 1476234 : for (int i = 0; i < dict->Capacity(); i++) {
141 : Object raw = dict->ValueAt(i);
142 1475816 : 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 662320 : if (copy->elements()->length() == 0) return copy;
153 : }
154 :
155 : // Deep copy own elements.
156 1061732 : switch (copy->GetElementsKind()) {
157 : case PACKED_ELEMENTS:
158 : case PACKED_FROZEN_ELEMENTS:
159 : case PACKED_SEALED_ELEMENTS:
160 : case HOLEY_ELEMENTS: {
161 : Handle<FixedArray> elements(FixedArray::cast(copy->elements()), isolate);
162 471407 : if (elements->map() == ReadOnlyRoots(isolate).fixed_cow_array_map()) {
163 : #ifdef DEBUG
164 : for (int i = 0; i < elements->length(); i++) {
165 : DCHECK(!elements->get(i)->IsJSObject());
166 : }
167 : #endif
168 : } else {
169 6841307 : for (int i = 0; i < elements->length(); i++) {
170 : Object raw = elements->get(i);
171 4785705 : if (!raw->IsJSObject()) continue;
172 : Handle<JSObject> value(JSObject::cast(raw), isolate);
173 1237610 : ASSIGN_RETURN_ON_EXCEPTION(
174 : isolate, value, VisitElementOrProperty(copy, value), JSObject);
175 1154468 : if (copying) elements->set(i, *value);
176 : }
177 : }
178 : break;
179 : }
180 : case DICTIONARY_ELEMENTS: {
181 : Handle<NumberDictionary> element_dictionary(copy->element_dictionary(),
182 : isolate);
183 : int capacity = element_dictionary->Capacity();
184 13251 : for (int i = 0; i < capacity; i++) {
185 : Object raw = element_dictionary->ValueAt(i);
186 12125 : if (!raw->IsJSObject()) continue;
187 : Handle<JSObject> value(JSObject::cast(raw), isolate);
188 900 : ASSIGN_RETURN_ON_EXCEPTION(
189 : isolate, value, VisitElementOrProperty(copy, value), JSObject);
190 558 : if (copying) element_dictionary->ValueAtPut(i, *value);
191 : }
192 : break;
193 : }
194 : case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
195 : case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
196 0 : UNIMPLEMENTED();
197 : break;
198 : case FAST_STRING_WRAPPER_ELEMENTS:
199 : case SLOW_STRING_WRAPPER_ELEMENTS:
200 0 : UNREACHABLE();
201 : break;
202 :
203 : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
204 :
205 : TYPED_ARRAYS(TYPED_ARRAY_CASE)
206 : #undef TYPED_ARRAY_CASE
207 : // Typed elements cannot be created using an object literal.
208 0 : UNREACHABLE();
209 : break;
210 :
211 : case PACKED_SMI_ELEMENTS:
212 : case HOLEY_SMI_ELEMENTS:
213 : case PACKED_DOUBLE_ELEMENTS:
214 : case HOLEY_DOUBLE_ELEMENTS:
215 : case NO_ELEMENTS:
216 : // No contained objects, nothing to do.
217 : break;
218 : }
219 :
220 1061715 : return copy;
221 : }
222 :
223 : class DeprecationUpdateContext {
224 : public:
225 28359 : explicit DeprecationUpdateContext(Isolate* isolate) { isolate_ = isolate; }
226 84551 : Isolate* isolate() { return isolate_; }
227 : bool ShouldCreateMemento(Handle<JSObject> object) { return false; }
228 : inline void ExitScope(Handle<AllocationSite> scope_site,
229 : Handle<JSObject> object) {}
230 : Handle<AllocationSite> EnterNewScope() { return Handle<AllocationSite>(); }
231 : Handle<AllocationSite> current() {
232 : UNREACHABLE();
233 : return Handle<AllocationSite>();
234 : }
235 :
236 : static const bool kCopying = false;
237 :
238 : private:
239 : Isolate* isolate_;
240 : };
241 :
242 : // AllocationSiteCreationContext aids in the creation of AllocationSites to
243 : // accompany object literals.
244 : class AllocationSiteCreationContext : public AllocationSiteContext {
245 : public:
246 : explicit AllocationSiteCreationContext(Isolate* isolate)
247 : : AllocationSiteContext(isolate) {}
248 :
249 112099 : Handle<AllocationSite> EnterNewScope() {
250 : Handle<AllocationSite> scope_site;
251 112099 : if (top().is_null()) {
252 : // We are creating the top level AllocationSite as opposed to a nested
253 : // AllocationSite.
254 96375 : InitializeTraversal(isolate()->factory()->NewAllocationSite(true));
255 : scope_site = Handle<AllocationSite>(*top(), isolate());
256 : if (FLAG_trace_creation_allocation_sites) {
257 : PrintF("*** Creating top level %s AllocationSite %p\n", "Fat",
258 : reinterpret_cast<void*>(scope_site->ptr()));
259 : }
260 : } else {
261 : DCHECK(!current().is_null());
262 15724 : scope_site = isolate()->factory()->NewAllocationSite(false);
263 : if (FLAG_trace_creation_allocation_sites) {
264 : PrintF(
265 : "*** Creating nested %s AllocationSite (top, current, new) (%p, "
266 : "%p, "
267 : "%p)\n",
268 : "Slim", reinterpret_cast<void*>(top()->ptr()),
269 : reinterpret_cast<void*>(current()->ptr()),
270 : reinterpret_cast<void*>(scope_site->ptr()));
271 : }
272 31448 : current()->set_nested_site(*scope_site);
273 : update_current_site(*scope_site);
274 : }
275 : DCHECK(!scope_site.is_null());
276 112103 : return scope_site;
277 : }
278 : void ExitScope(Handle<AllocationSite> scope_site, Handle<JSObject> object) {
279 112078 : if (object.is_null()) return;
280 224160 : scope_site->set_boilerplate(*object);
281 : if (FLAG_trace_creation_allocation_sites) {
282 : bool top_level =
283 : !scope_site.is_null() && top().is_identical_to(scope_site);
284 : if (top_level) {
285 : PrintF("*** Setting AllocationSite %p transition_info %p\n",
286 : reinterpret_cast<void*>(scope_site->ptr()),
287 : reinterpret_cast<void*>(object->ptr()));
288 : } else {
289 : PrintF("*** Setting AllocationSite (%p, %p) transition_info %p\n",
290 : reinterpret_cast<void*>(top()->ptr()),
291 : reinterpret_cast<void*>(scope_site->ptr()),
292 : reinterpret_cast<void*>(object->ptr()));
293 : }
294 : }
295 : }
296 : static const bool kCopying = false;
297 : };
298 :
299 : MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
300 : DeprecationUpdateContext* site_context) {
301 : JSObjectWalkVisitor<DeprecationUpdateContext> v(site_context, kNoHints);
302 28359 : MaybeHandle<JSObject> result = v.StructureWalk(object);
303 : Handle<JSObject> for_assert;
304 : DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
305 28359 : return result;
306 : }
307 :
308 : MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
309 : AllocationSiteCreationContext* site_context) {
310 : JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, kNoHints);
311 96379 : MaybeHandle<JSObject> result = v.StructureWalk(object);
312 : Handle<JSObject> for_assert;
313 : DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
314 96376 : return result;
315 : }
316 :
317 : MaybeHandle<JSObject> DeepCopy(Handle<JSObject> object,
318 : AllocationSiteUsageContext* site_context,
319 : DeepCopyHints hints) {
320 : JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, hints);
321 721788 : MaybeHandle<JSObject> copy = v.StructureWalk(object);
322 : Handle<JSObject> for_assert;
323 : DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
324 721789 : return copy;
325 : }
326 :
327 : struct ObjectLiteralHelper {
328 365030 : static Handle<JSObject> Create(Isolate* isolate,
329 : Handle<HeapObject> description, int flags,
330 : AllocationType allocation) {
331 365030 : Handle<NativeContext> native_context = isolate->native_context();
332 : Handle<ObjectBoilerplateDescription> object_boilerplate_description =
333 : Handle<ObjectBoilerplateDescription>::cast(description);
334 365030 : bool use_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
335 365030 : bool has_null_prototype = (flags & ObjectLiteral::kHasNullPrototype) != 0;
336 :
337 : // In case we have function literals, we want the object to be in
338 : // slow properties mode for now. We don't go in the map cache because
339 : // maps with constant functions can't be shared if the functions are
340 : // not the same (which is the common case).
341 : int number_of_properties =
342 365030 : object_boilerplate_description->backing_store_size();
343 :
344 : // Ignoring number_of_properties for force dictionary map with
345 : // __proto__:null.
346 : Handle<Map> map =
347 : has_null_prototype
348 371228 : ? handle(native_context->slow_object_with_null_prototype_map(),
349 3096 : isolate)
350 : : isolate->factory()->ObjectLiteralMapFromCache(
351 1088914 : native_context, number_of_properties);
352 :
353 : Handle<JSObject> boilerplate =
354 : map->is_dictionary_map()
355 : ? isolate->factory()->NewSlowJSObjectFromMap(
356 : map, number_of_properties, allocation)
357 365036 : : isolate->factory()->NewJSObjectFromMap(map, allocation);
358 :
359 : // Normalize the elements of the boilerplate to save space if needed.
360 365035 : if (!use_fast_elements) JSObject::NormalizeElements(boilerplate);
361 :
362 : // Add the constant properties to the boilerplate.
363 365035 : int length = object_boilerplate_description->size();
364 : // TODO(verwaest): Support tracking representations in the boilerplate.
365 9689087 : for (int index = 0; index < length; index++) {
366 9324048 : Handle<Object> key(object_boilerplate_description->name(index), isolate);
367 : Handle<Object> value(object_boilerplate_description->value(index),
368 9324050 : isolate);
369 :
370 9316455 : if (value->IsObjectBoilerplateDescription() ||
371 : value->IsArrayBoilerplateDescription()) {
372 34605 : value = InnerCreateBoilerplate(isolate, value, allocation);
373 : }
374 4662024 : uint32_t element_index = 0;
375 9324053 : if (key->ToArrayIndex(&element_index)) {
376 : // Array index (uint32).
377 2320055 : if (value->IsUninitialized(isolate)) {
378 : value = handle(Smi::kZero, isolate);
379 : }
380 4640111 : JSObject::SetOwnElementIgnoreAttributes(boilerplate, element_index,
381 2320055 : value, NONE)
382 : .Check();
383 : } else {
384 : Handle<String> name = Handle<String>::cast(key);
385 : DCHECK(!name->AsArrayIndex(&element_index));
386 4683946 : JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name, value, NONE)
387 : .Check();
388 : }
389 : }
390 :
391 365037 : if (map->is_dictionary_map() && !has_null_prototype) {
392 : // TODO(cbruni): avoid making the boilerplate fast again, the clone stub
393 : // supports dict-mode objects directly.
394 191 : JSObject::MigrateSlowToFast(boilerplate,
395 382 : boilerplate->map()->UnusedPropertyFields(),
396 191 : "FastLiteral");
397 : }
398 365037 : return boilerplate;
399 : }
400 : };
401 :
402 : struct ArrayLiteralHelper {
403 462334 : static Handle<JSObject> Create(Isolate* isolate,
404 : Handle<HeapObject> description, int flags,
405 : AllocationType allocation) {
406 : Handle<ArrayBoilerplateDescription> array_boilerplate_description =
407 : Handle<ArrayBoilerplateDescription>::cast(description);
408 :
409 : ElementsKind constant_elements_kind =
410 : array_boilerplate_description->elements_kind();
411 :
412 : Handle<FixedArrayBase> constant_elements_values(
413 : array_boilerplate_description->constant_elements(), isolate);
414 :
415 : // Create the JSArray.
416 : Handle<FixedArrayBase> copied_elements_values;
417 462333 : if (IsDoubleElementsKind(constant_elements_kind)) {
418 : copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
419 14032 : Handle<FixedDoubleArray>::cast(constant_elements_values));
420 : } else {
421 : DCHECK(IsSmiOrObjectElementsKind(constant_elements_kind));
422 : const bool is_cow = (constant_elements_values->map() ==
423 : ReadOnlyRoots(isolate).fixed_cow_array_map());
424 448301 : if (is_cow) {
425 : copied_elements_values = constant_elements_values;
426 : #if DEBUG
427 : Handle<FixedArray> fixed_array_values =
428 : Handle<FixedArray>::cast(copied_elements_values);
429 : for (int i = 0; i < fixed_array_values->length(); i++) {
430 : DCHECK(!fixed_array_values->get(i)->IsFixedArray());
431 : }
432 : #endif
433 : } else {
434 : Handle<FixedArray> fixed_array_values =
435 : Handle<FixedArray>::cast(constant_elements_values);
436 : Handle<FixedArray> fixed_array_values_copy =
437 312816 : isolate->factory()->CopyFixedArray(fixed_array_values);
438 : copied_elements_values = fixed_array_values_copy;
439 6178195 : FOR_WITH_HANDLE_SCOPE(
440 : isolate, int, i = 0, i, i < fixed_array_values->length(), i++, {
441 : Handle<Object> value(fixed_array_values->get(i), isolate);
442 :
443 : if (value->IsArrayBoilerplateDescription() ||
444 : value->IsObjectBoilerplateDescription()) {
445 : Handle<Object> result =
446 : InnerCreateBoilerplate(isolate, value, allocation);
447 : fixed_array_values_copy->set(i, *result);
448 : }
449 : });
450 : }
451 : }
452 :
453 : return isolate->factory()->NewJSArrayWithElements(
454 : copied_elements_values, constant_elements_kind,
455 462337 : copied_elements_values->length(), allocation);
456 : }
457 : };
458 :
459 76005 : Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
460 : Handle<Object> description,
461 : AllocationType allocation) {
462 76005 : if (description->IsObjectBoilerplateDescription()) {
463 : Handle<ObjectBoilerplateDescription> object_boilerplate_description =
464 : Handle<ObjectBoilerplateDescription>::cast(description);
465 : return ObjectLiteralHelper::Create(isolate, object_boilerplate_description,
466 : object_boilerplate_description->flags(),
467 33946 : allocation);
468 : } else {
469 : DCHECK(description->IsArrayBoilerplateDescription());
470 : Handle<ArrayBoilerplateDescription> array_boilerplate_description =
471 : Handle<ArrayBoilerplateDescription>::cast(description);
472 : return ArrayLiteralHelper::Create(
473 : isolate, array_boilerplate_description,
474 42059 : array_boilerplate_description->elements_kind(), allocation);
475 : }
476 : }
477 :
478 : inline DeepCopyHints DecodeCopyHints(int flags) {
479 : DeepCopyHints copy_hints =
480 1462398 : (flags & AggregateLiteral::kIsShallow) ? kObjectIsShallow : kNoHints;
481 : if (FLAG_track_double_fields && !FLAG_unbox_double_fields) {
482 : // Make sure we properly clone mutable heap numbers on 32-bit platforms.
483 : copy_hints = kNoHints;
484 : }
485 : return copy_hints;
486 : }
487 :
488 : template <typename LiteralHelper>
489 654985 : MaybeHandle<JSObject> CreateLiteralWithoutAllocationSite(
490 : Isolate* isolate, Handle<HeapObject> description, int flags) {
491 : Handle<JSObject> literal = LiteralHelper::Create(isolate, description, flags,
492 654985 : AllocationType::kYoung);
493 : DeepCopyHints copy_hints = DecodeCopyHints(flags);
494 654987 : if (copy_hints == kNoHints) {
495 : DeprecationUpdateContext update_context(isolate);
496 28359 : RETURN_ON_EXCEPTION(isolate, DeepWalk(literal, &update_context), JSObject);
497 : }
498 654987 : return literal;
499 : }
500 :
501 : template <typename LiteralHelper>
502 807411 : MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
503 : MaybeHandle<FeedbackVector> maybe_vector,
504 : int literals_index,
505 : Handle<HeapObject> description, int flags) {
506 807411 : if (maybe_vector.is_null()) {
507 : return CreateLiteralWithoutAllocationSite<LiteralHelper>(
508 0 : isolate, description, flags);
509 : }
510 :
511 : Handle<FeedbackVector> vector = maybe_vector.ToHandleChecked();
512 : FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
513 807411 : CHECK(literals_slot.ToInt() < vector->length());
514 : Handle<Object> literal_site(vector->Get(literals_slot)->cast<Object>(),
515 : isolate);
516 : DeepCopyHints copy_hints = DecodeCopyHints(flags);
517 :
518 : Handle<AllocationSite> site;
519 : Handle<JSObject> boilerplate;
520 :
521 807411 : if (HasBoilerplate(literal_site)) {
522 : site = Handle<AllocationSite>::cast(literal_site);
523 : boilerplate = Handle<JSObject>(site->boilerplate(), isolate);
524 : } else {
525 : // Eagerly create AllocationSites for literals that contain an Array.
526 : bool needs_initial_allocation_site =
527 181982 : (flags & AggregateLiteral::kNeedsInitialAllocationSite) != 0;
528 181982 : if (!needs_initial_allocation_site &&
529 : IsUninitializedLiteralSite(*literal_site)) {
530 : PreInitializeLiteralSite(vector, literals_slot);
531 : return CreateLiteralWithoutAllocationSite<LiteralHelper>(
532 171227 : isolate, description, flags);
533 : } else {
534 96379 : boilerplate = LiteralHelper::Create(isolate, description, flags,
535 : AllocationType::kOld);
536 : }
537 : // Install AllocationSite objects.
538 : AllocationSiteCreationContext creation_context(isolate);
539 96375 : site = creation_context.EnterNewScope();
540 96376 : RETURN_ON_EXCEPTION(isolate, DeepWalk(boilerplate, &creation_context),
541 : JSObject);
542 : creation_context.ExitScope(site, boilerplate);
543 :
544 192713 : vector->Set(literals_slot, *site);
545 : }
546 :
547 : STATIC_ASSERT(static_cast<int>(ObjectLiteral::kDisableMementos) ==
548 : static_cast<int>(ArrayLiteral::kDisableMementos));
549 721788 : bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0;
550 :
551 : // Copy the existing boilerplate.
552 : AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
553 721788 : usage_context.EnterNewScope();
554 : MaybeHandle<JSObject> copy =
555 : DeepCopy(boilerplate, &usage_context, copy_hints);
556 : usage_context.ExitScope(site, boilerplate);
557 721789 : return copy;
558 : }
559 : } // namespace
560 :
561 822098 : RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
562 : HandleScope scope(isolate);
563 : DCHECK_EQ(4, args.length());
564 411049 : CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 0);
565 411057 : CONVERT_SMI_ARG_CHECKED(literals_index, 1);
566 411056 : CONVERT_ARG_HANDLE_CHECKED(ObjectBoilerplateDescription, description, 2);
567 411055 : CONVERT_SMI_ARG_CHECKED(flags, 3);
568 : Handle<FeedbackVector> vector = Handle<FeedbackVector>();
569 411055 : if (!maybe_vector->IsUndefined()) {
570 : DCHECK(maybe_vector->IsFeedbackVector());
571 411052 : vector = Handle<FeedbackVector>::cast(maybe_vector);
572 : }
573 822106 : RETURN_RESULT_OR_FAILURE(
574 : isolate, CreateLiteral<ObjectLiteralHelper>(
575 : isolate, vector, literals_index, description, flags));
576 : }
577 :
578 398468 : RUNTIME_FUNCTION(Runtime_CreateObjectLiteralWithoutAllocationSite) {
579 : HandleScope scope(isolate);
580 : DCHECK_EQ(2, args.length());
581 199234 : CONVERT_ARG_HANDLE_CHECKED(ObjectBoilerplateDescription, description, 0);
582 199234 : CONVERT_SMI_ARG_CHECKED(flags, 1);
583 398468 : RETURN_RESULT_OR_FAILURE(
584 : isolate, CreateLiteralWithoutAllocationSite<ObjectLiteralHelper>(
585 : isolate, description, flags));
586 : }
587 :
588 740298 : RUNTIME_FUNCTION(Runtime_CreateArrayLiteralWithoutAllocationSite) {
589 : HandleScope scope(isolate);
590 : DCHECK_EQ(2, args.length());
591 370149 : CONVERT_ARG_HANDLE_CHECKED(ArrayBoilerplateDescription, description, 0);
592 370149 : CONVERT_SMI_ARG_CHECKED(flags, 1);
593 740298 : RETURN_RESULT_OR_FAILURE(
594 : isolate, CreateLiteralWithoutAllocationSite<ArrayLiteralHelper>(
595 : isolate, description, flags));
596 : }
597 :
598 792724 : RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
599 : HandleScope scope(isolate);
600 : DCHECK_EQ(4, args.length());
601 396362 : CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 0);
602 396363 : CONVERT_SMI_ARG_CHECKED(literals_index, 1);
603 396363 : CONVERT_ARG_HANDLE_CHECKED(ArrayBoilerplateDescription, elements, 2);
604 396364 : CONVERT_SMI_ARG_CHECKED(flags, 3);
605 : Handle<FeedbackVector> vector = Handle<FeedbackVector>();
606 396364 : if (!maybe_vector->IsUndefined()) {
607 : DCHECK(maybe_vector->IsFeedbackVector());
608 396364 : vector = Handle<FeedbackVector>::cast(maybe_vector);
609 : }
610 792730 : RETURN_RESULT_OR_FAILURE(
611 : isolate, CreateLiteral<ArrayLiteralHelper>(
612 : isolate, vector, literals_index, elements, flags));
613 : }
614 :
615 163664 : RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) {
616 : HandleScope scope(isolate);
617 : DCHECK_EQ(4, args.length());
618 81832 : CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 0);
619 81832 : CONVERT_SMI_ARG_CHECKED(index, 1);
620 81832 : CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
621 81832 : CONVERT_SMI_ARG_CHECKED(flags, 3);
622 : FeedbackSlot literal_slot(FeedbackVector::ToSlot(index));
623 : Handle<FeedbackVector> vector = Handle<FeedbackVector>();
624 81832 : if (!maybe_vector->IsUndefined()) {
625 : DCHECK(maybe_vector->IsFeedbackVector());
626 : vector = Handle<FeedbackVector>::cast(maybe_vector);
627 : }
628 : Handle<Object> boilerplate;
629 81832 : if (vector.is_null()) {
630 0 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
631 : isolate, boilerplate,
632 : JSRegExp::New(isolate, pattern, JSRegExp::Flags(flags)));
633 0 : return *JSRegExp::Copy(Handle<JSRegExp>::cast(boilerplate));
634 : }
635 :
636 : // Check if boilerplate exists. If not, create it first.
637 : Handle<Object> literal_site(vector->Get(literal_slot)->cast<Object>(),
638 : isolate);
639 81832 : if (!HasBoilerplate(literal_site)) {
640 163664 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
641 : isolate, boilerplate,
642 : JSRegExp::New(isolate, pattern, JSRegExp::Flags(flags)));
643 79262 : if (IsUninitializedLiteralSite(*literal_site)) {
644 : PreInitializeLiteralSite(vector, literal_slot);
645 : return *boilerplate;
646 : }
647 37302 : vector->Set(literal_slot, *boilerplate);
648 : }
649 37302 : return *JSRegExp::Copy(Handle<JSRegExp>::cast(boilerplate));
650 : }
651 :
652 : } // namespace internal
653 122036 : } // namespace v8
|