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
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);
- }
}
}
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
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;
}
// 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;
}
}
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
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);
- }
}
}
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
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);
- }
}
}