Revision: 3101 Author: [email protected] Date: Wed Oct 21 02:38:21 2009 Log: Add support for global variable references in toplevel code. We use the normal named load IC mechanism for now. Generated code is similar to the case for global variable assignments.
Review URL: http://codereview.chromium.org/294021 http://code.google.com/p/v8/source/detail?r=3101 Modified: /branches/bleeding_edge/src/arm/fast-codegen-arm.cc /branches/bleeding_edge/src/compiler.cc /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc /branches/bleeding_edge/src/x64/fast-codegen-x64.cc /branches/bleeding_edge/test/mjsunit/compiler/globals.js ======================================= --- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Wed Oct 21 02:17:39 2009 +++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Wed Oct 21 02:38:21 2009 @@ -185,11 +185,27 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { Comment cmnt(masm_, "[ VariableProxy"); Expression* rewrite = expr->var()->rewrite(); - ASSERT(rewrite != NULL); - - Slot* slot = rewrite->AsSlot(); - ASSERT(slot != NULL); - { Comment cmnt(masm_, "[ Slot"); + 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(); + } + + } 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); ======================================= --- /branches/bleeding_edge/src/compiler.cc Wed Oct 21 02:17:39 2009 +++ /branches/bleeding_edge/src/compiler.cc Wed Oct 21 02:38:21 2009 @@ -628,8 +628,7 @@ void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) { Expression* rewrite = expr->var()->rewrite(); - if (rewrite == NULL) BAILOUT("global variable reference"); - Visit(rewrite); + if (rewrite != NULL) Visit(rewrite); } ======================================= --- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Wed Oct 21 02:17:39 2009 +++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Wed Oct 21 02:38:21 2009 @@ -172,11 +172,31 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { Comment cmnt(masm_, "[ VariableProxy"); Expression* rewrite = expr->var()->rewrite(); - ASSERT(rewrite != NULL); - - Slot* slot = rewrite->AsSlot(); - ASSERT(slot != NULL); - { Comment cmnt(masm_, "[ Slot"); + 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); + } + + } else { + Comment cmnt(masm_, "Stack slot"); + Slot* slot = rewrite->AsSlot(); + ASSERT(slot != NULL); if (expr->location().is_temporary()) { __ push(Operand(ebp, SlotOffset(slot))); } else { ======================================= --- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Wed Oct 21 02:17:39 2009 +++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Wed Oct 21 02:38:21 2009 @@ -189,11 +189,30 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { Comment cmnt(masm_, "[ VariableProxy"); Expression* rewrite = expr->var()->rewrite(); - ASSERT(rewrite != NULL); - - Slot* slot = rewrite->AsSlot(); - ASSERT(slot != NULL); - { Comment cmnt(masm_, "[ Slot"); + 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); + + // 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 { ======================================= --- /branches/bleeding_edge/test/mjsunit/compiler/globals.js Tue Oct 20 06:37:26 2009 +++ /branches/bleeding_edge/test/mjsunit/compiler/globals.js Wed Oct 21 02:38:21 2009 @@ -42,3 +42,14 @@ // 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')); --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
