Refactor code for generating assignments in the fast compiler.

1. Refactor the structure of VisitAssignment: The existing code is not ideal 
to be extended with support for compound assignments.

2. Reuse common code for keyed property assigments: Now variables rewritten 
to a property (.arguments access) are treated like normal keyed property
assignments. This allows us to remove some code duplication.

Review URL: http://codereview.chromium.org/456024

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3425 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a5aedaea
......@@ -863,7 +863,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
Variable* var = expr->target()->AsVariableProxy()->AsVariable();
ASSERT(var != NULL);
ASSERT(var->is_global() || var->slot() != NULL);
if (var->is_global()) {
// Assignment to a global variable. Use inline caching for the
// assignment. Right-hand-side value is passed in r0, variable name in
......@@ -976,35 +976,6 @@ void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
UNREACHABLE();
break;
}
} else {
Property* property = var->rewrite()->AsProperty();
ASSERT_NOT_NULL(property);
// Load object and key onto the stack.
Slot* object_slot = property->obj()->AsSlot();
ASSERT_NOT_NULL(object_slot);
Move(Expression::kValue, object_slot, r0);
Literal* key_literal = property->key()->AsLiteral();
ASSERT_NOT_NULL(key_literal);
Move(Expression::kValue, key_literal);
// Value to store was pushed before object and key on the stack.
__ ldr(r0, MemOperand(sp, 2 * kPointerSize));
// Arguments to ic is value in r0, object and key on stack.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
if (expr->context() == Expression::kEffect) {
__ add(sp, sp, Operand(3 * kPointerSize));
} else if (expr->context() == Expression::kValue) {
// Value is still on the stack in esp[2 * kPointerSize]
__ add(sp, sp, Operand(2 * kPointerSize));
} else {
__ ldr(r0, MemOperand(sp, 2 * kPointerSize));
DropAndMove(expr->context(), r0, 3);
}
}
}
......
......@@ -891,28 +891,19 @@ void CodeGenSelector::VisitAssignment(Assignment* expr) {
Variable* var = expr->target()->AsVariableProxy()->AsVariable();
Property* prop = expr->target()->AsProperty();
ASSERT(var == NULL || prop == NULL);
if (var != NULL) {
// All global variables are supported.
if (!var->is_global()) {
if (var->slot() == NULL) {
Property* property = var->AsProperty();
if (property == NULL) {
BAILOUT("non-global/non-slot/non-property assignment");
}
if (property->obj()->AsSlot() == NULL) {
BAILOUT("variable rewritten to property non slot object assignment");
}
if (property->key()->AsLiteral() == NULL) {
BAILOUT("variable rewritten to property non literal key assignment");
}
} else {
Slot::Type type = var->slot()->type();
if (type == Slot::LOOKUP) {
BAILOUT("Lookup slot");
}
ASSERT(var->slot() != NULL);
Slot::Type type = var->slot()->type();
if (type == Slot::LOOKUP) {
BAILOUT("Lookup slot");
}
}
} else if (prop != NULL) {
ASSERT(prop->obj()->context() == Expression::kUninitialized ||
prop->obj()->context() == Expression::kValue);
ProcessExpression(prop->obj(), Expression::kValue);
CHECK_BAILOUT;
// We will only visit the key during code generation for keyed property
......@@ -923,6 +914,8 @@ void CodeGenSelector::VisitAssignment(Assignment* expr) {
if (lit == NULL ||
!lit->handle()->IsSymbol() ||
String::cast(*(lit->handle()))->AsArrayIndex(&ignored)) {
ASSERT(prop->key()->context() == Expression::kUninitialized ||
prop->key()->context() == Expression::kValue);
ProcessExpression(prop->key(), Expression::kValue);
CHECK_BAILOUT;
}
......
......@@ -505,35 +505,41 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// Record source code position of the (possible) IC call.
SetSourcePosition(expr->position());
Expression* rhs = expr->value();
// Left-hand side can only be a property, a global or a (parameter or
// local) slot.
Variable* var = expr->target()->AsVariableProxy()->AsVariable();
// Left-hand side can only be a property, a global or a (parameter or local)
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
LhsKind assign_type = VARIABLE;
Property* prop = expr->target()->AsProperty();
if (var != NULL) {
Visit(rhs);
ASSERT_EQ(Expression::kValue, rhs->context());
EmitVariableAssignment(expr);
} else if (prop != NULL) {
// Assignment to a property.
Visit(prop->obj());
ASSERT_EQ(Expression::kValue, prop->obj()->context());
// Use the expression context of the key subexpression to detect whether
// we have decided to us a named or keyed IC.
if (prop->key()->context() == Expression::kUninitialized) {
ASSERT(prop->key()->AsLiteral() != NULL);
// In case of a property we use the uninitialized expression context
// of the key to detect a named property.
if (prop != NULL) {
assign_type = (prop->key()->context() == Expression::kUninitialized)
? NAMED_PROPERTY
: KEYED_PROPERTY;
}
Expression* rhs = expr->value();
ASSERT_EQ(Expression::kValue, rhs->context());
switch (assign_type) {
case VARIABLE:
Visit(rhs);
EmitVariableAssignment(expr);
break;
case NAMED_PROPERTY:
Visit(prop->obj());
ASSERT_EQ(Expression::kValue, prop->obj()->context());
Visit(rhs);
ASSERT_EQ(Expression::kValue, rhs->context());
EmitNamedPropertyAssignment(expr);
} else {
break;
case KEYED_PROPERTY:
Visit(prop->obj());
ASSERT_EQ(Expression::kValue, prop->obj()->context());
Visit(prop->key());
ASSERT_EQ(Expression::kValue, prop->key()->context());
Visit(rhs);
ASSERT_EQ(Expression::kValue, rhs->context());
EmitKeyedPropertyAssignment(expr);
}
} else {
UNREACHABLE();
break;
}
}
......
......@@ -855,7 +855,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
Variable* var = expr->target()->AsVariableProxy()->AsVariable();
ASSERT(var != NULL);
ASSERT(var->is_global() || var->slot() != NULL);
if (var->is_global()) {
// Assignment to a global variable. Use inline caching for the
// assignment. Right-hand-side value is passed in eax, variable name in
......@@ -960,35 +960,6 @@ void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
UNREACHABLE();
break;
}
} else {
Property* property = var->rewrite()->AsProperty();
ASSERT_NOT_NULL(property);
// Load object and key onto the stack.
Slot* object_slot = property->obj()->AsSlot();
ASSERT_NOT_NULL(object_slot);
Move(Expression::kValue, object_slot, eax);
Literal* key_literal = property->key()->AsLiteral();
ASSERT_NOT_NULL(key_literal);
Move(Expression::kValue, key_literal);
// Value to store was pushed before object and key on the stack.
__ mov(eax, Operand(esp, 2 * kPointerSize));
// Arguments to ic is value in eax, object and key on stack.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET);
if (expr->context() == Expression::kEffect) {
__ add(Operand(esp), Immediate(3 * kPointerSize));
} else if (expr->context() == Expression::kValue) {
// Value is still on the stack in esp[2 * kPointerSize]
__ add(Operand(esp), Immediate(2 * kPointerSize));
} else {
__ mov(eax, Operand(esp, 2 * kPointerSize));
DropAndMove(expr->context(), eax, 3);
}
}
}
......
......@@ -856,7 +856,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
Variable* var = expr->target()->AsVariableProxy()->AsVariable();
ASSERT(var != NULL);
ASSERT(var->is_global() || var->slot() != NULL);
if (var->is_global()) {
// Assignment to a global variable. Use inline caching for the
// assignment. Right-hand-side value is passed in rax, variable name in
......@@ -961,36 +961,6 @@ void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
UNREACHABLE();
break;
}
} else {
Property* property = var->AsProperty();
ASSERT_NOT_NULL(property);
// A variable has been rewritten into a property on an object.
// Load object and key onto the stack.
Slot* object_slot = property->obj()->AsSlot();
ASSERT_NOT_NULL(object_slot);
Move(Expression::kValue, object_slot, rax);
Literal* key_literal = property->key()->AsLiteral();
ASSERT_NOT_NULL(key_literal);
Move(Expression::kValue, key_literal);
// Value to store was pushed before object and key on the stack.
__ movq(rax, Operand(rsp, 2 * kPointerSize));
// Arguments to ic is value in rax, object and key on stack.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET);
if (expr->context() == Expression::kEffect) {
__ addq(rsp, Immediate(3 * kPointerSize));
} else if (expr->context() == Expression::kValue) {
// Value is still on the stack in rsp[2 * kPointerSize]
__ addq(rsp, Immediate(2 * kPointerSize));
} else {
__ movq(rax, Operand(rsp, 2 * kPointerSize));
DropAndMove(expr->context(), rax, 3);
}
}
}
......
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