Defer allocation of constant literal properties.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 7 Nov 2013 12:08:37 +0000 (12:08 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 7 Nov 2013 12:08:37 +0000 (12:08 +0000)
This moves building of constant properties and elements arrays for all
materialized literals into the compiler. The parser no longer allocates
while parsing ObjectLiteral and ArrayLiteral expressions.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/61873003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17557 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/full-codegen-arm.cc
src/ast.cc
src/ast.h
src/hydrogen.cc
src/ia32/full-codegen-ia32.cc
src/mips/full-codegen-mips.cc
src/parser.cc
src/parser.h
src/x64/full-codegen-x64.cc

index a773893..8fb1e15 100644 (file)
@@ -1634,6 +1634,9 @@ void FullCodeGenerator::EmitAccessor(Expression* expression) {
 
 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
   Comment cmnt(masm_, "[ ObjectLiteral");
+
+  int depth = 1;
+  expr->BuildConstantProperties(isolate(), &depth);
   Handle<FixedArray> constant_properties = expr->constant_properties();
   __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
@@ -1648,7 +1651,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
   __ mov(r0, Operand(Smi::FromInt(flags)));
   int properties_count = constant_properties->length() / 2;
   if ((FLAG_track_double_fields && expr->may_store_doubles()) ||
-      expr->depth() > 1 || Serializer::enabled() ||
+      depth > 1 || Serializer::enabled() ||
       flags != ObjectLiteral::kFastElements ||
       properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
     __ Push(r3, r2, r1, r0);
@@ -1767,6 +1770,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
   Comment cmnt(masm_, "[ ArrayLiteral");
 
+  int depth = 1;
+  expr->BuildConstantElements(isolate(), &depth);
   ZoneList<Expression*>* subexprs = expr->values();
   int length = subexprs->length();
   Handle<FixedArray> constant_elements = expr->constant_elements();
@@ -1790,8 +1795,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
     __ CallStub(&stub);
     __ IncrementCounter(
         isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2);
-  } else if (expr->depth() > 1 ||
-             Serializer::enabled() ||
+  } else if (depth > 1 || Serializer::enabled() ||
              length > FastCloneShallowArrayStub::kMaximumClonedLength) {
     __ Push(r3, r2, r1);
     __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
index 843f8c8..9deb71d 100644 (file)
@@ -256,6 +256,169 @@ void ObjectLiteral::CalculateEmitStore(Zone* zone) {
 }
 
 
+bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) {
+  return property != NULL &&
+         property->kind() != ObjectLiteral::Property::PROTOTYPE;
+}
+
+
+void ObjectLiteral::BuildConstantProperties(Isolate* isolate, int* depth) {
+  if (!constant_properties_.is_null()) return;
+
+  // Allocate a fixed array to hold all the constant properties.
+  Handle<FixedArray> constant_properties = isolate->factory()->NewFixedArray(
+      boilerplate_properties_ * 2, TENURED);
+
+  int position = 0;
+  // Accumulate the value in local variables and store it at the end.
+  bool is_simple = true;
+  int depth_acc = 1;
+  uint32_t max_element_index = 0;
+  uint32_t elements = 0;
+  for (int i = 0; i < properties()->length(); i++) {
+    ObjectLiteral::Property* property = properties()->at(i);
+    if (!IsBoilerplateProperty(property)) {
+      is_simple = false;
+      continue;
+    }
+    MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
+    if (m_literal != NULL) {
+      int inner_depth = 1;
+      m_literal->BuildConstants(isolate, &inner_depth);
+      if (inner_depth >= depth_acc) depth_acc = inner_depth + 1;
+    }
+
+    // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
+    // value for COMPUTED properties, the real value is filled in at
+    // runtime. The enumeration order is maintained.
+    Handle<Object> key = property->key()->value();
+    Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
+
+    // Ensure objects that may, at any point in time, contain fields with double
+    // representation are always treated as nested objects. This is true for
+    // computed fields (value is undefined), and smi and double literals
+    // (value->IsNumber()).
+    // TODO(verwaest): Remove once we can store them inline.
+    if (FLAG_track_double_fields &&
+        (value->IsNumber() || value->IsUninitialized())) {
+      may_store_doubles_ = true;
+    }
+
+    is_simple = is_simple && !value->IsUninitialized();
+
+    // Keep track of the number of elements in the object literal and
+    // the largest element index.  If the largest element index is
+    // much larger than the number of elements, creating an object
+    // literal with fast elements will be a waste of space.
+    uint32_t element_index = 0;
+    if (key->IsString()
+        && Handle<String>::cast(key)->AsArrayIndex(&element_index)
+        && element_index > max_element_index) {
+      max_element_index = element_index;
+      elements++;
+    } else if (key->IsSmi()) {
+      int key_value = Smi::cast(*key)->value();
+      if (key_value > 0
+          && static_cast<uint32_t>(key_value) > max_element_index) {
+        max_element_index = key_value;
+      }
+      elements++;
+    }
+
+    // Add name, value pair to the fixed array.
+    constant_properties->set(position++, *key);
+    constant_properties->set(position++, *value);
+  }
+
+  constant_properties_ = constant_properties;
+  fast_elements_ =
+      (max_element_index <= 32) || ((2 * elements) >= max_element_index);
+  set_is_simple(is_simple);
+  if (depth != NULL) *depth = depth_acc;
+}
+
+
+void ArrayLiteral::BuildConstantElements(Isolate* isolate, int* depth) {
+  if (!constant_elements_.is_null()) return;
+
+  // Allocate a fixed array to hold all the object literals.
+  Handle<JSArray> array =
+      isolate->factory()->NewJSArray(0, FAST_HOLEY_SMI_ELEMENTS);
+  isolate->factory()->SetElementsCapacityAndLength(
+      array, values()->length(), values()->length());
+
+  // Fill in the literals.
+  bool is_simple = true;
+  int depth_acc = 1;
+  bool is_holey = false;
+  for (int i = 0, n = values()->length(); i < n; i++) {
+    Expression* element = values()->at(i);
+    MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
+    if (m_literal != NULL) {
+      int inner_depth = 1;
+      m_literal->BuildConstants(isolate, &inner_depth);
+      if (inner_depth + 1 > depth_acc) depth_acc = inner_depth + 1;
+    }
+    Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
+    if (boilerplate_value->IsTheHole()) {
+      is_holey = true;
+    } else if (boilerplate_value->IsUninitialized()) {
+      is_simple = false;
+      JSObject::SetOwnElement(
+          array, i, handle(Smi::FromInt(0), isolate), kNonStrictMode);
+    } else {
+      JSObject::SetOwnElement(array, i, boilerplate_value, kNonStrictMode);
+    }
+  }
+
+  Handle<FixedArrayBase> element_values(array->elements());
+
+  // Simple and shallow arrays can be lazily copied, we transform the
+  // elements array to a copy-on-write array.
+  if (is_simple && depth_acc == 1 && values()->length() > 0 &&
+      array->HasFastSmiOrObjectElements()) {
+    element_values->set_map(isolate->heap()->fixed_cow_array_map());
+  }
+
+  // Remember both the literal's constant values as well as the ElementsKind
+  // in a 2-element FixedArray.
+  Handle<FixedArray> literals = isolate->factory()->NewFixedArray(2, TENURED);
+
+  ElementsKind kind = array->GetElementsKind();
+  kind = is_holey ? GetHoleyElementsKind(kind) : GetPackedElementsKind(kind);
+
+  literals->set(0, Smi::FromInt(kind));
+  literals->set(1, *element_values);
+
+  constant_elements_ = literals;
+  set_is_simple(is_simple);
+  if (depth != NULL) *depth = depth_acc;
+}
+
+
+Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
+                                                        Isolate* isolate) {
+  if (expression->AsLiteral() != NULL) {
+    return expression->AsLiteral()->value();
+  }
+  if (CompileTimeValue::IsCompileTimeValue(expression)) {
+    return CompileTimeValue::GetValue(isolate, expression);
+  }
+  return isolate->factory()->uninitialized_value();
+}
+
+
+void MaterializedLiteral::BuildConstants(Isolate* isolate, int* depth) {
+  if (IsArrayLiteral()) {
+    return AsArrayLiteral()->BuildConstantElements(isolate, depth);
+  }
+  if (IsObjectLiteral()) {
+    return AsObjectLiteral()->BuildConstantProperties(isolate, depth);
+  }
+  ASSERT(IsRegExpLiteral());
+}
+
+
 void TargetCollector::AddTarget(Label* target, Zone* zone) {
   // Add the label to the collector, but discard duplicates.
   int length = targets_.length();
index b4f7348..42f6c8b 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -1409,27 +1409,35 @@ class MaterializedLiteral : public Expression {
 
   int literal_index() { return literal_index_; }
 
-  // A materialized literal is simple if the values consist of only
-  // constants and simple object and array literals.
-  bool is_simple() const { return is_simple_; }
-
-  int depth() const { return depth_; }
-
  protected:
   MaterializedLiteral(Isolate* isolate,
                       int literal_index,
-                      bool is_simple,
-                      int depth,
                       int pos)
       : Expression(isolate, pos),
         literal_index_(literal_index),
-        is_simple_(is_simple),
-        depth_(depth) {}
+        is_simple_(false) {}
+
+  // A materialized literal is simple if the values consist of only
+  // constants and simple object and array literals.
+  bool is_simple() const { return is_simple_; }
+  void set_is_simple(bool is_simple) { is_simple_ = is_simple; }
+  friend class CompileTimeValue;
+
+  // Populate the constant properties/elements fixed array.
+  void BuildConstants(Isolate* isolate, int* depth);
+  friend class ArrayLiteral;
+  friend class ObjectLiteral;
+
+  // If the expression is a literal, return the literal value;
+  // if the expression is a materialized literal and is simple return a
+  // compile time value as encoded by CompileTimeValue::GetValue().
+  // Otherwise, return undefined literal as the placeholder
+  // in the object literal boilerplate.
+  Handle<Object> GetBoilerplateValue(Expression* expression, Isolate* isolate);
 
  private:
   int literal_index_;
   bool is_simple_;
-  int depth_;
 };
 
 
@@ -1493,6 +1501,12 @@ class ObjectLiteral V8_FINAL : public MaterializedLiteral {
   bool may_store_doubles() const { return may_store_doubles_; }
   bool has_function() const { return has_function_; }
 
+  // Decide if a property should be in the object boilerplate.
+  static bool IsBoilerplateProperty(Property* property);
+
+  // Populate the constant properties fixed array.
+  void BuildConstantProperties(Isolate* isolate, int* depth = NULL);
+
   // Mark all computed expressions that are bound to a key that
   // is shadowed by a later occurrence of the same key. For the
   // marked expressions, no store code is emitted.
@@ -1512,25 +1526,22 @@ class ObjectLiteral V8_FINAL : public MaterializedLiteral {
 
  protected:
   ObjectLiteral(Isolate* isolate,
-                Handle<FixedArray> constant_properties,
                 ZoneList<Property*>* properties,
                 int literal_index,
-                bool is_simple,
-                bool fast_elements,
-                int depth,
-                bool may_store_doubles,
+                int boilerplate_properties,
                 bool has_function,
                 int pos)
-      : MaterializedLiteral(isolate, literal_index, is_simple, depth, pos),
-        constant_properties_(constant_properties),
+      : MaterializedLiteral(isolate, literal_index, pos),
         properties_(properties),
-        fast_elements_(fast_elements),
-        may_store_doubles_(may_store_doubles),
+        boilerplate_properties_(boilerplate_properties),
+        fast_elements_(false),
+        may_store_doubles_(false),
         has_function_(has_function) {}
 
  private:
   Handle<FixedArray> constant_properties_;
   ZoneList<Property*>* properties_;
+  int boilerplate_properties_;
   bool fast_elements_;
   bool may_store_doubles_;
   bool has_function_;
@@ -1551,7 +1562,7 @@ class RegExpLiteral V8_FINAL : public MaterializedLiteral {
                 Handle<String> flags,
                 int literal_index,
                 int pos)
-      : MaterializedLiteral(isolate, literal_index, false, 1, pos),
+      : MaterializedLiteral(isolate, literal_index, pos),
         pattern_(pattern),
         flags_(flags) {}
 
@@ -1575,16 +1586,15 @@ class ArrayLiteral V8_FINAL : public MaterializedLiteral {
     return BailoutId(first_element_id_.ToInt() + i);
   }
 
+  // Populate the constant elements fixed array.
+  void BuildConstantElements(Isolate* isolate, int* depth = NULL);
+
  protected:
   ArrayLiteral(Isolate* isolate,
-               Handle<FixedArray> constant_elements,
                ZoneList<Expression*>* values,
                int literal_index,
-               bool is_simple,
-               int depth,
                int pos)
-      : MaterializedLiteral(isolate, literal_index, is_simple, depth, pos),
-        constant_elements_(constant_elements),
+      : MaterializedLiteral(isolate, literal_index, pos),
         values_(values),
         first_element_id_(ReserveIdRange(isolate, values->length())) {}
 
@@ -3066,18 +3076,14 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
   }
 
   ObjectLiteral* NewObjectLiteral(
-      Handle<FixedArray> constant_properties,
       ZoneList<ObjectLiteral::Property*>* properties,
       int literal_index,
-      bool is_simple,
-      bool fast_elements,
-      int depth,
-      bool may_store_doubles,
+      int boilerplate_properties,
       bool has_function,
       int pos) {
     ObjectLiteral* lit = new(zone_) ObjectLiteral(
-        isolate_, constant_properties, properties, literal_index,
-        is_simple, fast_elements, depth, may_store_doubles, has_function, pos);
+        isolate_, properties, literal_index, boilerplate_properties,
+        has_function, pos);
     VISIT_AND_RETURN(ObjectLiteral, lit)
   }
 
@@ -3099,15 +3105,11 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
     VISIT_AND_RETURN(RegExpLiteral, lit);
   }
 
-  ArrayLiteral* NewArrayLiteral(Handle<FixedArray> constant_elements,
-                                ZoneList<Expression*>* values,
+  ArrayLiteral* NewArrayLiteral(ZoneList<Expression*>* values,
                                 int literal_index,
-                                bool is_simple,
-                                int depth,
                                 int pos) {
     ArrayLiteral* lit = new(zone_) ArrayLiteral(
-        isolate_, constant_elements, values, literal_index, is_simple,
-        depth, pos);
+        isolate_, values, literal_index, pos);
     VISIT_AND_RETURN(ArrayLiteral, lit)
   }
 
index d6b97a8..3075952 100644 (file)
@@ -4310,6 +4310,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
+  expr->BuildConstantProperties(isolate());
   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
   HInstruction* literal;
 
@@ -4431,6 +4432,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
+  expr->BuildConstantElements(isolate());
   ZoneList<Expression*>* subexprs = expr->values();
   int length = subexprs->length();
   HInstruction* literal;
index 82d23e7..b7ddeac 100644 (file)
@@ -1574,6 +1574,9 @@ void FullCodeGenerator::EmitAccessor(Expression* expression) {
 
 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
   Comment cmnt(masm_, "[ ObjectLiteral");
+
+  int depth = 1;
+  expr->BuildConstantProperties(isolate(), &depth);
   Handle<FixedArray> constant_properties = expr->constant_properties();
   int flags = expr->fast_elements()
       ? ObjectLiteral::kFastElements
@@ -1583,7 +1586,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       : ObjectLiteral::kNoFlags;
   int properties_count = constant_properties->length() / 2;
   if ((FLAG_track_double_fields && expr->may_store_doubles()) ||
-      expr->depth() > 1 || Serializer::enabled() ||
+      depth > 1 || Serializer::enabled() ||
       flags != ObjectLiteral::kFastElements ||
       properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
     __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
@@ -1702,6 +1705,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
   Comment cmnt(masm_, "[ ArrayLiteral");
 
+  int depth = 1;
+  expr->BuildConstantElements(isolate(), &depth);
   ZoneList<Expression*>* subexprs = expr->values();
   int length = subexprs->length();
   Handle<FixedArray> constant_elements = expr->constant_elements();
@@ -1728,8 +1733,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
         DONT_TRACK_ALLOCATION_SITE,
         length);
     __ CallStub(&stub);
-  } else if (expr->depth() > 1 ||
-             Serializer::enabled() ||
+  } else if (depth > 1 || Serializer::enabled() ||
              length > FastCloneShallowArrayStub::kMaximumClonedLength) {
     __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
     __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
index b217e06..6947ca8 100644 (file)
@@ -1644,6 +1644,9 @@ void FullCodeGenerator::EmitAccessor(Expression* expression) {
 
 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
   Comment cmnt(masm_, "[ ObjectLiteral");
+
+  int depth = 1;
+  expr->BuildConstantProperties(isolate(), &depth);
   Handle<FixedArray> constant_properties = expr->constant_properties();
   __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   __ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
@@ -1658,7 +1661,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
   __ li(a0, Operand(Smi::FromInt(flags)));
   int properties_count = constant_properties->length() / 2;
   if ((FLAG_track_double_fields && expr->may_store_doubles()) ||
-      expr->depth() > 1 || Serializer::enabled() ||
+      depth > 1 || Serializer::enabled() ||
       flags != ObjectLiteral::kFastElements ||
       properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
     __ Push(a3, a2, a1, a0);
@@ -1777,6 +1780,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
   Comment cmnt(masm_, "[ ArrayLiteral");
 
+  int depth = 1;
+  expr->BuildConstantElements(isolate(), &depth);
   ZoneList<Expression*>* subexprs = expr->values();
   int length = subexprs->length();
 
@@ -1803,8 +1808,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
     __ CallStub(&stub);
     __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(),
         1, a1, a2);
-  } else if (expr->depth() > 1 ||
-             Serializer::enabled() ||
+  } else if (depth > 1 || Serializer::enabled() ||
              length > FastCloneShallowArrayStub::kMaximumClonedLength) {
     __ Push(a3, a2, a1);
     __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
index 837d46f..0b1bf63 100644 (file)
@@ -3660,61 +3660,7 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
   // Update the scope information before the pre-parsing bailout.
   int literal_index = current_function_state_->NextMaterializedLiteralIndex();
 
-  // Allocate a fixed array to hold all the object literals.
-  Handle<JSArray> array =
-      isolate()->factory()->NewJSArray(0, FAST_HOLEY_SMI_ELEMENTS);
-  isolate()->factory()->SetElementsCapacityAndLength(
-      array, values->length(), values->length());
-
-  // Fill in the literals.
-  Heap* heap = isolate()->heap();
-  bool is_simple = true;
-  int depth = 1;
-  bool is_holey = false;
-  for (int i = 0, n = values->length(); i < n; i++) {
-    MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
-    if (m_literal != NULL && m_literal->depth() + 1 > depth) {
-      depth = m_literal->depth() + 1;
-    }
-    Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
-    if (boilerplate_value->IsTheHole()) {
-      is_holey = true;
-    } else if (boilerplate_value->IsUninitialized()) {
-      is_simple = false;
-      JSObject::SetOwnElement(
-          array, i, handle(Smi::FromInt(0), isolate()), kNonStrictMode);
-    } else {
-      JSObject::SetOwnElement(array, i, boilerplate_value, kNonStrictMode);
-    }
-  }
-
-  Handle<FixedArrayBase> element_values(array->elements());
-
-  // Simple and shallow arrays can be lazily copied, we transform the
-  // elements array to a copy-on-write array.
-  if (is_simple && depth == 1 && values->length() > 0 &&
-      array->HasFastSmiOrObjectElements()) {
-    element_values->set_map(heap->fixed_cow_array_map());
-  }
-
-  // Remember both the literal's constant values as well as the ElementsKind
-  // in a 2-element FixedArray.
-  Handle<FixedArray> literals = isolate()->factory()->NewFixedArray(2, TENURED);
-
-  ElementsKind kind = array->GetElementsKind();
-  kind = is_holey ? GetHoleyElementsKind(kind) : GetPackedElementsKind(kind);
-
-  literals->set(0, Smi::FromInt(kind));
-  literals->set(1, *element_values);
-
-  return factory()->NewArrayLiteral(
-      literals, values, literal_index, is_simple, depth, pos);
-}
-
-
-bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
-  return property != NULL &&
-         property->kind() != ObjectLiteral::Property::PROTOTYPE;
+  return factory()->NewArrayLiteral(values, literal_index, pos);
 }
 
 
@@ -3761,89 +3707,6 @@ Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
 }
 
 
-Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
-  if (expression->AsLiteral() != NULL) {
-    return expression->AsLiteral()->value();
-  }
-  if (CompileTimeValue::IsCompileTimeValue(expression)) {
-    return CompileTimeValue::GetValue(isolate(), expression);
-  }
-  return isolate()->factory()->uninitialized_value();
-}
-
-
-void Parser::BuildObjectLiteralConstantProperties(
-    ZoneList<ObjectLiteral::Property*>* properties,
-    Handle<FixedArray> constant_properties,
-    bool* is_simple,
-    bool* fast_elements,
-    int* depth,
-    bool* may_store_doubles) {
-  int position = 0;
-  // Accumulate the value in local variables and store it at the end.
-  bool is_simple_acc = true;
-  int depth_acc = 1;
-  uint32_t max_element_index = 0;
-  uint32_t elements = 0;
-  for (int i = 0; i < properties->length(); i++) {
-    ObjectLiteral::Property* property = properties->at(i);
-    if (!IsBoilerplateProperty(property)) {
-      is_simple_acc = false;
-      continue;
-    }
-    MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
-    if (m_literal != NULL && m_literal->depth() >= depth_acc) {
-      depth_acc = m_literal->depth() + 1;
-    }
-
-    // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
-    // value for COMPUTED properties, the real value is filled in at
-    // runtime. The enumeration order is maintained.
-    Handle<Object> key = property->key()->value();
-    Handle<Object> value = GetBoilerplateValue(property->value());
-
-    // Ensure objects that may, at any point in time, contain fields with double
-    // representation are always treated as nested objects. This is true for
-    // computed fields (value is undefined), and smi and double literals
-    // (value->IsNumber()).
-    // TODO(verwaest): Remove once we can store them inline.
-    if (FLAG_track_double_fields &&
-        (value->IsNumber() || value->IsUninitialized())) {
-      *may_store_doubles = true;
-    }
-
-    is_simple_acc = is_simple_acc && !value->IsUninitialized();
-
-    // Keep track of the number of elements in the object literal and
-    // the largest element index.  If the largest element index is
-    // much larger than the number of elements, creating an object
-    // literal with fast elements will be a waste of space.
-    uint32_t element_index = 0;
-    if (key->IsString()
-        && Handle<String>::cast(key)->AsArrayIndex(&element_index)
-        && element_index > max_element_index) {
-      max_element_index = element_index;
-      elements++;
-    } else if (key->IsSmi()) {
-      int key_value = Smi::cast(*key)->value();
-      if (key_value > 0
-          && static_cast<uint32_t>(key_value) > max_element_index) {
-        max_element_index = key_value;
-      }
-      elements++;
-    }
-
-    // Add name, value pair to the fixed array.
-    constant_properties->set(position++, *key);
-    constant_properties->set(position++, *value);
-  }
-  *fast_elements =
-      (max_element_index <= 32) || ((2 * elements) >= max_element_index);
-  *is_simple = is_simple_acc;
-  *depth = depth_acc;
-}
-
-
 Expression* Parser::ParseObjectLiteral(bool* ok) {
   // ObjectLiteral ::
   //   '{' (
@@ -3912,7 +3775,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
           // Specification only allows zero parameters for get and one for set.
           ObjectLiteral::Property* property =
               factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
-          if (IsBoilerplateProperty(property)) {
+          if (ObjectLiteral::IsBoilerplateProperty(property)) {
             number_of_boilerplate_properties++;
           }
           properties->Add(property, zone());
@@ -3984,7 +3847,9 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
     }
 
     // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
-    if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
+    if (ObjectLiteral::IsBoilerplateProperty(property)) {
+      number_of_boilerplate_properties++;
+    }
     properties->Add(property, zone());
 
     // TODO(1240767): Consider allowing trailing comma.
@@ -4000,26 +3865,9 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
   // Computation of literal_index must happen before pre parse bailout.
   int literal_index = current_function_state_->NextMaterializedLiteralIndex();
 
-  Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
-      number_of_boilerplate_properties * 2, TENURED);
-
-  bool is_simple = true;
-  bool fast_elements = true;
-  int depth = 1;
-  bool may_store_doubles = false;
-  BuildObjectLiteralConstantProperties(properties,
-                                       constant_properties,
-                                       &is_simple,
-                                       &fast_elements,
-                                       &depth,
-                                       &may_store_doubles);
-  return factory()->NewObjectLiteral(constant_properties,
-                                     properties,
+  return factory()->NewObjectLiteral(properties,
                                      literal_index,
-                                     is_simple,
-                                     fast_elements,
-                                     depth,
-                                     may_store_doubles,
+                                     number_of_boilerplate_properties,
                                      has_function,
                                      pos);
 }
