From b2306a41d0e2e3bf896f1c3defb07f2368a737ab Mon Sep 17 00:00:00 2001 From: "kasperl@chromium.org" Date: Thu, 16 Sep 2010 09:10:34 +0000 Subject: [PATCH] Clean up the insertion of nops (signalling non-inlined loads and stores) in the full codegens. Review URL: http://codereview.chromium.org/3431010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5470 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/full-codegen-arm.cc | 55 ++++++++++++--------- src/full-codegen.h | 3 ++ src/ia32/full-codegen-ia32.cc | 106 +++++++++++++++++++---------------------- src/x64/full-codegen-x64.cc | 102 +++++++++++++++++++-------------------- src/x64/macro-assembler-x64.cc | 1 - 5 files changed, 134 insertions(+), 133 deletions(-) diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index c776d67..f5d1217 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -620,7 +620,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, __ pop(r2); // Receiver. Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // Value in r0 is ignored (declarations are statements). } } @@ -956,7 +956,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( slow)); __ mov(r0, Operand(key_literal->handle())); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); __ jmp(done); } } @@ -1022,7 +1022,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT; Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); - __ Call(ic, mode); + EmitCallIC(ic, mode); } @@ -1041,7 +1041,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var, __ ldr(r0, CodeGenerator::GlobalObject()); __ mov(r2, Operand(var->name())); Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); + EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); Apply(context, r0); } else if (slot != NULL && slot->type() == Slot::LOOKUP) { @@ -1100,7 +1100,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var, // Call keyed load IC. It has arguments key and receiver in r0 and r1. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); Apply(context, r0); } } @@ -1189,7 +1189,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ mov(r2, Operand(key->handle())); __ ldr(r1, MemOperand(sp)); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } // Fall through. @@ -1409,7 +1409,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { __ mov(r2, Operand(key->handle())); // Call load IC. It has arguments receiver and property name r0 and r2. Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } @@ -1417,7 +1417,7 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); // Call keyed load IC. It has arguments key and receiver in r0 and r1. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } @@ -1475,7 +1475,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ pop(r0); // Restore value. __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } case KEYED_PROPERTY: { @@ -1486,7 +1486,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ pop(r2); __ pop(r0); // Restore value. Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } } @@ -1509,7 +1509,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, __ mov(r2, Operand(var->name())); __ ldr(r1, CodeGenerator::GlobalObject()); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { // Perform the assignment for non-const variables and for initialization @@ -1598,7 +1598,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { } Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // If the assignment ends an initialization block, revert to fast case. if (expr->ends_initialization_block()) { @@ -1642,7 +1642,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { } Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // If the assignment ends an initialization block, revert to fast case. if (expr->ends_initialization_block()) { @@ -1691,7 +1691,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, // Call the IC initialization code. InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); - __ Call(ic, mode); + EmitCallIC(ic, mode); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); Apply(context_, r0); @@ -1715,7 +1715,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, in_loop); - __ Call(ic, mode); + EmitCallIC(ic, mode); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); Apply(context_, r0); @@ -1854,7 +1854,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { __ pop(r1); // We do not need to keep the receiver. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); __ ldr(r1, CodeGenerator::GlobalObject()); __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); __ Push(r0, r1); // Function, receiver. @@ -2769,7 +2769,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { __ mov(r2, Operand(expr->name())); Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, NOT_IN_LOOP); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); } else { @@ -3065,7 +3065,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); __ pop(r1); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); if (expr->is_postfix()) { if (context_ != Expression::kEffect) { ApplyTOS(context_); @@ -3079,7 +3079,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ pop(r1); // Key. __ pop(r2); // Receiver. Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); if (expr->is_postfix()) { if (context_ != Expression::kEffect) { ApplyTOS(context_); @@ -3102,7 +3102,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); // Use a regular load, not a contextual load, to avoid a reference // error. - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); if (where == kStack) __ push(r0); } else if (proxy != NULL && proxy->var()->slot() != NULL && @@ -3365,10 +3365,21 @@ void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { } -Register FullCodeGenerator::result_register() { return r0; } +Register FullCodeGenerator::result_register() { + return r0; +} -Register FullCodeGenerator::context_register() { return cp; } +Register FullCodeGenerator::context_register() { + return cp; +} + + +void FullCodeGenerator::EmitCallIC(Handle ic, RelocInfo::Mode mode) { + ASSERT(mode == RelocInfo::CODE_TARGET || + mode == RelocInfo::CODE_TARGET_CONTEXT); + __ Call(ic, mode); +} void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { diff --git a/src/full-codegen.h b/src/full-codegen.h index 9db233c..2d60d5b 100644 --- a/src/full-codegen.h +++ b/src/full-codegen.h @@ -509,6 +509,9 @@ class FullCodeGenerator: public AstVisitor { static Register result_register(); static Register context_register(); + // Helper for calling an IC stub. + void EmitCallIC(Handle ic, RelocInfo::Mode mode); + // Set fields in the stack frame. Offsets are the frame pointer relative // offsets defined in, e.g., StandardFrameConstants. void StoreToFrameField(int frame_offset, Register value); diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 07d19a1..5bb087d 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -631,10 +631,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, __ pop(edx); Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - // Absence of a test eax instruction following the call - // indicates that none of the load was inlined. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } } } @@ -992,8 +989,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT; - __ call(ic, mode); - __ nop(); // Signal no inlined code. + EmitCallIC(ic, mode); } @@ -1070,7 +1066,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( slow)); __ mov(eax, Immediate(key_literal->handle())); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); __ jmp(done); } } @@ -1094,12 +1090,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var, __ mov(eax, CodeGenerator::GlobalObject()); __ mov(ecx, var->name()); Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); - // By emitting a nop we make sure that we do not have a test eax - // instruction after the call it is treated specially by the LoadIC code - // Remember that the assembler may choose to do peephole optimization - // (eg, push/pop elimination). - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); Apply(context, eax); } else if (slot != NULL && slot->type() == Slot::LOOKUP) { @@ -1162,10 +1153,8 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var, // Do a keyed property load. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - // Notice: We must not have a "test eax, ..." instruction after the - // call. It is treated specially by the LoadIC code. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); + // Drop key and object left on the stack by IC. Apply(context, eax); } @@ -1263,8 +1252,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ mov(ecx, Immediate(key->handle())); __ mov(edx, Operand(esp, 0)); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } // Fall through. @@ -1477,16 +1465,14 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { Literal* key = prop->key()->AsLiteral(); __ mov(ecx, Immediate(key->handle())); Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } @@ -1846,8 +1832,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ pop(eax); // Restore value. __ mov(ecx, prop->key()->AsLiteral()->handle()); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - __ nop(); // Signal no inlined code. + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } case KEYED_PROPERTY: { @@ -1858,8 +1843,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ pop(edx); __ pop(eax); // Restore value. Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - __ nop(); // Signal no inlined code. + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } } @@ -1882,8 +1866,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, __ mov(ecx, var->name()); __ mov(edx, CodeGenerator::GlobalObject()); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { // Perform the assignment for non-const variables and for initialization @@ -1967,8 +1950,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ pop(edx); } Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // If the assignment ends an initialization block, revert to fast case. if (expr->ends_initialization_block()) { @@ -2006,10 +1988,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { // Record source code position before IC call. SetSourcePosition(expr->position()); Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - // This nop signals to the IC that there is no inlined code at the call - // site for it to patch. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // If the assignment ends an initialization block, revert to fast case. if (expr->ends_initialization_block()) { @@ -2056,7 +2035,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, SetSourcePosition(expr->position()); InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); - __ call(ic, mode); + EmitCallIC(ic, mode); // Restore context register. __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); Apply(context_, eax); @@ -2079,7 +2058,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeKeyedCallInitialize( arg_count, in_loop); - __ call(ic, mode); + EmitCallIC(ic, mode); // Restore context register. __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); Apply(context_, eax); @@ -2203,7 +2182,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { } else { // Call to a keyed property. // For a synthetic property use keyed load IC followed by function call, - // for a regular property use keyed CallIC. + // for a regular property use keyed EmitCallIC. VisitForValue(prop->obj(), kStack); if (prop->is_synthetic()) { VisitForValue(prop->key(), kAccumulator); @@ -2212,11 +2191,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { __ pop(edx); // We do not need to keep the receiver. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - // By emitting a nop we make sure that we do not have a "test eax,..." - // instruction after the call as it is treated specially - // by the LoadIC code. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // Push result (function). __ push(eax); // Push Global receiver. @@ -3144,7 +3119,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { __ Set(ecx, Immediate(expr->name())); InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); - __ call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // Restore context register. __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); } else { @@ -3450,10 +3425,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ mov(ecx, prop->key()->AsLiteral()->handle()); __ pop(edx); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - // This nop signals to the IC that there is no inlined code at the call - // site for it to patch. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); if (expr->is_postfix()) { if (context_ != Expression::kEffect) { ApplyTOS(context_); @@ -3467,10 +3439,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ pop(ecx); __ pop(edx); Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - // This nop signals to the IC that there is no inlined code at the call - // site for it to patch. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); if (expr->is_postfix()) { // Result is on the stack if (context_ != Expression::kEffect) { @@ -3494,8 +3463,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); // Use a regular load, not a contextual load, to avoid a reference // error. - __ call(ic, RelocInfo::CODE_TARGET); - __ nop(); // Signal no inlined code. + EmitCallIC(ic, RelocInfo::CODE_TARGET); if (where == kStack) __ push(eax); } else if (proxy != NULL && proxy->var()->slot() != NULL && @@ -3747,10 +3715,36 @@ void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { } -Register FullCodeGenerator::result_register() { return eax; } +Register FullCodeGenerator::result_register() { + return eax; +} + + +Register FullCodeGenerator::context_register() { + return esi; +} -Register FullCodeGenerator::context_register() { return esi; } +void FullCodeGenerator::EmitCallIC(Handle ic, RelocInfo::Mode mode) { + ASSERT(mode == RelocInfo::CODE_TARGET || + mode == RelocInfo::CODE_TARGET_CONTEXT); + __ call(ic, mode); + + // If we're calling a (keyed) load or store stub, we have to mark + // the call as containing no inlined code so we will not attempt to + // patch it. + switch (ic->kind()) { + case Code::LOAD_IC: + case Code::KEYED_LOAD_IC: + case Code::STORE_IC: + case Code::KEYED_STORE_IC: + __ nop(); // Signals no inlined code. + break; + default: + // Do nothing. + break; + } +} void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 35ce52c..8c19503 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -625,10 +625,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, __ pop(rdx); Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - // Absence of a test rax instruction following the call - // indicates that none of the load was inlined. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } } } @@ -941,8 +938,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT; - __ call(ic, mode); - __ nop(); // Signal no inlined code. + EmitCallIC(ic, mode); } @@ -1019,7 +1015,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( slow)); __ Move(rax, key_literal->handle()); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); __ jmp(done); } } @@ -1043,11 +1039,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var, __ Move(rcx, var->name()); __ movq(rax, CodeGenerator::GlobalObject()); Handle 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. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); Apply(context, rax); } else if (slot != NULL && slot->type() == Slot::LOOKUP) { @@ -1110,10 +1102,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var, // Do a keyed property load. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - // Notice: We must not have a "test rax, ..." instruction after the - // call. It is treated specially by the LoadIC code. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); Apply(context, rax); } } @@ -1212,8 +1201,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ Move(rcx, key->handle()); __ movq(rdx, Operand(rsp, 0)); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } // Fall through. @@ -1425,16 +1413,14 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { Literal* key = prop->key()->AsLiteral(); __ Move(rcx, key->handle()); Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } @@ -1553,8 +1539,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ pop(rax); // Restore value. __ Move(rcx, prop->key()->AsLiteral()->handle()); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - __ nop(); // Signal no inlined code. + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } case KEYED_PROPERTY: { @@ -1565,8 +1550,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ pop(rdx); __ pop(rax); Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - __ nop(); // Signal no inlined code. + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } } @@ -1589,8 +1573,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, __ Move(rcx, var->name()); __ movq(rdx, CodeGenerator::GlobalObject()); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { // Perform the assignment for non-const variables and for initialization @@ -1674,8 +1657,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ pop(rdx); } Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // If the assignment ends an initialization block, revert to fast case. if (expr->ends_initialization_block()) { @@ -1713,10 +1695,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { // Record source code position before IC call. SetSourcePosition(expr->position()); Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); - // This nop signals to the IC that there is no inlined code at the call - // site for it to patch. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // If the assignment ends an initialization block, revert to fast case. if (expr->ends_initialization_block()) { @@ -1765,7 +1744,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); - __ Call(ic, mode); + EmitCallIC(ic, mode); // Restore context register. __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); Apply(context_, rax); @@ -1789,7 +1768,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, in_loop); - __ Call(ic, mode); + EmitCallIC(ic, mode); // Restore context register. __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); Apply(context_, rax); @@ -1924,11 +1903,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { // Record source code position for IC call. SetSourcePosition(prop->position()); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - // By emitting a nop we make sure that we do not have a "test rax,..." - // instruction after the call as it is treated specially - // by the LoadIC code. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // Pop receiver. __ pop(rbx); // Push result (function). @@ -2841,7 +2816,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { __ Move(rcx, expr->name()); InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); - __ call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // Restore context register. __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); } else { @@ -3139,10 +3114,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ Move(rcx, prop->key()->AsLiteral()->handle()); __ pop(rdx); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - // This nop signals to the IC that there is no inlined code at the call - // site for it to patch. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); if (expr->is_postfix()) { if (context_ != Expression::kEffect) { ApplyTOS(context_); @@ -3156,10 +3128,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ pop(rcx); __ pop(rdx); Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ call(ic, RelocInfo::CODE_TARGET); - // This nop signals to the IC that there is no inlined code at the call - // site for it to patch. - __ nop(); + EmitCallIC(ic, RelocInfo::CODE_TARGET); if (expr->is_postfix()) { if (context_ != Expression::kEffect) { ApplyTOS(context_); @@ -3182,8 +3151,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); // Use a regular load, not a contextual load, to avoid a reference // error. - __ Call(ic, RelocInfo::CODE_TARGET); - __ nop(); // Signal no inlined code. + EmitCallIC(ic, RelocInfo::CODE_TARGET); if (where == kStack) __ push(rax); } else if (proxy != NULL && proxy->var()->slot() != NULL && @@ -3431,10 +3399,36 @@ void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { } -Register FullCodeGenerator::result_register() { return rax; } +Register FullCodeGenerator::result_register() { + return rax; +} + + +Register FullCodeGenerator::context_register() { + return rsi; +} + +void FullCodeGenerator::EmitCallIC(Handle ic, RelocInfo::Mode mode) { + ASSERT(mode == RelocInfo::CODE_TARGET || + mode == RelocInfo::CODE_TARGET_CONTEXT); + __ call(ic, mode); -Register FullCodeGenerator::context_register() { return rsi; } + // If we're calling a (keyed) load or store stub, we have to mark + // the call as containing no inlined code so we will not attempt to + // patch it. + switch (ic->kind()) { + case Code::LOAD_IC: + case Code::KEYED_LOAD_IC: + case Code::STORE_IC: + case Code::KEYED_STORE_IC: + __ nop(); // Signals no inlined code. + break; + default: + // Do nothing. + break; + } +} void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index e6f81b3..d62bed4 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -1315,7 +1315,6 @@ void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { void MacroAssembler::Call(Handle code_object, RelocInfo::Mode rmode) { ASSERT(RelocInfo::IsCodeTarget(rmode)); - WriteRecordedPositions(); call(code_object, rmode); } -- 2.7.4