1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/runtime/runtime-utils.h"
6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/allocation-site-scopes.h"
8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/arguments.h"
9f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/ast/ast.h"
10f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/ast/compile-time-value.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate-inl.h"
12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h"
13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic Handle<Map> ComputeObjectLiteralMap(
1862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Context> context,
1962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<BoilerplateDescription> boilerplate_description,
203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    bool* is_result_from_cache) {
2162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int number_of_properties = boilerplate_description->backing_store_size();
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Isolate* isolate = context->GetIsolate();
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return isolate->factory()->ObjectLiteralMapFromCache(
243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      context, number_of_properties, is_result_from_cache);
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierMUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
2862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Isolate* isolate, Handle<FeedbackVector> vector,
2962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<BoilerplateDescription> boilerplate_description);
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierMUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
3262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Isolate* isolate, Handle<FeedbackVector> vector,
3362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<BoilerplateDescription> boilerplate_description,
3462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bool should_have_fast_elements) {
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Context> context = isolate->native_context();
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // In case we have function literals, we want the object to be in
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // slow properties mode for now. We don't go in the map cache because
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // maps with constant functions can't be shared if the functions are
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // not the same (which is the common case).
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool is_result_from_cache = false;
4262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Map> map = ComputeObjectLiteralMap(context, boilerplate_description,
433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                            &is_result_from_cache);
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  PretenureFlag pretenure_flag =
4662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate->heap()->InNewSpace(*vector) ? NOT_TENURED : TENURED;
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSObject> boilerplate =
49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);
50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Normalize the elements of the boilerplate to save space if needed.
52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Add the constant properties to the boilerplate.
5562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int length = boilerplate_description->size();
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool should_transform =
57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      !is_result_from_cache && boilerplate->HasFastProperties();
583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool should_normalize = should_transform;
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (should_normalize) {
60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // TODO(verwaest): We might not want to ever normalize here.
6162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    JSObject::NormalizeProperties(boilerplate, KEEP_INOBJECT_PROPERTIES, length,
6262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                  "Boilerplate");
63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // TODO(verwaest): Support tracking representations in the boilerplate.
6562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  for (int index = 0; index < length; index++) {
6662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Object> key(boilerplate_description->name(index), isolate);
6762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Object> value(boilerplate_description->value(index), isolate);
6862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (value->IsBoilerplateDescription()) {
6962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // The value contains the boilerplate properties of a
70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // simple object or array literal.
7162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Handle<BoilerplateDescription> boilerplate =
7262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Handle<BoilerplateDescription>::cast(value);
73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ASSIGN_RETURN_ON_EXCEPTION(
7462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          isolate, value,
7562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          CreateLiteralBoilerplate(isolate, vector, boilerplate), Object);
76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MaybeHandle<Object> maybe_result;
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    uint32_t element_index = 0;
793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (key->ToArrayIndex(&element_index)) {
80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Array index (uint32).
8113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (value->IsUninitialized(isolate)) {
82c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        value = handle(Smi::kZero, isolate);
8313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      maybe_result = JSObject::SetOwnElementIgnoreAttributes(
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          boilerplate, element_index, value, NONE);
86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Handle<String> name = Handle<String>::cast(key);
883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      DCHECK(!name->AsArrayIndex(&element_index));
89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name,
90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                              value, NONE);
91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    RETURN_ON_EXCEPTION(isolate, maybe_result, Object);
93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Transform to fast properties if necessary. For object literals with
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // containing function literals we defer this operation until after all
97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // computed properties have been assigned so that we can generate
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // constant function properties.
993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (should_transform) {
100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    JSObject::MigrateSlowToFast(boilerplate,
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                boilerplate->map()->unused_property_fields(),
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                "FastLiteral");
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return boilerplate;
105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
107bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochstatic MaybeHandle<Object> CreateArrayLiteralBoilerplate(
10862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Isolate* isolate, Handle<FeedbackVector> vector,
10962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<ConstantElementsPair> elements) {
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Create the JSArray.
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<JSFunction> constructor = isolate->array_function();
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  PretenureFlag pretenure_flag =
11462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate->heap()->InNewSpace(*vector) ? NOT_TENURED : TENURED;
115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSArray> object = Handle<JSArray>::cast(
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      isolate->factory()->NewJSObject(constructor, pretenure_flag));
118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ElementsKind constant_elements_kind =
12062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      static_cast<ElementsKind>(elements->elements_kind());
12162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<FixedArrayBase> constant_elements_values(elements->constant_values());
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  {
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DisallowHeapAllocation no_gc;
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(IsFastElementsKind(constant_elements_kind));
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Context* native_context = isolate->context()->native_context();
1273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Object* map =
1283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        native_context->get(Context::ArrayMapIndex(constant_elements_kind));
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    object->set_map(Map::cast(map));
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<FixedArrayBase> copied_elements_values;
133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (IsFastDoubleElementsKind(constant_elements_kind)) {
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Handle<FixedDoubleArray>::cast(constant_elements_values));
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(IsFastSmiOrObjectElementsKind(constant_elements_kind));
138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    const bool is_cow = (constant_elements_values->map() ==
139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         isolate->heap()->fixed_cow_array_map());
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (is_cow) {
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      copied_elements_values = constant_elements_values;
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if DEBUG
143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<FixedArray> fixed_array_values =
144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Handle<FixedArray>::cast(copied_elements_values);
145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      for (int i = 0; i < fixed_array_values->length(); i++) {
146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DCHECK(!fixed_array_values->get(i)->IsFixedArray());
147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<FixedArray> fixed_array_values =
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Handle<FixedArray>::cast(constant_elements_values);
152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<FixedArray> fixed_array_values_copy =
153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          isolate->factory()->CopyFixedArray(fixed_array_values);
154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      copied_elements_values = fixed_array_values_copy;
1553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      FOR_WITH_HANDLE_SCOPE(
1563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          isolate, int, i = 0, i, i < fixed_array_values->length(), i++, {
15762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            if (fixed_array_values->get(i)->IsBoilerplateDescription()) {
15862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              // The value contains the boilerplate properties of a
1593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch              // simple object or array literal.
16062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Handle<BoilerplateDescription> boilerplate(
16162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  BoilerplateDescription::cast(fixed_array_values->get(i)));
1623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch              Handle<Object> result;
1633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch              ASSIGN_RETURN_ON_EXCEPTION(
1643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                  isolate, result,
16562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  CreateLiteralBoilerplate(isolate, vector, boilerplate),
16662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  Object);
1673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch              fixed_array_values_copy->set(i, *result);
1683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            }
1693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          });
170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  object->set_elements(*copied_elements_values);
173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  object->set_length(Smi::FromInt(copied_elements_values->length()));
174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JSObject::ValidateElements(object);
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return object;
177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierMUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
18062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Isolate* isolate, Handle<FeedbackVector> vector,
18162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<BoilerplateDescription> array) {
18262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<HeapObject> elements = CompileTimeValue::GetElements(array);
183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  switch (CompileTimeValue::GetLiteralType(array)) {
18462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS: {
18562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Handle<BoilerplateDescription> props =
18662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Handle<BoilerplateDescription>::cast(elements);
18762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return CreateObjectLiteralBoilerplate(isolate, vector, props, true);
18862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
18962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS: {
19062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Handle<BoilerplateDescription> props =
19162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Handle<BoilerplateDescription>::cast(elements);
19262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return CreateObjectLiteralBoilerplate(isolate, vector, props, false);
19362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case CompileTimeValue::ARRAY_LITERAL: {
19562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Handle<ConstantElementsPair> elems =
19662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Handle<ConstantElementsPair>::cast(elements);
19762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return CreateArrayLiteralBoilerplate(isolate, vector, elems);
19862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    default:
200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      UNREACHABLE();
201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return MaybeHandle<Object>();
202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) {
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HandleScope scope(isolate);
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(4, args.length());
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0);
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CONVERT_SMI_ARG_CHECKED(index, 1);
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CONVERT_SMI_ARG_CHECKED(flags, 3);
21362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  FeedbackSlot literal_slot(FeedbackVector::ToSlot(index));
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check if boilerplate exists. If not, create it first.
21662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> boilerplate(closure->feedback_vector()->Get(literal_slot),
21762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             isolate);
21813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (boilerplate->IsUndefined(isolate)) {
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isolate, boilerplate, JSRegExp::New(pattern, JSRegExp::Flags(flags)));
22162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    closure->feedback_vector()->Set(literal_slot, *boilerplate);
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return *JSRegExp::Copy(Handle<JSRegExp>::cast(boilerplate));
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(4, args.length());
230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0);
231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
23262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(BoilerplateDescription, boilerplate_description,
23362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             2);
234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_SMI_ARG_CHECKED(flags, 3);
23562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<FeedbackVector> vector(closure->feedback_vector(), isolate);
236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0;
238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
23962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
24062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CHECK(literals_slot.ToInt() < vector->slot_count());
241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check if boilerplate exists. If not, create it first.
24362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> literal_site(vector->Get(literals_slot), isolate);
244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<AllocationSite> site;
245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSObject> boilerplate;
24613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (literal_site->IsUndefined(isolate)) {
247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Object> raw_boilerplate;
248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        isolate, raw_boilerplate,
25062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        CreateObjectLiteralBoilerplate(isolate, vector, boilerplate_description,
2513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                       should_have_fast_elements));
252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    boilerplate = Handle<JSObject>::cast(raw_boilerplate);
253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    AllocationSiteCreationContext creation_context(isolate);
255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    site = creation_context.EnterNewScope();
256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    RETURN_FAILURE_ON_EXCEPTION(
257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        isolate, JSObject::DeepWalk(boilerplate, &creation_context));
258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    creation_context.ExitScope(site, boilerplate);
259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Update the functions literal and return the boilerplate.
26162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    vector->Set(literals_slot, *site);
262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    site = Handle<AllocationSite>::cast(literal_site);
264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    boilerplate =
265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Handle<JSObject>(JSObject::cast(site->transition_info()), isolate);
266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  usage_context.EnterNewScope();
270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MaybeHandle<Object> maybe_copy =
271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      JSObject::DeepCopy(boilerplate, &usage_context);
272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  usage_context.ExitScope(site, boilerplate);
27313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  RETURN_RESULT_OR_FAILURE(isolate, maybe_copy);
274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierMUST_USE_RESULT static MaybeHandle<AllocationSite> GetLiteralAllocationSite(
27762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot literals_slot,
27862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<ConstantElementsPair> elements) {
279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check if boilerplate exists. If not, create it first.
28062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> literal_site(vector->Get(literals_slot), isolate);
281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<AllocationSite> site;
28213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (literal_site->IsUndefined(isolate)) {
283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Object> boilerplate;
284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    ASSIGN_RETURN_ON_EXCEPTION(
285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        isolate, boilerplate,
28662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        CreateArrayLiteralBoilerplate(isolate, vector, elements),
287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AllocationSite);
288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    AllocationSiteCreationContext creation_context(isolate);
290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    site = creation_context.EnterNewScope();
291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (JSObject::DeepWalk(Handle<JSObject>::cast(boilerplate),
292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           &creation_context).is_null()) {
293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return Handle<AllocationSite>::null();
294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    creation_context.ExitScope(site, Handle<JSObject>::cast(boilerplate));
296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
29762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    vector->Set(literals_slot, *site);
298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    site = Handle<AllocationSite>::cast(literal_site);
300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return site;
303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic MaybeHandle<JSObject> CreateArrayLiteralImpl(
30662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot literals_slot,
30762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<ConstantElementsPair> elements, int flags) {
30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CHECK(literals_slot.ToInt() < vector->slot_count());
309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<AllocationSite> site;
310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ASSIGN_RETURN_ON_EXCEPTION(
311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      isolate, site,
31262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      GetLiteralAllocationSite(isolate, vector, literals_slot, elements),
313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      JSObject);
314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  usage_context.EnterNewScope();
319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0
320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                      ? JSObject::kNoHints
321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                      : JSObject::kObjectIsShallow;
322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MaybeHandle<JSObject> copy =
323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      JSObject::DeepCopy(boilerplate, &usage_context, hints);
324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  usage_context.ExitScope(site, boilerplate);
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return copy;
326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(4, args.length());
332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0);
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
33462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(ConstantElementsPair, elements, 2);
335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_SMI_ARG_CHECKED(flags, 3);
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
33762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
33862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<FeedbackVector> vector(closure->feedback_vector(), isolate);
33913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  RETURN_RESULT_OR_FAILURE(
34062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate,
34162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CreateArrayLiteralImpl(isolate, vector, literals_slot, elements, flags));
342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_CreateArrayLiteralStubBailout) {
346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(3, args.length());
348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0);
349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
35062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(ConstantElementsPair, elements, 2);
351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
35262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<FeedbackVector> vector(closure->feedback_vector(), isolate);
35362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
35413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  RETURN_RESULT_OR_FAILURE(
35562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate, CreateArrayLiteralImpl(isolate, vector, literals_slot, elements,
35662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                      ArrayLiteral::kShallowElements));
357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
361