Commit ec209c77 authored by dslomov@chromium.org's avatar dslomov@chromium.org

Support count operations on super named properties.

R=ishell@chromium.org
BUG=v8:3330
LOG=N

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24290 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5b742b35
...@@ -2003,7 +2003,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -2003,7 +2003,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedPropertyAssignment(expr); EmitNamedPropertyAssignment(expr);
break; break;
case NAMED_SUPER_PROPERTY: case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyAssignment(expr); EmitNamedSuperPropertyStore(property);
context()->Plug(r0);
break; break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr); EmitKeyedPropertyAssignment(expr);
...@@ -2634,11 +2635,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { ...@@ -2634,11 +2635,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
} }
void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) { void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
// Assignment to named property of super. // Assignment to named property of super.
// r0 : value // r0 : value
// stack : receiver ('this'), home_object // stack : receiver ('this'), home_object
Property* prop = expr->target()->AsProperty();
DCHECK(prop != NULL); DCHECK(prop != NULL);
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
DCHECK(key != NULL); DCHECK(key != NULL);
...@@ -2648,7 +2648,6 @@ void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) { ...@@ -2648,7 +2648,6 @@ void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) {
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
: Runtime::kStoreToSuper_Sloppy), : Runtime::kStoreToSuper_Sloppy),
4); 4);
context()->Plug(r0);
} }
...@@ -4377,19 +4376,21 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4377,19 +4376,21 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Expression can only be a property, a global or a (parameter or local) // Expression can only be a property, a global or a (parameter or local)
// slot. // slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE; 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 // In case of a property we use the uninitialized expression context
// of the key to detect a named property. // of the key to detect a named property.
if (prop != NULL) { if (prop != NULL) {
assign_type = assign_type =
(prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; (prop->key()->IsPropertyName())
if (prop->IsSuperAccess()) { ? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
// throw exception. : KEYED_PROPERTY;
VisitSuperReference(prop->obj()->AsSuperReference());
return;
}
} }
// Evaluate expression and get value. // Evaluate expression and get value.
...@@ -4408,6 +4409,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4408,6 +4409,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
__ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
EmitNamedPropertyLoad(prop); EmitNamedPropertyLoad(prop);
} else if (assign_type == NAMED_SUPER_PROPERTY) {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
const Register scratch = r1;
__ ldr(scratch, MemOperand(sp, kPointerSize));
__ Push(scratch);
__ Push(result_register());
EmitNamedSuperPropertyLoad(prop);
} else { } else {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
VisitForStackValue(prop->key()); VisitForStackValue(prop->key());
...@@ -4448,6 +4458,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4448,6 +4458,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_PROPERTY: case NAMED_PROPERTY:
__ str(r0, MemOperand(sp, kPointerSize)); __ str(r0, MemOperand(sp, kPointerSize));
break; break;
case NAMED_SUPER_PROPERTY:
__ str(r0, MemOperand(sp, 2 * kPointerSize));
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ str(r0, MemOperand(sp, 2 * kPointerSize)); __ str(r0, MemOperand(sp, 2 * kPointerSize));
break; break;
...@@ -4478,6 +4491,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4478,6 +4491,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_PROPERTY: case NAMED_PROPERTY:
__ str(r0, MemOperand(sp, kPointerSize)); __ str(r0, MemOperand(sp, kPointerSize));
break; break;
case NAMED_SUPER_PROPERTY:
__ str(r0, MemOperand(sp, 2 * kPointerSize));
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ str(r0, MemOperand(sp, 2 * kPointerSize)); __ str(r0, MemOperand(sp, 2 * kPointerSize));
break; break;
...@@ -4536,6 +4552,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4536,6 +4552,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
break; break;
} }
case NAMED_SUPER_PROPERTY: {
EmitNamedSuperPropertyStore(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());
......
...@@ -1980,7 +1980,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1980,7 +1980,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedPropertyAssignment(expr); EmitNamedPropertyAssignment(expr);
break; break;
case NAMED_SUPER_PROPERTY: case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyAssignment(expr); EmitNamedSuperPropertyStore(property);
context()->Plug(x0);
break; break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr); EmitKeyedPropertyAssignment(expr);
...@@ -2297,11 +2298,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { ...@@ -2297,11 +2298,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
} }
void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) { void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
// Assignment to named property of super. // Assignment to named property of super.
// x0 : value // x0 : value
// stack : receiver ('this'), home_object // stack : receiver ('this'), home_object
Property* prop = expr->target()->AsProperty();
DCHECK(prop != NULL); DCHECK(prop != NULL);
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
DCHECK(key != NULL); DCHECK(key != NULL);
...@@ -2311,7 +2311,6 @@ void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) { ...@@ -2311,7 +2311,6 @@ void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) {
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
: Runtime::kStoreToSuper_Sloppy), : Runtime::kStoreToSuper_Sloppy),
4); 4);
context()->Plug(x0);
} }
...@@ -4042,19 +4041,21 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4042,19 +4041,21 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Expression can only be a property, a global or a (parameter or local) // Expression can only be a property, a global or a (parameter or local)
// slot. // slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE; 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 // In case of a property we use the uninitialized expression context
// of the key to detect a named property. // of the key to detect a named property.
if (prop != NULL) { if (prop != NULL) {
assign_type = assign_type =
(prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; (prop->key()->IsPropertyName())
if (prop->IsSuperAccess()) { ? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
// throw exception. : KEYED_PROPERTY;
VisitSuperReference(prop->obj()->AsSuperReference());
return;
}
} }
// Evaluate expression and get value. // Evaluate expression and get value.
...@@ -4072,6 +4073,14 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4072,6 +4073,14 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
__ Peek(LoadDescriptor::ReceiverRegister(), 0); __ Peek(LoadDescriptor::ReceiverRegister(), 0);
EmitNamedPropertyLoad(prop); EmitNamedPropertyLoad(prop);
} else if (assign_type == NAMED_SUPER_PROPERTY) {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
const Register scratch = x10;
__ Peek(scratch, kPointerSize);
__ Push(scratch, result_register());
EmitNamedSuperPropertyLoad(prop);
} else { } else {
// KEYED_PROPERTY // KEYED_PROPERTY
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
...@@ -4112,6 +4121,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4112,6 +4121,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_PROPERTY: case NAMED_PROPERTY:
__ Poke(x0, kPointerSize); __ Poke(x0, kPointerSize);
break; break;
case NAMED_SUPER_PROPERTY:
__ Poke(x0, kPointerSize * 2);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ Poke(x0, kPointerSize * 2); __ Poke(x0, kPointerSize * 2);
break; break;
...@@ -4142,6 +4154,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4142,6 +4154,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_PROPERTY: case NAMED_PROPERTY:
__ Poke(x0, kXRegSize); __ Poke(x0, kXRegSize);
break; break;
case NAMED_SUPER_PROPERTY:
__ Poke(x0, 2 * kXRegSize);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ Poke(x0, 2 * kXRegSize); __ Poke(x0, 2 * kXRegSize);
break; break;
...@@ -4202,6 +4217,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4202,6 +4217,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
break; break;
} }
case NAMED_SUPER_PROPERTY: {
EmitNamedSuperPropertyStore(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());
......
...@@ -562,7 +562,7 @@ class FullCodeGenerator: public AstVisitor { ...@@ -562,7 +562,7 @@ class FullCodeGenerator: public AstVisitor {
// Complete a super named property assignment. The right-hand-side value // Complete a super named property assignment. The right-hand-side value
// is expected in accumulator. // is expected in accumulator.
void EmitNamedSuperPropertyAssignment(Assignment* expr); void EmitNamedSuperPropertyStore(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
......
...@@ -1932,7 +1932,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1932,7 +1932,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedPropertyAssignment(expr); EmitNamedPropertyAssignment(expr);
break; break;
case NAMED_SUPER_PROPERTY: case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyAssignment(expr); EmitNamedSuperPropertyStore(property);
context()->Plug(eax);
break; break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr); EmitKeyedPropertyAssignment(expr);
...@@ -2551,11 +2552,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { ...@@ -2551,11 +2552,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
} }
void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) { void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
// Assignment to named property of super. // Assignment to named property of super.
// eax : value // eax : value
// stack : receiver ('this'), home_object // stack : receiver ('this'), home_object
Property* prop = expr->target()->AsProperty();
DCHECK(prop != NULL); DCHECK(prop != NULL);
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
DCHECK(key != NULL); DCHECK(key != NULL);
...@@ -2565,7 +2565,6 @@ void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) { ...@@ -2565,7 +2565,6 @@ void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) {
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
: Runtime::kStoreToSuper_Sloppy), : Runtime::kStoreToSuper_Sloppy),
4); 4);
context()->Plug(eax);
} }
...@@ -4335,19 +4334,21 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4335,19 +4334,21 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Expression can only be a property, a global or a (parameter or local) // Expression can only be a property, a global or a (parameter or local)
// slot. // slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE; 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 // In case of a property we use the uninitialized expression context
// of the key to detect a named property. // of the key to detect a named property.
if (prop != NULL) { if (prop != NULL) {
assign_type = assign_type =
(prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; (prop->key()->IsPropertyName())
if (prop->IsSuperAccess()) { ? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
// throw exception. : KEYED_PROPERTY;
VisitSuperReference(prop->obj()->AsSuperReference());
return;
}
} }
// Evaluate expression and get value. // Evaluate expression and get value.
...@@ -4365,6 +4366,13 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4365,6 +4366,13 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
__ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
EmitNamedPropertyLoad(prop); EmitNamedPropertyLoad(prop);
} else if (assign_type == NAMED_SUPER_PROPERTY) {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ push(result_register());
__ push(MemOperand(esp, kPointerSize));
__ push(result_register());
EmitNamedSuperPropertyLoad(prop);
} else { } else {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
VisitForStackValue(prop->key()); VisitForStackValue(prop->key());
...@@ -4403,6 +4411,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4403,6 +4411,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_PROPERTY: case NAMED_PROPERTY:
__ mov(Operand(esp, kPointerSize), eax); __ mov(Operand(esp, kPointerSize), eax);
break; break;
case NAMED_SUPER_PROPERTY:
__ mov(Operand(esp, 2 * kPointerSize), eax);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ mov(Operand(esp, 2 * kPointerSize), eax); __ mov(Operand(esp, 2 * kPointerSize), eax);
break; break;
...@@ -4441,6 +4452,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4441,6 +4452,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_PROPERTY: case NAMED_PROPERTY:
__ mov(Operand(esp, kPointerSize), eax); __ mov(Operand(esp, kPointerSize), eax);
break; break;
case NAMED_SUPER_PROPERTY:
__ mov(Operand(esp, 2 * kPointerSize), eax);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ mov(Operand(esp, 2 * kPointerSize), eax); __ mov(Operand(esp, 2 * kPointerSize), eax);
break; break;
...@@ -4500,6 +4514,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4500,6 +4514,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
break; break;
} }
case NAMED_SUPER_PROPERTY: {
EmitNamedSuperPropertyStore(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());
......
...@@ -1964,7 +1964,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1964,7 +1964,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedPropertyAssignment(expr); EmitNamedPropertyAssignment(expr);
break; break;
case NAMED_SUPER_PROPERTY: case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyAssignment(expr); EmitNamedSuperPropertyStore(property);
context()->Plug(rax);
break; break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr); EmitKeyedPropertyAssignment(expr);
...@@ -2547,11 +2548,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { ...@@ -2547,11 +2548,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
} }
void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) { void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
// Assignment to named property of super. // Assignment to named property of super.
// rax : value // rax : value
// stack : receiver ('this'), home_object // stack : receiver ('this'), home_object
Property* prop = expr->target()->AsProperty();
DCHECK(prop != NULL); DCHECK(prop != NULL);
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
DCHECK(key != NULL); DCHECK(key != NULL);
...@@ -2561,7 +2561,6 @@ void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) { ...@@ -2561,7 +2561,6 @@ void FullCodeGenerator::EmitNamedSuperPropertyAssignment(Assignment* expr) {
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
: Runtime::kStoreToSuper_Sloppy), : Runtime::kStoreToSuper_Sloppy),
4); 4);
context()->Plug(rax);
} }
...@@ -4348,19 +4347,21 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4348,19 +4347,21 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Expression can only be a property, a global or a (parameter or local) // Expression can only be a property, a global or a (parameter or local)
// slot. // slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY
};
LhsKind assign_type = VARIABLE; 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 // In case of a property we use the uninitialized expression context
// of the key to detect a named property. // of the key to detect a named property.
if (prop != NULL) { if (prop != NULL) {
assign_type = assign_type =
(prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; (prop->key()->IsPropertyName())
if (prop->IsSuperAccess()) { ? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
// throw exception. : KEYED_PROPERTY;
VisitSuperReference(prop->obj()->AsSuperReference());
return;
}
} }
// Evaluate expression and get value. // Evaluate expression and get value.
...@@ -4377,6 +4378,13 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4377,6 +4378,13 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
__ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0)); __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
EmitNamedPropertyLoad(prop); EmitNamedPropertyLoad(prop);
} else if (assign_type == NAMED_SUPER_PROPERTY) {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
__ Push(MemOperand(rsp, kPointerSize));
__ Push(result_register());
EmitNamedSuperPropertyLoad(prop);
} else { } else {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
VisitForStackValue(prop->key()); VisitForStackValue(prop->key());
...@@ -4416,6 +4424,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4416,6 +4424,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_PROPERTY: case NAMED_PROPERTY:
__ movp(Operand(rsp, kPointerSize), rax); __ movp(Operand(rsp, kPointerSize), rax);
break; break;
case NAMED_SUPER_PROPERTY:
__ movp(Operand(rsp, 2 * kPointerSize), rax);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ movp(Operand(rsp, 2 * kPointerSize), rax); __ movp(Operand(rsp, 2 * kPointerSize), rax);
break; break;
...@@ -4451,6 +4462,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4451,6 +4462,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_PROPERTY: case NAMED_PROPERTY:
__ movp(Operand(rsp, kPointerSize), rax); __ movp(Operand(rsp, kPointerSize), rax);
break; break;
case NAMED_SUPER_PROPERTY:
__ movp(Operand(rsp, 2 * kPointerSize), rax);
break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
__ movp(Operand(rsp, 2 * kPointerSize), rax); __ movp(Operand(rsp, 2 * kPointerSize), rax);
break; break;
...@@ -4510,6 +4524,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4510,6 +4524,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
break; break;
} }
case NAMED_SUPER_PROPERTY: {
EmitNamedSuperPropertyStore(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());
......
...@@ -225,10 +225,58 @@ ...@@ -225,10 +225,58 @@
}()); }());
(function TestCountOperations() {
function Base() {}
Base.prototype = {
constructor: Base,
get x() {
return this._x;
},
set x(v) {
this._x = v;
},
_x: 1
};
function Derived() {}
Derived.__proto__ = Base;
Derived.prototype = {
__proto__: Base.prototype,
constructor: Derived,
_x: 2
};
Derived.prototype.testCounts = function() {
assertEquals(2, this._x);
assertEquals(2, super.x);
super.x++;
assertEquals(3, super.x);
++super.x;
assertEquals(4, super.x);
assertEquals(4, super.x++);
assertEquals(5, super.x);
assertEquals(6, ++super.x);
assertEquals(6, super.x);
assertEquals(6, this._x);
super.x--;
assertEquals(5, super.x);
--super.x;
assertEquals(4, super.x);
assertEquals(4, super.x--);
assertEquals(3, super.x);
assertEquals(2, --super.x);
assertEquals(2, super.x);
assertEquals(2, this._x);
}.toMethod(Derived.prototype);
new Derived().testCounts();
}());
(function TestUnsupportedCases() { (function TestUnsupportedCases() {
function f1(x) { return super[x]; } function f1(x) { return super[x]; }
function f2(x) { super[x] = 5; }
var o = {} var o = {}
assertThrows(function(){f1.toMethod(o)(x);}, ReferenceError); assertThrows(function(){f1.toMethod(o)(x);}, ReferenceError);
function f2() { super.x++; } assertThrows(function(){f2.toMethod(o)(x);}, ReferenceError);
assertThrows(function(){f2.toMethod(o)();}, ReferenceError);
}()); }());
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