Index: src/x64/fast-codegen-x64.cc |
=================================================================== |
--- src/x64/fast-codegen-x64.cc (revision 3091) |
+++ src/x64/fast-codegen-x64.cc (working copy) |
@@ -166,9 +166,10 @@ |
Expression* rhs = expr->value(); |
Visit(rhs); |
- // Left-hand side is always a (parameter or local) slot. |
+ // Left-hand side can only be a global or a (parameter or local) slot. |
Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
- ASSERT(var != NULL && var->slot() != NULL); |
+ ASSERT(var != NULL); |
+ ASSERT(var->is_global() || var->slot() != NULL); |
// Complete the assignment based on the location of the right-hand-side |
// value and the desired location of the assignment value. |
@@ -177,27 +178,50 @@ |
ASSERT(!destination.is_constant()); |
ASSERT(!source.is_nowhere()); |
- if (source.is_temporary()) { |
+ if (var->is_global()) { |
+ // Assignment to a global variable, use inline caching. Right-hand-side |
+ // value is passed in rax, variable name in rcx, and the global object |
+ // on the stack. |
+ if (source.is_temporary()) { |
+ __ pop(rax); |
+ } else { |
+ ASSERT(source.is_constant()); |
+ ASSERT(rhs->AsLiteral() != NULL); |
+ __ Move(rax, rhs->AsLiteral()->handle()); |
+ } |
+ __ Move(rcx, var->name()); |
+ __ push(CodeGenerator::GlobalObject()); |
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
+ __ Call(ic, RelocInfo::CODE_TARGET); |
+ // Overwrite the global object on the stack with the result if needed. |
if (destination.is_temporary()) { |
- // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side temporary |
- // on the stack. |
- __ movq(kScratchRegister, Operand(rsp, 0)); |
- __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); |
+ __ movq(Operand(rsp, 0), rax); |
} else { |
- ASSERT(destination.is_nowhere()); |
- // Case 'var = temp'. Discard right-hand-side temporary. |
- __ pop(Operand(rbp, SlotOffset(var->slot()))); |
+ __ pop(rax); |
} |
} else { |
- ASSERT(source.is_constant()); |
- ASSERT(rhs->AsLiteral() != NULL); |
- // Two cases: 'temp <- (var = constant)', or 'var = constant' with a |
- // discarded result. Always perform the assignment. |
- __ Move(kScratchRegister, rhs->AsLiteral()->handle()); |
- __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); |
- if (destination.is_temporary()) { |
- // Case 'temp <- (var = constant)'. Save result. |
- __ push(kScratchRegister); |
+ if (source.is_temporary()) { |
+ if (destination.is_temporary()) { |
+ // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side temporary |
+ // on the stack. |
+ __ movq(kScratchRegister, Operand(rsp, 0)); |
+ __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); |
+ } else { |
+ ASSERT(destination.is_nowhere()); |
+ // Case 'var = temp'. Discard right-hand-side temporary. |
+ __ pop(Operand(rbp, SlotOffset(var->slot()))); |
+ } |
+ } else { |
+ ASSERT(source.is_constant()); |
+ ASSERT(rhs->AsLiteral() != NULL); |
+ // Two cases: 'temp <- (var = constant)', or 'var = constant' with a |
+ // discarded result. Always perform the assignment. |
+ __ Move(kScratchRegister, rhs->AsLiteral()->handle()); |
+ __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); |
+ if (destination.is_temporary()) { |
+ // Case 'temp <- (var = constant)'. Save result. |
+ __ push(kScratchRegister); |
+ } |
} |
} |
} |