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