Chromium Code Reviews| Index: src/compiler/ast-graph-builder.cc |
| diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc |
| index 8443cfafac50cf6aff02651acfb4aa55e51fc24e..e4b22601eca6020ca374b21e529e49490e5ccd8d 100644 |
| --- a/src/compiler/ast-graph-builder.cc |
| +++ b/src/compiler/ast-graph-builder.cc |
| @@ -1027,9 +1027,11 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| expr->CalculateEmitStore(zone()); |
| // Create nodes to store computed values into the literal. |
| + int property_index = 0; |
| AccessorTable accessor_table(zone()); |
| - for (int i = 0; i < expr->properties()->length(); i++) { |
| - ObjectLiteral::Property* property = expr->properties()->at(i); |
| + for (; property_index < expr->properties()->length(); property_index++) { |
| + ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| + if (property->is_computed_name()) break; |
| if (property->IsCompileTimeValue()) continue; |
| Literal* key = property->key()->AsLiteral(); |
| @@ -1111,6 +1113,64 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| PrepareFrameState(call, BailoutId::None()); |
| } |
| + // Object literals have two parts. The "static" part on the left contains no |
| + // computed property names, and so we can compute its map ahead of time; see |
| + // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts |
| + // with the first computed property name and continues with all properties to |
| + // its right. All the code from above initializes the static component of the |
| + // object literal, and arranges for the map of the result to reflect the |
| + // static order in which the keys appear. For the dynamic properties, we |
| + // compile them into a series of "SetOwnProperty" runtime calls. This will |
| + // preserve insertion order. |
| + for (; property_index < expr->properties()->length(); property_index++) { |
| + ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| + |
| + environment()->Push(literal); // Duplicate receiver. |
| + VisitForValue(property->key()); |
| + environment()->Push(BuildToName(environment()->Pop())); |
| + // TODO(mstarzinger): For ObjectLiteral::Property::PROTOTYPE the key should |
|
arv (Not doing code reviews)
2015/02/13 15:15:57
In the case of the property being `__proto__: expr
Michael Starzinger
2015/02/16 10:39:15
The TODO is not about evaluating the "key" being o
|
| + // not be on the operand stack while the value is being evaluated. Come up |
| + // with a repro for this and fix it. Also find a nice way to do so. :) |
| + VisitForValue(property->value()); |
| + Node* value = environment()->Pop(); |
| + Node* key = environment()->Pop(); |
| + Node* receiver = environment()->Pop(); |
| + |
| + switch (property->kind()) { |
| + case ObjectLiteral::Property::CONSTANT: |
| + case ObjectLiteral::Property::COMPUTED: |
| + case ObjectLiteral::Property::MATERIALIZED_LITERAL: { |
| + Node* attr = jsgraph()->Constant(NONE); |
| + const Operator* op = |
| + javascript()->CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); |
| + Node* call = NewNode(op, receiver, key, value, attr); |
| + PrepareFrameState(call, BailoutId::None()); |
| + break; |
| + } |
| + case ObjectLiteral::Property::PROTOTYPE: { |
| + const Operator* op = |
| + javascript()->CallRuntime(Runtime::kInternalSetPrototype, 2); |
| + Node* call = NewNode(op, receiver, value); |
| + PrepareFrameState(call, BailoutId::None()); |
| + break; |
| + } |
| + case ObjectLiteral::Property::GETTER: { |
| + const Operator* op = javascript()->CallRuntime( |
| + Runtime::kDefineGetterPropertyUnchecked, 3); |
| + Node* call = NewNode(op, receiver, key, value); |
| + PrepareFrameState(call, BailoutId::None()); |
| + break; |
| + } |
| + case ObjectLiteral::Property::SETTER: { |
| + const Operator* op = javascript()->CallRuntime( |
| + Runtime::kDefineSetterPropertyUnchecked, 3); |
| + Node* call = NewNode(op, receiver, key, value); |
| + PrepareFrameState(call, BailoutId::None()); |
| + break; |
| + } |
| + } |
| + } |
| + |
| // Transform literals that contain functions to fast properties. |
| if (expr->has_function()) { |
| const Operator* op = |