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());
|
||||
|
||||
// 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
|
||||
// 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 =
|
||||
|
@ -263,10 +263,17 @@ function ID(x) {
|
||||
};
|
||||
assertEquals(proto, Object.getPrototypeOf(object));
|
||||
|
||||
var object = {
|
||||
object = {
|
||||
['__proto__']: proto
|
||||
};
|
||||
assertEquals(Object.prototype, Object.getPrototypeOf(object));
|
||||
assertEquals(proto, object.__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.
|
||||
'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.
|
||||
'debug-evaluate-const': [PASS, NO_VARIANTS],
|
||||
'debug-evaluate-locals': [PASS, NO_VARIANTS],
|
||||
|
Loading…
Reference in New Issue
Block a user