Computed property names for object literals in TurboFan.
R=dslomov@chromium.org TEST=mjsunit/harmony/computed-property-names Review URL: https://codereview.chromium.org/860033002 Cr-Commit-Position: refs/heads/master@{#26174}
This commit is contained in:
parent
65c01bdc64
commit
bd7f546f11
@ -1027,9 +1027,11 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
expr->CalculateEmitStore(zone());
|
expr->CalculateEmitStore(zone());
|
||||||
|
|
||||||
// Create nodes to store computed values into the literal.
|
// Create nodes to store computed values into the literal.
|
||||||
|
int property_index = 0;
|
||||||
AccessorTable accessor_table(zone());
|
AccessorTable accessor_table(zone());
|
||||||
for (int i = 0; i < expr->properties()->length(); i++) {
|
for (; property_index < expr->properties()->length(); property_index++) {
|
||||||
ObjectLiteral::Property* property = expr->properties()->at(i);
|
ObjectLiteral::Property* property = expr->properties()->at(property_index);
|
||||||
|
if (property->is_computed_name()) break;
|
||||||
if (property->IsCompileTimeValue()) continue;
|
if (property->IsCompileTimeValue()) continue;
|
||||||
|
|
||||||
Literal* key = property->key()->AsLiteral();
|
Literal* key = property->key()->AsLiteral();
|
||||||
@ -1111,6 +1113,64 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
PrepareFrameState(call, BailoutId::None());
|
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
|
||||||
|
// 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.
|
// Transform literals that contain functions to fast properties.
|
||||||
if (expr->has_function()) {
|
if (expr->has_function()) {
|
||||||
const Operator* op =
|
const Operator* op =
|
||||||
|
@ -263,10 +263,17 @@ function ID(x) {
|
|||||||
};
|
};
|
||||||
assertEquals(proto, Object.getPrototypeOf(object));
|
assertEquals(proto, Object.getPrototypeOf(object));
|
||||||
|
|
||||||
var object = {
|
object = {
|
||||||
['__proto__']: proto
|
['__proto__']: proto
|
||||||
};
|
};
|
||||||
assertEquals(Object.prototype, Object.getPrototypeOf(object));
|
assertEquals(Object.prototype, Object.getPrototypeOf(object));
|
||||||
assertEquals(proto, object.__proto__);
|
assertEquals(proto, object.__proto__);
|
||||||
assertTrue(object.hasOwnProperty('__proto__'));
|
assertTrue(object.hasOwnProperty('__proto__'));
|
||||||
|
|
||||||
|
object = {
|
||||||
|
[ID('x')]: 'X',
|
||||||
|
__proto__: proto
|
||||||
|
};
|
||||||
|
assertEquals('X', object.x);
|
||||||
|
assertEquals(proto, Object.getPrototypeOf(object));
|
||||||
})();
|
})();
|
||||||
|
@ -84,11 +84,6 @@
|
|||||||
# not work, but we expect it to not crash.
|
# not work, but we expect it to not crash.
|
||||||
'debug-step-turbofan': [PASS, FAIL],
|
'debug-step-turbofan': [PASS, FAIL],
|
||||||
|
|
||||||
# TODO(mstarzinger): Investigate failures with computed property names.
|
|
||||||
# Note that this happens in GC-stress mode only.
|
|
||||||
'harmony/computed-property-names': [PASS, NO_VARIANTS],
|
|
||||||
'harmony/computed-property-names-object-literals-methods': [PASS, NO_VARIANTS],
|
|
||||||
|
|
||||||
# TODO(jarin/mstarzinger): Investigate debugger issues with TurboFan.
|
# TODO(jarin/mstarzinger): Investigate debugger issues with TurboFan.
|
||||||
'debug-evaluate-const': [PASS, NO_VARIANTS],
|
'debug-evaluate-const': [PASS, NO_VARIANTS],
|
||||||
'debug-evaluate-locals': [PASS, NO_VARIANTS],
|
'debug-evaluate-locals': [PASS, NO_VARIANTS],
|
||||||
|
Loading…
Reference in New Issue
Block a user