void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
Comment cmnt(masm_, "[ VariableProxy");
Expression* rewrite = expr->var()->rewrite();
- ASSERT(rewrite != NULL);
+ if (rewrite == NULL) {
+ Comment cmnt(masm_, "Global variable");
+ // Use inline caching. Variable name is passed in r2 and the global
+ // object on the stack.
+ __ ldr(ip, CodeGenerator::GlobalObject());
+ __ push(ip);
+ __ mov(r2, Operand(expr->name()));
+ Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+ __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+ if (expr->location().is_temporary()) {
+ // Replace the global object with the result.
+ __ str(r0, MemOperand(sp));
+ } else {
+ ASSERT(expr->location().is_nowhere());
+ __ pop();
+ }
- Slot* slot = rewrite->AsSlot();
- ASSERT(slot != NULL);
- { Comment cmnt(masm_, "[ Slot");
+ } else {
+ Comment cmnt(masm_, "Stack slot");
+ Slot* slot = rewrite->AsSlot();
+ ASSERT(slot != NULL);
if (expr->location().is_temporary()) {
__ ldr(ip, MemOperand(fp, SlotOffset(slot)));
__ push(ip);
void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
Expression* rewrite = expr->var()->rewrite();
- if (rewrite == NULL) BAILOUT("global variable reference");
- Visit(rewrite);
+ if (rewrite != NULL) Visit(rewrite);
}
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
Comment cmnt(masm_, "[ VariableProxy");
Expression* rewrite = expr->var()->rewrite();
- ASSERT(rewrite != NULL);
+ if (rewrite == NULL) {
+ Comment cmnt(masm_, "Global variable");
+ // Use inline caching. Variable name is passed in ecx and the global
+ // object on the stack.
+ __ push(CodeGenerator::GlobalObject());
+ __ mov(ecx, expr->name());
+ Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+ __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+
+ // A test eax instruction following the call is used by the IC to
+ // indicate that the inobject property case was inlined. Ensure there
+ // is no test eax instruction here. Remember that the assembler may
+ // choose to do peephole optimization (eg, push/pop elimination).
+ if (expr->location().is_temporary()) {
+ // Replace the global object with the result.
+ __ mov(Operand(esp, 0), eax);
+ } else {
+ ASSERT(expr->location().is_nowhere());
+ __ pop(eax);
+ }
- Slot* slot = rewrite->AsSlot();
- ASSERT(slot != NULL);
- { Comment cmnt(masm_, "[ Slot");
+ } else {
+ Comment cmnt(masm_, "Stack slot");
+ Slot* slot = rewrite->AsSlot();
+ ASSERT(slot != NULL);
if (expr->location().is_temporary()) {
__ push(Operand(ebp, SlotOffset(slot)));
} else {
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
Comment cmnt(masm_, "[ VariableProxy");
Expression* rewrite = expr->var()->rewrite();
- ASSERT(rewrite != NULL);
+ if (rewrite == NULL) {
+ Comment cmnt(masm_, "Global variable");
+ // Use inline caching. Variable name is passed in rcx and the global
+ // object on the stack.
+ __ push(CodeGenerator::GlobalObject());
+ __ Move(rcx, expr->name());
+ Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+ __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
- Slot* slot = rewrite->AsSlot();
- ASSERT(slot != NULL);
- { Comment cmnt(masm_, "[ Slot");
+ // A test rax instruction following the call is used by the IC to
+ // indicate that the inobject property case was inlined. Ensure there
+ // is no test rax instruction here.
+ if (expr->location().is_temporary()) {
+ // Replace the global object with the result.
+ __ movq(Operand(rsp, 0), rax);
+ } else {
+ ASSERT(expr->location().is_nowhere());
+ __ pop(rax);
+ }
+
+ } else {
+ Comment cmnt(masm_, "Stack slot");
+ Slot* slot = rewrite->AsSlot();
+ ASSERT(slot != NULL);
if (expr->location().is_temporary()) {
__ push(Operand(rbp, SlotOffset(slot)));
} else {
// Test a second store.
assertEquals("2", eval('g = "2"'));
assertEquals("2", g);
+
+// Test a load.
+assertEquals("2", eval('g'));
+
+// Test that patching the IC in the compiled code works.
+assertEquals("2", eval('g'));
+assertEquals("2", eval('g'));
+
+// Test a second load.
+g = 3;
+assertEquals(3, eval('g'));