Commit 53c9f0bb authored by dslomov@chromium.org's avatar dslomov@chromium.org

Keyed stores to super where key is a name.

R=arv@chromium.org, ishell@chromium.org
BUG=v:3330
LOG=N

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24490 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 61b68155
...@@ -1889,22 +1889,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1889,22 +1889,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment"); Comment cmnt(masm_, "[ Assignment");
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE;
Property* property = expr->target()->AsProperty(); Property* property = expr->target()->AsProperty();
if (property != NULL) { LhsKind assign_type = GetAssignType(property);
assign_type = (property->key()->IsPropertyName())
? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY
: NAMED_PROPERTY)
: KEYED_PROPERTY;
}
// Evaluate LHS expression. // Evaluate LHS expression.
switch (assign_type) { switch (assign_type) {
...@@ -1931,6 +1917,21 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1931,6 +1917,21 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
__ Push(result_register()); __ Push(result_register());
} }
break; break;
case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
__ Push(result_register());
VisitForAccumulatorValue(property->key());
__ Push(result_register());
if (expr->is_compound()) {
const Register scratch = r1;
__ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
__ Push(scratch);
__ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
__ Push(scratch);
__ Push(result_register());
}
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
if (expr->is_compound()) { if (expr->is_compound()) {
VisitForStackValue(property->obj()); VisitForStackValue(property->obj());
...@@ -1962,6 +1963,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1962,6 +1963,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedSuperPropertyLoad(property); EmitNamedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG); PrepareForBailoutForId(property->LoadId(), TOS_REG);
break; break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property); EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG); PrepareForBailoutForId(property->LoadId(), TOS_REG);
...@@ -2012,6 +2017,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -2012,6 +2017,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedSuperPropertyStore(property); EmitNamedSuperPropertyStore(property);
context()->Plug(r0); context()->Plug(r0);
break; break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyStore(property);
context()->Plug(r0);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr); EmitKeyedPropertyAssignment(expr);
break; break;
...@@ -2657,14 +2666,27 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { ...@@ -2657,14 +2666,27 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
DCHECK(key != NULL); DCHECK(key != NULL);
__ Push(r0);
__ Push(key->value()); __ Push(key->value());
__ Push(r0);
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
: Runtime::kStoreToSuper_Sloppy), : Runtime::kStoreToSuper_Sloppy),
4); 4);
} }
void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
// Assignment to named property of super.
// r0 : value
// stack : receiver ('this'), home_object, key
DCHECK(prop != NULL);
__ Push(r0);
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict
: Runtime::kStoreKeyedToSuper_Sloppy),
4);
}
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
// Assignment to a property, using a keyed store IC. // Assignment to a property, using a keyed store IC.
...@@ -4436,24 +4458,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4436,24 +4458,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Comment cmnt(masm_, "[ CountOperation"); Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
// Expression can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE;
Property* prop = expr->expression()->AsProperty(); Property* prop = expr->expression()->AsProperty();
// In case of a property we use the uninitialized expression context LhsKind assign_type = GetAssignType(prop);
// of the key to detect a named property.
if (prop != NULL) {
assign_type =
(prop->key()->IsPropertyName())
? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
: KEYED_PROPERTY;
}
// Evaluate expression and get value. // Evaluate expression and get value.
if (assign_type == VARIABLE) { if (assign_type == VARIABLE) {
...@@ -4466,27 +4472,55 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4466,27 +4472,55 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ mov(ip, Operand(Smi::FromInt(0))); __ mov(ip, Operand(Smi::FromInt(0)));
__ push(ip); __ push(ip);
} }
if (assign_type == NAMED_PROPERTY) { switch (assign_type) {
// Put the object both on the stack and in the register. case NAMED_PROPERTY: {
VisitForStackValue(prop->obj()); // Put the object both on the stack and in the register.
__ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); VisitForStackValue(prop->obj());
EmitNamedPropertyLoad(prop); __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
} else if (assign_type == NAMED_SUPER_PROPERTY) { EmitNamedPropertyLoad(prop);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); break;
EmitLoadHomeObject(prop->obj()->AsSuperReference()); }
__ Push(result_register());
const Register scratch = r1; case NAMED_SUPER_PROPERTY: {
__ ldr(scratch, MemOperand(sp, kPointerSize)); VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
__ Push(scratch); EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register()); __ Push(result_register());
EmitNamedSuperPropertyLoad(prop); const Register scratch = r1;
} else { __ ldr(scratch, MemOperand(sp, kPointerSize));
VisitForStackValue(prop->obj()); __ Push(scratch);
VisitForStackValue(prop->key()); __ Push(result_register());
__ ldr(LoadDescriptor::ReceiverRegister(), EmitNamedSuperPropertyLoad(prop);
MemOperand(sp, 1 * kPointerSize)); break;
__ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0)); }
EmitKeyedPropertyLoad(prop);
case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
VisitForAccumulatorValue(prop->key());
__ Push(result_register());
const Register scratch = r1;
__ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
__ Push(scratch);
__ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
__ Push(scratch);
__ Push(result_register());
EmitKeyedSuperPropertyLoad(prop);
break;
}
case KEYED_PROPERTY: {
VisitForStackValue(prop->obj());
VisitForStackValue(prop->key());
__ ldr(LoadDescriptor::ReceiverRegister(),
MemOperand(sp, 1 * kPointerSize));
__ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
EmitKeyedPropertyLoad(prop);
break;
}
case VARIABLE:
UNREACHABLE();
} }
} }
...@@ -4526,6 +4560,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4526,6 +4560,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ str(r0, MemOperand(sp, 2 * kPointerSize)); __ str(r0, MemOperand(sp, 2 * kPointerSize));
break; break;
case KEYED_SUPER_PROPERTY:
__ str(r0, MemOperand(sp, 3 * kPointerSize));
break;
} }
} }
} }
...@@ -4559,6 +4596,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4559,6 +4596,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ str(r0, MemOperand(sp, 2 * kPointerSize)); __ str(r0, MemOperand(sp, 2 * kPointerSize));
break; break;
case KEYED_SUPER_PROPERTY:
__ str(r0, MemOperand(sp, 3 * kPointerSize));
break;
} }
} }
} }
...@@ -4625,6 +4665,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4625,6 +4665,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
break; break;
} }
case KEYED_SUPER_PROPERTY: {
EmitKeyedSuperPropertyStore(prop);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();
}
} else {
context()->Plug(r0);
}
break;
}
case KEYED_PROPERTY: { case KEYED_PROPERTY: {
__ Pop(StoreDescriptor::ReceiverRegister(), __ Pop(StoreDescriptor::ReceiverRegister(),
StoreDescriptor::NameRegister()); StoreDescriptor::NameRegister());
......
...@@ -1868,22 +1868,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1868,22 +1868,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment"); Comment cmnt(masm_, "[ Assignment");
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE;
Property* property = expr->target()->AsProperty(); Property* property = expr->target()->AsProperty();
if (property != NULL) { LhsKind assign_type = GetAssignType(property);
assign_type = (property->key()->IsPropertyName())
? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY
: NAMED_PROPERTY)
: KEYED_PROPERTY;
}
// Evaluate LHS expression. // Evaluate LHS expression.
switch (assign_type) { switch (assign_type) {
...@@ -1909,6 +1895,20 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1909,6 +1895,20 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
__ Push(scratch, result_register()); __ Push(scratch, result_register());
} }
break; break;
case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
__ Push(result_register());
VisitForAccumulatorValue(property->key());
__ Push(result_register());
if (expr->is_compound()) {
const Register scratch1 = x10;
const Register scratch2 = x11;
__ Peek(scratch1, 2 * kPointerSize);
__ Peek(scratch2, kPointerSize);
__ Push(scratch1, scratch2, result_register());
}
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
if (expr->is_compound()) { if (expr->is_compound()) {
VisitForStackValue(property->obj()); VisitForStackValue(property->obj());
...@@ -1939,6 +1939,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1939,6 +1939,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedSuperPropertyLoad(property); EmitNamedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG); PrepareForBailoutForId(property->LoadId(), TOS_REG);
break; break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property); EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG); PrepareForBailoutForId(property->LoadId(), TOS_REG);
...@@ -1989,6 +1993,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1989,6 +1993,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedSuperPropertyStore(property); EmitNamedSuperPropertyStore(property);
context()->Plug(x0); context()->Plug(x0);
break; break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyStore(property);
context()->Plug(x0);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr); EmitKeyedPropertyAssignment(expr);
break; break;
...@@ -2320,14 +2328,27 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { ...@@ -2320,14 +2328,27 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
DCHECK(key != NULL); DCHECK(key != NULL);
__ Push(x0);
__ Push(key->value()); __ Push(key->value());
__ Push(x0);
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
: Runtime::kStoreToSuper_Sloppy), : Runtime::kStoreToSuper_Sloppy),
4); 4);
} }
void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
// Assignment to named property of super.
// x0 : value
// stack : receiver ('this'), home_object, key
DCHECK(prop != NULL);
__ Push(x0);
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict
: Runtime::kStoreKeyedToSuper_Sloppy),
4);
}
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment"); ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment");
// Assignment to a property, using a keyed store IC. // Assignment to a property, using a keyed store IC.
...@@ -4101,24 +4122,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4101,24 +4122,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Comment cmnt(masm_, "[ CountOperation"); Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
// Expression can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE;
Property* prop = expr->expression()->AsProperty(); Property* prop = expr->expression()->AsProperty();
// In case of a property we use the uninitialized expression context LhsKind assign_type = GetAssignType(prop);
// of the key to detect a named property.
if (prop != NULL) {
assign_type =
(prop->key()->IsPropertyName())
? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
: KEYED_PROPERTY;
}
// Evaluate expression and get value. // Evaluate expression and get value.
if (assign_type == VARIABLE) { if (assign_type == VARIABLE) {
...@@ -4130,26 +4135,52 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4130,26 +4135,52 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
if (expr->is_postfix() && !context()->IsEffect()) { if (expr->is_postfix() && !context()->IsEffect()) {
__ Push(xzr); __ Push(xzr);
} }
if (assign_type == NAMED_PROPERTY) { switch (assign_type) {
// Put the object both on the stack and in the register. case NAMED_PROPERTY: {
VisitForStackValue(prop->obj()); // Put the object both on the stack and in the register.
__ Peek(LoadDescriptor::ReceiverRegister(), 0); VisitForStackValue(prop->obj());
EmitNamedPropertyLoad(prop); __ Peek(LoadDescriptor::ReceiverRegister(), 0);
} else if (assign_type == NAMED_SUPER_PROPERTY) { EmitNamedPropertyLoad(prop);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); break;
EmitLoadHomeObject(prop->obj()->AsSuperReference()); }
__ Push(result_register());
const Register scratch = x10; case NAMED_SUPER_PROPERTY: {
__ Peek(scratch, kPointerSize); VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
__ Push(scratch, result_register()); EmitLoadHomeObject(prop->obj()->AsSuperReference());
EmitNamedSuperPropertyLoad(prop); __ Push(result_register());
} else { const Register scratch = x10;
// KEYED_PROPERTY __ Peek(scratch, kPointerSize);
VisitForStackValue(prop->obj()); __ Push(scratch, result_register());
VisitForStackValue(prop->key()); EmitNamedSuperPropertyLoad(prop);
__ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize); break;
__ Peek(LoadDescriptor::NameRegister(), 0); }
EmitKeyedPropertyLoad(prop);
case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
VisitForAccumulatorValue(prop->key());
__ Push(result_register());
const Register scratch1 = x10;
const Register scratch2 = x11;
__ Peek(scratch1, 2 * kPointerSize);
__ Peek(scratch2, kPointerSize);
__ Push(scratch1, scratch2, result_register());
EmitKeyedSuperPropertyLoad(prop);
break;
}
case KEYED_PROPERTY: {
VisitForStackValue(prop->obj());
VisitForStackValue(prop->key());
__ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize);
__ Peek(LoadDescriptor::NameRegister(), 0);
EmitKeyedPropertyLoad(prop);
break;
}
case VARIABLE:
UNREACHABLE();
} }
} }
...@@ -4189,6 +4220,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4189,6 +4220,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ Poke(x0, kPointerSize * 2); __ Poke(x0, kPointerSize * 2);
break; break;
case KEYED_SUPER_PROPERTY:
__ Poke(x0, kPointerSize * 3);
break;
} }
} }
} }
...@@ -4222,6 +4256,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4222,6 +4256,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ Poke(x0, 2 * kXRegSize); __ Poke(x0, 2 * kXRegSize);
break; break;
case KEYED_SUPER_PROPERTY:
__ Poke(x0, 3 * kXRegSize);
break;
} }
} }
} }
...@@ -4290,6 +4327,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4290,6 +4327,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
break; break;
} }
case KEYED_SUPER_PROPERTY: {
EmitKeyedSuperPropertyStore(prop);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();
}
} else {
context()->Plug(x0);
}
break;
}
case KEYED_PROPERTY: { case KEYED_PROPERTY: {
__ Pop(StoreDescriptor::NameRegister()); __ Pop(StoreDescriptor::NameRegister());
__ Pop(StoreDescriptor::ReceiverRegister()); __ Pop(StoreDescriptor::ReceiverRegister());
......
...@@ -518,6 +518,24 @@ class FullCodeGenerator: public AstVisitor { ...@@ -518,6 +518,24 @@ class FullCodeGenerator: public AstVisitor {
// Platform-specific support for compiling assignments. // Platform-specific support for compiling assignments.
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY,
KEYED_SUPER_PROPERTY
};
static LhsKind GetAssignType(Property* property) {
if (property == NULL) return VARIABLE;
bool super_access = property->IsSuperAccess();
return (property->key()->IsPropertyName())
? (super_access ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
: (super_access ? KEYED_SUPER_PROPERTY : KEYED_PROPERTY);
}
// Load a value from a named property. // Load a value from a named property.
// The receiver is left on the stack by the IC. // The receiver is left on the stack by the IC.
void EmitNamedPropertyLoad(Property* expr); void EmitNamedPropertyLoad(Property* expr);
...@@ -569,6 +587,10 @@ class FullCodeGenerator: public AstVisitor { ...@@ -569,6 +587,10 @@ class FullCodeGenerator: public AstVisitor {
// is expected in accumulator. // is expected in accumulator.
void EmitNamedSuperPropertyStore(Property* prop); void EmitNamedSuperPropertyStore(Property* prop);
// Complete a super named property assignment. The right-hand-side value
// is expected in accumulator.
void EmitKeyedSuperPropertyStore(Property* prop);
// Complete a keyed property assignment. The receiver and key are // Complete a keyed property assignment. The receiver and key are
// expected on top of the stack and the right-hand-side value in the // expected on top of the stack and the right-hand-side value in the
// accumulator. // accumulator.
......
...@@ -1820,22 +1820,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1820,22 +1820,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment"); Comment cmnt(masm_, "[ Assignment");
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE;
Property* property = expr->target()->AsProperty(); Property* property = expr->target()->AsProperty();
if (property != NULL) { LhsKind assign_type = GetAssignType(property);
assign_type = (property->key()->IsPropertyName())
? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY
: NAMED_PROPERTY)
: KEYED_PROPERTY;
}
// Evaluate LHS expression. // Evaluate LHS expression.
switch (assign_type) { switch (assign_type) {
...@@ -1860,6 +1846,18 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1860,6 +1846,18 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
VisitForStackValue(property->obj()); VisitForStackValue(property->obj());
} }
break; break;
case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
__ Push(result_register());
VisitForAccumulatorValue(property->key());
__ Push(result_register());
if (expr->is_compound()) {
__ push(MemOperand(esp, 2 * kPointerSize));
__ push(MemOperand(esp, 2 * kPointerSize));
__ push(result_register());
}
break;
case KEYED_PROPERTY: { case KEYED_PROPERTY: {
if (expr->is_compound()) { if (expr->is_compound()) {
VisitForStackValue(property->obj()); VisitForStackValue(property->obj());
...@@ -1892,6 +1890,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1892,6 +1890,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedPropertyLoad(property); EmitNamedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG); PrepareForBailoutForId(property->LoadId(), TOS_REG);
break; break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property); EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG); PrepareForBailoutForId(property->LoadId(), TOS_REG);
...@@ -1939,7 +1941,11 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1939,7 +1941,11 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break; break;
case NAMED_SUPER_PROPERTY: case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyStore(property); EmitNamedSuperPropertyStore(property);
context()->Plug(eax); context()->Plug(result_register());
break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyStore(property);
context()->Plug(result_register());
break; break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr); EmitKeyedPropertyAssignment(expr);
...@@ -2574,14 +2580,26 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { ...@@ -2574,14 +2580,26 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
DCHECK(key != NULL); DCHECK(key != NULL);
__ push(eax);
__ push(Immediate(key->value())); __ push(Immediate(key->value()));
__ push(eax);
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
: Runtime::kStoreToSuper_Sloppy), : Runtime::kStoreToSuper_Sloppy),
4); 4);
} }
void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
// Assignment to named property of super.
// eax : value
// stack : receiver ('this'), home_object, key
__ push(eax);
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict
: Runtime::kStoreKeyedToSuper_Sloppy),
4);
}
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
// Assignment to a property, using a keyed store IC. // Assignment to a property, using a keyed store IC.
// eax : value // eax : value
...@@ -4391,24 +4409,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4391,24 +4409,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Comment cmnt(masm_, "[ CountOperation"); Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
// Expression can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE;
Property* prop = expr->expression()->AsProperty(); Property* prop = expr->expression()->AsProperty();
// In case of a property we use the uninitialized expression context LhsKind assign_type = GetAssignType(prop);
// of the key to detect a named property.
if (prop != NULL) {
assign_type =
(prop->key()->IsPropertyName())
? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
: KEYED_PROPERTY;
}
// Evaluate expression and get value. // Evaluate expression and get value.
if (assign_type == VARIABLE) { if (assign_type == VARIABLE) {
...@@ -4420,25 +4422,50 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4420,25 +4422,50 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
if (expr->is_postfix() && !context()->IsEffect()) { if (expr->is_postfix() && !context()->IsEffect()) {
__ push(Immediate(Smi::FromInt(0))); __ push(Immediate(Smi::FromInt(0)));
} }
if (assign_type == NAMED_PROPERTY) { switch (assign_type) {
// Put the object both on the stack and in the register. case NAMED_PROPERTY: {
VisitForStackValue(prop->obj()); // Put the object both on the stack and in the register.
__ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); VisitForStackValue(prop->obj());
EmitNamedPropertyLoad(prop); __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
} else if (assign_type == NAMED_SUPER_PROPERTY) { EmitNamedPropertyLoad(prop);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); break;
EmitLoadHomeObject(prop->obj()->AsSuperReference()); }
__ push(result_register());
__ push(MemOperand(esp, kPointerSize)); case NAMED_SUPER_PROPERTY: {
__ push(result_register()); VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitNamedSuperPropertyLoad(prop); EmitLoadHomeObject(prop->obj()->AsSuperReference());
} else { __ push(result_register());
VisitForStackValue(prop->obj()); __ push(MemOperand(esp, kPointerSize));
VisitForStackValue(prop->key()); __ push(result_register());
__ mov(LoadDescriptor::ReceiverRegister(), EmitNamedSuperPropertyLoad(prop);
Operand(esp, kPointerSize)); // Object. break;
__ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); // Key. }
EmitKeyedPropertyLoad(prop);
case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ push(result_register());
VisitForAccumulatorValue(prop->key());
__ push(result_register());
__ push(MemOperand(esp, 2 * kPointerSize));
__ push(MemOperand(esp, 2 * kPointerSize));
__ push(result_register());
EmitKeyedSuperPropertyLoad(prop);
break;
}
case KEYED_PROPERTY: {
VisitForStackValue(prop->obj());
VisitForStackValue(prop->key());
__ mov(LoadDescriptor::ReceiverRegister(),
Operand(esp, kPointerSize)); // Object.
__ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); // Key.
EmitKeyedPropertyLoad(prop);
break;
}
case VARIABLE:
UNREACHABLE();
} }
} }
...@@ -4476,6 +4503,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4476,6 +4503,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ mov(Operand(esp, 2 * kPointerSize), eax); __ mov(Operand(esp, 2 * kPointerSize), eax);
break; break;
case KEYED_SUPER_PROPERTY:
__ mov(Operand(esp, 3 * kPointerSize), eax);
break;
} }
} }
} }
...@@ -4517,6 +4547,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4517,6 +4547,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ mov(Operand(esp, 2 * kPointerSize), eax); __ mov(Operand(esp, 2 * kPointerSize), eax);
break; break;
case KEYED_SUPER_PROPERTY:
__ mov(Operand(esp, 3 * kPointerSize), eax);
break;
} }
} }
} }
...@@ -4584,6 +4617,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4584,6 +4617,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
break; break;
} }
case KEYED_SUPER_PROPERTY: {
EmitKeyedSuperPropertyStore(prop);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();
}
} else {
context()->Plug(eax);
}
break;
}
case KEYED_PROPERTY: { case KEYED_PROPERTY: {
__ pop(StoreDescriptor::NameRegister()); __ pop(StoreDescriptor::NameRegister());
__ pop(StoreDescriptor::ReceiverRegister()); __ pop(StoreDescriptor::ReceiverRegister());
......
...@@ -76,83 +76,6 @@ static Object* LoadFromSuper(Isolate* isolate, Handle<Object> receiver, ...@@ -76,83 +76,6 @@ static Object* LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
} }
RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
return LoadFromSuper(isolate, receiver, home_object, name);
}
RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Runtime::ToName(isolate, key));
uint32_t index;
if (name->AsArrayIndex(&index)) {
return ThrowUnsupportedSuper(isolate);
}
return LoadFromSuper(isolate, receiver, home_object, name);
}
static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
Handle<Object> receiver, Handle<Name> name,
Handle<Object> value, StrictMode strict_mode) {
if (home_object->IsAccessCheckNeeded() &&
!isolate->MayNamedAccess(home_object, name, v8::ACCESS_SET)) {
isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_SET);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
}
PrototypeIterator iter(isolate, home_object);
Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
Object::SetProperty(&it, value, strict_mode,
Object::CERTAINLY_NOT_STORE_FROM_KEYED,
Object::SUPER_PROPERTY));
return *result;
}
RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
HandleScope scope(isolate);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 3);
return StoreToSuper(isolate, home_object, receiver, name, value, STRICT);
}
RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
HandleScope scope(isolate);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 3);
return StoreToSuper(isolate, home_object, receiver, name, value, SLOPPY);
}
RUNTIME_FUNCTION(Runtime_DefineClass) { RUNTIME_FUNCTION(Runtime_DefineClass) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 6); DCHECK(args.length() == 6);
...@@ -284,5 +207,122 @@ RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) { ...@@ -284,5 +207,122 @@ RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
source, Handle<Smi>::cast(start_position)->value(), source, Handle<Smi>::cast(start_position)->value(),
Handle<Smi>::cast(end_position)->value()); Handle<Smi>::cast(end_position)->value());
} }
RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
return LoadFromSuper(isolate, receiver, home_object, name);
}
RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Runtime::ToName(isolate, key));
uint32_t index;
if (name->AsArrayIndex(&index)) {
// TODO(dslomov): Implement.
return ThrowUnsupportedSuper(isolate);
}
return LoadFromSuper(isolate, receiver, home_object, name);
}
static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
Handle<Object> receiver, Handle<Name> name,
Handle<Object> value, StrictMode strict_mode) {
if (home_object->IsAccessCheckNeeded() &&
!isolate->MayNamedAccess(home_object, name, v8::ACCESS_SET)) {
isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_SET);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
}
PrototypeIterator iter(isolate, home_object);
Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
Object::SetProperty(&it, value, strict_mode,
Object::CERTAINLY_NOT_STORE_FROM_KEYED,
Object::SUPER_PROPERTY));
return *result;
}
RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
HandleScope scope(isolate);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
return StoreToSuper(isolate, home_object, receiver, name, value, STRICT);
}
RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
HandleScope scope(isolate);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
return StoreToSuper(isolate, home_object, receiver, name, value, SLOPPY);
}
static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object,
Handle<Object> receiver, Handle<Object> key,
Handle<Object> value, StrictMode strict_mode) {
Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Runtime::ToName(isolate, key));
uint32_t index;
if (name->AsArrayIndex(&index)) {
// TODO(dslomov): Implement.
return ThrowUnsupportedSuper(isolate);
}
return StoreToSuper(isolate, home_object, receiver, name, value, strict_mode);
}
RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Strict) {
HandleScope scope(isolate);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
return StoreKeyedToSuper(isolate, home_object, receiver, key, value, STRICT);
}
RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy) {
HandleScope scope(isolate);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
return StoreKeyedToSuper(isolate, home_object, receiver, key, value, SLOPPY);
}
} }
} // namespace v8::internal } // namespace v8::internal
...@@ -187,14 +187,16 @@ namespace internal { ...@@ -187,14 +187,16 @@ namespace internal {
/* Classes support */ \ /* Classes support */ \
F(ToMethod, 2, 1) \ F(ToMethod, 2, 1) \
F(HomeObjectSymbol, 0, 1) \ F(HomeObjectSymbol, 0, 1) \
F(DefineClass, 6, 1) \
F(ClassGetSourceCode, 1, 1) \
F(ThrowNonMethodError, 0, 1) \ F(ThrowNonMethodError, 0, 1) \
F(ThrowUnsupportedSuperError, 0, 1) \ F(ThrowUnsupportedSuperError, 0, 1) \
F(LoadFromSuper, 3, 1) \ F(LoadFromSuper, 3, 1) \
F(LoadKeyedFromSuper, 3, 1) \ F(LoadKeyedFromSuper, 3, 1) \
F(StoreToSuper_Strict, 4, 1) \ F(StoreToSuper_Strict, 4, 1) \
F(StoreToSuper_Sloppy, 4, 1) \ F(StoreToSuper_Sloppy, 4, 1) \
F(DefineClass, 6, 1) \ F(StoreKeyedToSuper_Strict, 4, 1) \
F(ClassGetSourceCode, 1, 1) F(StoreKeyedToSuper_Sloppy, 4, 1)
#define RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \ #define RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \
......
...@@ -1854,22 +1854,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1854,22 +1854,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment"); Comment cmnt(masm_, "[ Assignment");
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE;
Property* property = expr->target()->AsProperty(); Property* property = expr->target()->AsProperty();
if (property != NULL) { LhsKind assign_type = GetAssignType(property);
assign_type = (property->key()->IsPropertyName())
? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY
: NAMED_PROPERTY)
: KEYED_PROPERTY;
}
// Evaluate LHS expression. // Evaluate LHS expression.
switch (assign_type) { switch (assign_type) {
...@@ -1894,6 +1880,18 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1894,6 +1880,18 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
__ Push(result_register()); __ Push(result_register());
} }
break; break;
case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
__ Push(result_register());
VisitForAccumulatorValue(property->key());
__ Push(result_register());
if (expr->is_compound()) {
__ Push(MemOperand(rsp, 2 * kPointerSize));
__ Push(MemOperand(rsp, 2 * kPointerSize));
__ Push(result_register());
}
break;
case KEYED_PROPERTY: { case KEYED_PROPERTY: {
if (expr->is_compound()) { if (expr->is_compound()) {
VisitForStackValue(property->obj()); VisitForStackValue(property->obj());
...@@ -1925,6 +1923,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1925,6 +1923,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedSuperPropertyLoad(property); EmitNamedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG); PrepareForBailoutForId(property->LoadId(), TOS_REG);
break; break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property); EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG); PrepareForBailoutForId(property->LoadId(), TOS_REG);
...@@ -1974,6 +1976,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1974,6 +1976,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedSuperPropertyStore(property); EmitNamedSuperPropertyStore(property);
context()->Plug(rax); context()->Plug(rax);
break; break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyStore(property);
context()->Plug(rax);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr); EmitKeyedPropertyAssignment(expr);
break; break;
...@@ -2571,14 +2577,27 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { ...@@ -2571,14 +2577,27 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
DCHECK(key != NULL); DCHECK(key != NULL);
__ Push(rax);
__ Push(key->value()); __ Push(key->value());
__ Push(rax);
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
: Runtime::kStoreToSuper_Sloppy), : Runtime::kStoreToSuper_Sloppy),
4); 4);
} }
void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
// Assignment to named property of super.
// rax : value
// stack : receiver ('this'), home_object, key
DCHECK(prop != NULL);
__ Push(rax);
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict
: Runtime::kStoreKeyedToSuper_Sloppy),
4);
}
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
// Assignment to a property, using a keyed store IC. // Assignment to a property, using a keyed store IC.
...@@ -4406,24 +4425,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4406,24 +4425,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Comment cmnt(masm_, "[ CountOperation"); Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
// Expression can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE;
Property* prop = expr->expression()->AsProperty(); Property* prop = expr->expression()->AsProperty();
// In case of a property we use the uninitialized expression context LhsKind assign_type = GetAssignType(prop);
// of the key to detect a named property.
if (prop != NULL) {
assign_type =
(prop->key()->IsPropertyName())
? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
: KEYED_PROPERTY;
}
// Evaluate expression and get value. // Evaluate expression and get value.
if (assign_type == VARIABLE) { if (assign_type == VARIABLE) {
...@@ -4435,25 +4438,50 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4435,25 +4438,50 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
if (expr->is_postfix() && !context()->IsEffect()) { if (expr->is_postfix() && !context()->IsEffect()) {
__ Push(Smi::FromInt(0)); __ Push(Smi::FromInt(0));
} }
if (assign_type == NAMED_PROPERTY) { switch (assign_type) {
VisitForStackValue(prop->obj()); case NAMED_PROPERTY: {
__ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0)); VisitForStackValue(prop->obj());
EmitNamedPropertyLoad(prop); __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
} else if (assign_type == NAMED_SUPER_PROPERTY) { EmitNamedPropertyLoad(prop);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); break;
EmitLoadHomeObject(prop->obj()->AsSuperReference()); }
__ Push(result_register());
__ Push(MemOperand(rsp, kPointerSize)); case NAMED_SUPER_PROPERTY: {
__ Push(result_register()); VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitNamedSuperPropertyLoad(prop); EmitLoadHomeObject(prop->obj()->AsSuperReference());
} else { __ Push(result_register());
VisitForStackValue(prop->obj()); __ Push(MemOperand(rsp, kPointerSize));
VisitForStackValue(prop->key()); __ Push(result_register());
// Leave receiver on stack EmitNamedSuperPropertyLoad(prop);
__ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize)); break;
// Copy of key, needed for later store. }
__ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0));
EmitKeyedPropertyLoad(prop); case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
VisitForAccumulatorValue(prop->key());
__ Push(result_register());
__ Push(MemOperand(rsp, 2 * kPointerSize));
__ Push(MemOperand(rsp, 2 * kPointerSize));
__ Push(result_register());
EmitKeyedSuperPropertyLoad(prop);
break;
}
case KEYED_PROPERTY: {
VisitForStackValue(prop->obj());
VisitForStackValue(prop->key());
// Leave receiver on stack
__ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize));
// Copy of key, needed for later store.
__ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0));
EmitKeyedPropertyLoad(prop);
break;
}
case VARIABLE:
UNREACHABLE();
} }
} }
...@@ -4491,6 +4519,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4491,6 +4519,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ movp(Operand(rsp, 2 * kPointerSize), rax); __ movp(Operand(rsp, 2 * kPointerSize), rax);
break; break;
case KEYED_SUPER_PROPERTY:
__ movp(Operand(rsp, 3 * kPointerSize), rax);
break;
} }
} }
} }
...@@ -4529,6 +4560,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4529,6 +4560,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ movp(Operand(rsp, 2 * kPointerSize), rax); __ movp(Operand(rsp, 2 * kPointerSize), rax);
break; break;
case KEYED_SUPER_PROPERTY:
__ movp(Operand(rsp, 3 * kPointerSize), rax);
break;
} }
} }
} }
...@@ -4596,6 +4630,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4596,6 +4630,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
break; break;
} }
case KEYED_SUPER_PROPERTY: {
EmitKeyedSuperPropertyStore(prop);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();
}
} else {
context()->Plug(rax);
}
break;
}
case KEYED_PROPERTY: { case KEYED_PROPERTY: {
__ Pop(StoreDescriptor::NameRegister()); __ Pop(StoreDescriptor::NameRegister());
__ Pop(StoreDescriptor::ReceiverRegister()); __ Pop(StoreDescriptor::ReceiverRegister());
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment