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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3101 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2a635946
......@@ -185,11 +185,27 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
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);
......
......@@ -628,8 +628,7 @@ void CodeGenSelector::VisitSlot(Slot* expr) {
void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
Expression* rewrite = expr->var()->rewrite();
if (rewrite == NULL) BAILOUT("global variable reference");
Visit(rewrite);
if (rewrite != NULL) Visit(rewrite);
}
......
......@@ -172,11 +172,31 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
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 {
......
......@@ -189,11 +189,30 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
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 {
......
......@@ -42,3 +42,14 @@ assertEquals(1, g);
// 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'));
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