index 79ce68b..f5ad311 100644 (file)
@@ -653,25 +653,6 @@ class Parser : public ParserBase {
   Expression* ParseObjectLiteral(bool* ok);
   Expression* ParseRegExpLiteral(bool seen_equal, bool* ok);
 
-  // Populate the constant properties fixed array for a materialized object
-  // literal.
-  void BuildObjectLiteralConstantProperties(
-      ZoneList<ObjectLiteral::Property*>* properties,
-      Handle<FixedArray> constants,
-      bool* is_simple,
-      bool* fast_elements,
-      int* depth,
-      bool* may_store_doubles);
-
-  // Decide if a property should be in the object boilerplate.
-  bool IsBoilerplateProperty(ObjectLiteral::Property* property);
-  // If the expression is a literal, return the literal value;
-  // if the expression is a materialized literal and is simple return a
-  // compile time value as encoded by CompileTimeValue::GetValue().
-  // Otherwise, return undefined literal as the placeholder
-  // in the object literal boilerplate.
-  Handle<Object> GetBoilerplateValue(Expression* expression);
-
   // Initialize the components of a for-in / for-of statement.
   void InitializeForEachStatement(ForEachStatement* stmt,
                                   Expression* each,
index 2e988c8..468ed8c 100644 (file)
@@ -1595,6 +1595,9 @@ void FullCodeGenerator::EmitAccessor(Expression* expression) {
 
 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
   Comment cmnt(masm_, "[ ObjectLiteral");
+
+  int depth = 1;
+  expr->BuildConstantProperties(isolate(), &depth);
   Handle<FixedArray> constant_properties = expr->constant_properties();
   int flags = expr->fast_elements()
       ? ObjectLiteral::kFastElements
@@ -1604,7 +1607,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       : ObjectLiteral::kNoFlags;
   int properties_count = constant_properties->length() / 2;
   if ((FLAG_track_double_fields && expr->may_store_doubles()) ||
-      expr->depth() > 1 || Serializer::enabled() ||
+      depth > 1 || Serializer::enabled() ||
       flags != ObjectLiteral::kFastElements ||
       properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
     __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
@@ -1723,6 +1726,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
   Comment cmnt(masm_, "[ ArrayLiteral");
 
+  int depth = 1;
+  expr->BuildConstantElements(isolate(), &depth);
   ZoneList<Expression*>* subexprs = expr->values();
   int length = subexprs->length();
   Handle<FixedArray> constant_elements = expr->constant_elements();
@@ -1749,8 +1754,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
         DONT_TRACK_ALLOCATION_SITE,
         length);
     __ CallStub(&stub);
-  } else if (expr->depth() > 1 ||
-             Serializer::enabled() ||
+  } else if (depth > 1 || Serializer::enabled() ||
              length > FastCloneShallowArrayStub::kMaximumClonedLength) {
     __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
     __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));