From e3e7daf01cc58a8b13132326aa2bc816124a76bd Mon Sep 17 00:00:00 2001 From: "mvstanton@chromium.org" Date: Tue, 7 Jan 2014 14:14:34 +0000 Subject: [PATCH] We need to know if a load, store or call IC is assumed to be on the global object. Previously, this information was stored in RelocInfo. A more logical place for this kind of structural information is ExtraICState. Storing it there makes it easier for us to gather type feedback from these sites too. R=verwaest@chromium.org Review URL: https://codereview.chromium.org/96083005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18466 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/full-codegen-arm.cc | 91 +++++------- src/arm/ic-arm.cc | 5 +- src/arm/lithium-codegen-arm.cc | 33 ++--- src/assembler.cc | 3 - src/assembler.h | 1 - src/builtins.cc | 57 -------- src/builtins.h | 23 ---- src/code-stubs.h | 4 +- src/disassembler.cc | 2 +- src/full-codegen.cc | 13 +- src/full-codegen.h | 12 +- src/ia32/full-codegen-ia32.cc | 97 ++++++------- src/ia32/ic-ia32.cc | 5 +- src/ia32/lithium-codegen-ia32.cc | 33 ++--- src/ic.cc | 89 ++++++++---- src/ic.h | 156 +++++++++------------ src/log.h | 7 + src/mips/full-codegen-mips.cc | 92 +++++-------- src/mips/ic-mips.cc | 5 +- src/mips/lithium-codegen-mips.cc | 33 ++--- src/objects.cc | 14 +- src/objects.h | 1 + src/stub-cache.cc | 168 ++++++++++++++++++++--- src/stub-cache.h | 25 +++- src/x64/full-codegen-x64.cc | 89 +++++------- src/x64/ic-x64.cc | 5 +- src/x64/lithium-codegen-x64.cc | 33 ++--- test/cctest/test-debug.cc | 10 +- test/cctest/test-disasm-ia32.cc | 3 +- test/cctest/test-heap.cc | 11 +- test/mjsunit/context-calls-maintained.js | 116 ++++++++++++++++ 31 files changed, 694 insertions(+), 542 deletions(-) create mode 100644 test/mjsunit/context-calls-maintained.js diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index da7eb99b95..3a96dd296c 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -659,7 +659,7 @@ void FullCodeGenerator::DoTest(Expression* condition, Label* if_false, Label* fall_through) { Handle ic = ToBooleanStub::GetUninitialized(isolate()); - CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); + CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); __ tst(result_register(), result_register()); Split(ne, if_true, if_false, fall_through); } @@ -1020,7 +1020,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { // Record position before stub call for type feedback. SetSourcePosition(clause->position()); Handle ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); - CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); + CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); patch_site.EmitPatchInfo(); Label skip; @@ -1388,11 +1388,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, __ ldr(r0, GlobalObjectOperand()); __ mov(r2, Operand(var->name())); - RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) - ? RelocInfo::CODE_TARGET - : RelocInfo::CODE_TARGET_CONTEXT; - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(ic, mode); + ContextualMode mode = (typeof_state == INSIDE_TYPEOF) + ? NOT_CONTEXTUAL + : CONTEXTUAL; + CallLoadIC(mode); } @@ -1475,8 +1474,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { // object (receiver) in r0. __ ldr(r0, GlobalObjectOperand()); __ mov(r2, Operand(var->name())); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); + CallLoadIC(CONTEXTUAL); context()->Plug(r0); break; } @@ -1685,10 +1683,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { VisitForAccumulatorValue(value); __ mov(r2, Operand(key->value())); __ ldr(r1, MemOperand(sp)); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); + CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); PrepareForBailoutForId(key->id(), NO_REGISTERS); } else { VisitForEffect(value); @@ -2096,8 +2091,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ bind(&l_loop); __ push(r0); // save result __ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done" - Handle done_ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(done_ic); // result.done in r0 + CallLoadIC(NOT_CONTEXTUAL); // result.done in r0 Handle bool_ic = ToBooleanStub::GetUninitialized(isolate()); CallIC(bool_ic); __ cmp(r0, Operand(0)); @@ -2106,8 +2100,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { // result.value __ pop(r0); // result __ LoadRoot(r2, Heap::kvalue_stringRootIndex); // "value" - Handle value_ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(value_ic); // result.value in r0 + CallLoadIC(NOT_CONTEXTUAL); // result.value in r0 context()->DropAndPlug(2, r0); // drop iter and g break; } @@ -2257,8 +2250,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { Literal* key = prop->key()->AsLiteral(); __ mov(r2, Operand(key->value())); // Call load IC. It has arguments receiver and property name r0 and r2. - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); + CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); } @@ -2266,7 +2258,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 = isolate()->builtins()->KeyedLoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); } @@ -2293,7 +2285,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, __ bind(&stub_call); BinaryOpICStub stub(op, mode); - CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, + CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, expr->BinaryOperationFeedbackId()); patch_site.EmitPatchInfo(); __ jmp(&done); @@ -2371,7 +2363,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, __ pop(r1); BinaryOpICStub stub(op, mode); JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. - CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, + CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, expr->BinaryOperationFeedbackId()); patch_site.EmitPatchInfo(); context()->Plug(r0); @@ -2410,10 +2402,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ mov(r1, r0); __ pop(r0); // Restore value. __ mov(r2, Operand(prop->key()->AsLiteral()->value())); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic); + CallStoreIC(NOT_CONTEXTUAL); break; } case KEYED_PROPERTY: { @@ -2439,11 +2428,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, // Global var, const, or let. __ mov(r2, Operand(var->name())); __ ldr(r1, GlobalObjectOperand()); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); - + CallStoreIC(CONTEXTUAL); } else if (op == Token::INIT_CONST) { // Const initializers need a write barrier. ASSERT(!var->IsParameter()); // No const parameters. @@ -2537,10 +2522,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ mov(r2, Operand(prop->key()->AsLiteral()->value())); __ pop(r1); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); + CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(r0); @@ -2557,7 +2539,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { Handle ic = is_classic_mode() ? isolate()->builtins()->KeyedStoreIC_Initialize() : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(r0); @@ -2584,17 +2566,19 @@ void FullCodeGenerator::VisitProperty(Property* expr) { void FullCodeGenerator::CallIC(Handle code, - RelocInfo::Mode rmode, + ContextualMode mode, TypeFeedbackId ast_id) { ic_total_count_++; // All calls must have a predictable size in full-codegen code to ensure that // the debugger can patch them correctly. - __ Call(code, rmode, ast_id, al, NEVER_INLINE_TARGET_ADDRESS); + ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); + __ Call(code, RelocInfo::CODE_TARGET, ast_id, al, + NEVER_INLINE_TARGET_ADDRESS); } void FullCodeGenerator::EmitCallWithIC(Call* expr, Handle name, - RelocInfo::Mode mode) { + ContextualMode mode) { // Code common for calls using the IC. ZoneList* args = expr->arguments(); int arg_count = args->length(); @@ -2609,7 +2593,10 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, // Call the IC initialization code. Handle ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); - CallIC(ic, mode, expr->CallFeedbackId()); + TypeFeedbackId ast_id = mode == CONTEXTUAL + ? TypeFeedbackId::None() + : expr->CallFeedbackId(); + CallIC(ic, mode, ast_id); RecordJSReturnSite(expr); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); @@ -2642,7 +2629,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, Handle ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. - CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); RecordJSReturnSite(expr); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); @@ -2759,7 +2746,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { // Push global object as receiver for the call IC. __ ldr(r0, GlobalObjectOperand()); __ push(r0); - EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); + EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { // Call to a lookup slot (dynamically introduced variable). Label slow, done; @@ -2806,7 +2793,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { if (property->key()->IsPropertyName()) { EmitCallWithIC(expr, property->key()->AsLiteral()->value(), - RelocInfo::CODE_TARGET); + NOT_CONTEXTUAL); } else { EmitKeyedCallWithIC(expr, property->key()); } @@ -4149,7 +4136,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->is_jsruntime()) { // Call the JS runtime function. __ mov(r2, Operand(expr->name())); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET; + ContextualMode mode = NOT_CONTEXTUAL; Handle ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); CallIC(ic, mode, expr->CallRuntimeFeedbackId()); @@ -4400,7 +4387,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); CallIC(stub.GetCode(isolate()), - RelocInfo::CODE_TARGET, + NOT_CONTEXTUAL, expr->CountBinOpFeedbackId()); patch_site.EmitPatchInfo(); __ bind(&done); @@ -4430,10 +4417,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { case NAMED_PROPERTY: { __ mov(r2, Operand(prop->key()->AsLiteral()->value())); __ pop(r1); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); + CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { if (!context()->IsEffect()) { @@ -4449,7 +4433,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { Handle ic = is_classic_mode() ? isolate()->builtins()->KeyedStoreIC_Initialize() : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { if (!context()->IsEffect()) { @@ -4472,10 +4456,9 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { Comment cmnt(masm_, "Global variable"); __ ldr(r0, GlobalObjectOperand()); __ mov(r2, Operand(proxy->name())); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); // Use a regular load, not a contextual load, to avoid a reference // error. - CallIC(ic); + CallLoadIC(NOT_CONTEXTUAL); PrepareForBailout(expr, TOS_REG); context()->Plug(r0); } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { @@ -4640,7 +4623,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { // Record position and call the compare IC. SetSourcePosition(expr->position()); Handle ic = CompareIC::GetUninitialized(isolate(), op); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); patch_site.EmitPatchInfo(); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); __ cmp(r0, Operand::Zero()); @@ -4675,7 +4658,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, Split(eq, if_true, if_false, fall_through); } else { Handle ic = CompareNilICStub::GetUninitialized(isolate(), nil); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); __ cmp(r0, Operand(0)); Split(ne, if_true, if_false, fall_through); } diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc index a8943e12a5..7b3ba36689 100644 --- a/src/arm/ic-arm.cc +++ b/src/arm/ic-arm.cc @@ -647,7 +647,7 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { } -void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -655,8 +655,9 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { // ----------------------------------- // Probe the stub cache. + ExtraICState extra_ic_state = IC::ComputeExtraICState(mode); Code::Flags flags = Code::ComputeFlags( - Code::HANDLER, MONOMORPHIC, kNoExtraICState, + Code::HANDLER, MONOMORPHIC, extra_ic_state, Code::NORMAL, Code::LOAD_IC); masm->isolate()->stub_cache()->GenerateProbe( masm, flags, r0, r2, r3, r4, r5, r6); diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index c58fdb1c92..caeee042da 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -2958,10 +2958,9 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { ASSERT(ToRegister(instr->result()).is(r0)); __ mov(r2, Operand(instr->name())); - RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET - : RelocInfo::CODE_TARGET_CONTEXT; - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallCode(ic, mode, instr); + ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; + Handle ic = LoadIC::initialize_stub(isolate(), mode); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -2996,10 +2995,10 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { ASSERT(ToRegister(instr->value()).is(r0)); __ mov(r2, Operand(instr->name())); - Handle ic = (instr->strict_mode_flag() == kStrictMode) - ? isolate()->builtins()->StoreIC_Initialize_Strict() - : isolate()->builtins()->StoreIC_Initialize(); - CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); + Handle ic = StoreIC::initialize_stub(isolate(), + instr->strict_mode_flag(), + CONTEXTUAL); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3092,7 +3091,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { // Name is always in r2. __ mov(r2, Operand(instr->name())); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); + Handle ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } @@ -3976,11 +3975,10 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) { ASSERT(ToRegister(instr->result()).is(r0)); int arity = instr->arity(); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET; Handle ic = - isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL); __ mov(r2, Operand(instr->name())); - CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); + CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } @@ -4008,11 +4006,10 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { ASSERT(ToRegister(instr->result()).is(r0)); int arity = instr->arity(); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; Handle ic = - isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL); __ mov(r2, Operand(instr->name())); - CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); + CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } @@ -4209,9 +4206,9 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { // Name is always in r2. __ mov(r2, Operand(instr->name())); - Handle ic = (instr->strict_mode_flag() == kStrictMode) - ? isolate()->builtins()->StoreIC_Initialize_Strict() - : isolate()->builtins()->StoreIC_Initialize(); + Handle ic = StoreIC::initialize_stub(isolate(), + instr->strict_mode_flag(), + NOT_CONTEXTUAL); CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } diff --git a/src/assembler.cc b/src/assembler.cc index 4ac2fb49ea..d0e96695f6 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -766,8 +766,6 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) { return "embedded object"; case RelocInfo::CONSTRUCT_CALL: return "code target (js construct call)"; - case RelocInfo::CODE_TARGET_CONTEXT: - return "code target (context)"; case RelocInfo::DEBUG_BREAK: #ifndef ENABLE_DEBUGGER_SUPPORT UNREACHABLE(); @@ -862,7 +860,6 @@ void RelocInfo::Verify() { break; #endif case CONSTRUCT_CALL: - case CODE_TARGET_CONTEXT: case CODE_TARGET_WITH_ID: case CODE_TARGET: { // convert inline target address to code object diff --git a/src/assembler.h b/src/assembler.h index 3ccfccf315..ce7d9f5b7d 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -262,7 +262,6 @@ class RelocInfo BASE_EMBEDDED { CODE_TARGET, // Code target which is not any of the above. CODE_TARGET_WITH_ID, CONSTRUCT_CALL, // code target that is a call to a JavaScript constructor. - CODE_TARGET_CONTEXT, // Code target used for contextual loads and stores. DEBUG_BREAK, // Code target for the debugger statement. EMBEDDED_OBJECT, CELL, diff --git a/src/builtins.cc b/src/builtins.cc index b27f29a3d7..9191263630 100644 --- a/src/builtins.cc +++ b/src/builtins.cc @@ -1300,26 +1300,11 @@ BUILTIN(HandleApiCallAsConstructor) { } -static void Generate_LoadIC_Initialize(MacroAssembler* masm) { - LoadIC::GenerateInitialize(masm); -} - - -static void Generate_LoadIC_PreMonomorphic(MacroAssembler* masm) { - LoadIC::GeneratePreMonomorphic(masm); -} - - static void Generate_LoadIC_Miss(MacroAssembler* masm) { LoadIC::GenerateMiss(masm); } -static void Generate_LoadIC_Megamorphic(MacroAssembler* masm) { - LoadIC::GenerateMegamorphic(masm); -} - - static void Generate_LoadIC_Normal(MacroAssembler* masm) { LoadIC::GenerateNormal(masm); } @@ -1381,26 +1366,6 @@ static void Generate_StoreIC_Slow(MacroAssembler* masm) { } -static void Generate_StoreIC_Initialize(MacroAssembler* masm) { - StoreIC::GenerateInitialize(masm); -} - - -static void Generate_StoreIC_Initialize_Strict(MacroAssembler* masm) { - StoreIC::GenerateInitialize(masm); -} - - -static void Generate_StoreIC_PreMonomorphic(MacroAssembler* masm) { - StoreIC::GeneratePreMonomorphic(masm); -} - - -static void Generate_StoreIC_PreMonomorphic_Strict(MacroAssembler* masm) { - StoreIC::GeneratePreMonomorphic(masm); -} - - static void Generate_StoreIC_Miss(MacroAssembler* masm) { StoreIC::GenerateMiss(masm); } @@ -1411,33 +1376,11 @@ static void Generate_StoreIC_Normal(MacroAssembler* masm) { } -static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) { - StoreIC::GenerateMegamorphic(masm, - StoreIC::ComputeExtraICState(kNonStrictMode)); -} - - -static void Generate_StoreIC_Megamorphic_Strict(MacroAssembler* masm) { - StoreIC::GenerateMegamorphic(masm, - StoreIC::ComputeExtraICState(kStrictMode)); -} - - static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) { StoreStubCompiler::GenerateStoreViaSetter(masm, Handle()); } -static void Generate_StoreIC_Generic(MacroAssembler* masm) { - StoreIC::GenerateRuntimeSetProperty(masm, kNonStrictMode); -} - - -static void Generate_StoreIC_Generic_Strict(MacroAssembler* masm) { - StoreIC::GenerateRuntimeSetProperty(masm, kStrictMode); -} - - static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) { KeyedStoreIC::GenerateGeneric(masm, kNonStrictMode); } diff --git a/src/builtins.h b/src/builtins.h index affb253829..d977a4817c 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -125,15 +125,8 @@ enum BuiltinExtraArguments { kNoExtraICState) \ V(KeyedStoreIC_Miss, BUILTIN, UNINITIALIZED, \ kNoExtraICState) \ - V(LoadIC_Initialize, LOAD_IC, UNINITIALIZED, \ - kNoExtraICState) \ - V(LoadIC_PreMonomorphic, LOAD_IC, PREMONOMORPHIC, \ - kNoExtraICState) \ - V(LoadIC_Megamorphic, LOAD_IC, MEGAMORPHIC, \ - kNoExtraICState) \ V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, \ kNoExtraICState) \ - \ V(KeyedLoadIC_Initialize, KEYED_LOAD_IC, UNINITIALIZED, \ kNoExtraICState) \ V(KeyedLoadIC_PreMonomorphic, KEYED_LOAD_IC, PREMONOMORPHIC, \ @@ -147,22 +140,6 @@ enum BuiltinExtraArguments { V(KeyedLoadIC_NonStrictArguments, KEYED_LOAD_IC, MONOMORPHIC, \ kNoExtraICState) \ \ - V(StoreIC_Initialize, STORE_IC, UNINITIALIZED, \ - kNoExtraICState) \ - V(StoreIC_PreMonomorphic, STORE_IC, PREMONOMORPHIC, \ - kNoExtraICState) \ - V(StoreIC_Megamorphic, STORE_IC, MEGAMORPHIC, \ - kNoExtraICState) \ - V(StoreIC_Generic, STORE_IC, GENERIC, \ - kNoExtraICState) \ - V(StoreIC_Generic_Strict, STORE_IC, GENERIC, \ - StoreIC::kStrictModeState) \ - V(StoreIC_Initialize_Strict, STORE_IC, UNINITIALIZED, \ - StoreIC::kStrictModeState) \ - V(StoreIC_PreMonomorphic_Strict, STORE_IC, PREMONOMORPHIC, \ - StoreIC::kStrictModeState) \ - V(StoreIC_Megamorphic_Strict, STORE_IC, MEGAMORPHIC, \ - StoreIC::kStrictModeState) \ V(StoreIC_Setter_ForDeopt, STORE_IC, MONOMORPHIC, \ StoreIC::kStrictModeState) \ \ diff --git a/src/code-stubs.h b/src/code-stubs.h index 3c3c1946c7..175778a496 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -1053,8 +1053,8 @@ class KeyedArrayCallStub: public HICStub { } class ContextualBits: public BitField {}; - STATIC_ASSERT(CallICBase::Contextual::kShift == ContextualBits::kShift); - STATIC_ASSERT(CallICBase::Contextual::kSize == ContextualBits::kSize); + STATIC_ASSERT(IC::Contextual::kShift == ContextualBits::kShift); + STATIC_ASSERT(IC::Contextual::kSize == ContextualBits::kSize); class HoleyBits: public BitField {}; STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 2); class ArgcBits: public BitField {}; diff --git a/src/disassembler.cc b/src/disassembler.cc index 8bec2ced32..5a4a93c6ee 100644 --- a/src/disassembler.cc +++ b/src/disassembler.cc @@ -237,7 +237,7 @@ static int DecodeIt(Isolate* isolate, Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address()); Code::Kind kind = code->kind(); if (code->is_inline_cache_stub()) { - if (rmode == RelocInfo::CODE_TARGET_CONTEXT) { + if (code->IsContextual()) { out.AddFormatted(" contextual,"); } InlineCacheState ic_state = code->ic_state(); diff --git a/src/full-codegen.cc b/src/full-codegen.cc index ff4e8d31c9..f88c7d42f3 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -440,12 +440,23 @@ void FullCodeGenerator::PopulateTypeFeedbackCells(Handle code) { } - void FullCodeGenerator::PrepareForBailout(Expression* node, State state) { PrepareForBailoutForId(node->id(), state); } +void FullCodeGenerator::CallLoadIC(ContextualMode mode, TypeFeedbackId id) { + Handle ic = LoadIC::initialize_stub(isolate(), mode); + CallIC(ic, mode, id); +} + + +void FullCodeGenerator::CallStoreIC(ContextualMode mode, TypeFeedbackId id) { + Handle ic = StoreIC::initialize_stub(isolate(), strict_mode(), mode); + CallIC(ic, mode, id); +} + + void FullCodeGenerator::RecordJSReturnSite(Call* call) { // We record the offset of the function return so we can rebuild the frame // if the function was inlined, i.e., this is the return address in the diff --git a/src/full-codegen.h b/src/full-codegen.h index 6fd61c0505..edf333dee2 100644 --- a/src/full-codegen.h +++ b/src/full-codegen.h @@ -483,7 +483,7 @@ class FullCodeGenerator: public AstVisitor { // Platform-specific code sequences for calls void EmitCallWithStub(Call* expr, CallFunctionFlags flags); - void EmitCallWithIC(Call* expr, Handle name, RelocInfo::Mode mode); + void EmitCallWithIC(Call* expr, Handle name, ContextualMode mode); void EmitKeyedCallWithIC(Call* expr, Expression* key); // Platform-specific code for inline runtime calls. @@ -565,9 +565,14 @@ class FullCodeGenerator: public AstVisitor { void EmitKeyedPropertyAssignment(Assignment* expr); void CallIC(Handle code, - RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, + ContextualMode mode = NOT_CONTEXTUAL, TypeFeedbackId id = TypeFeedbackId::None()); + void CallLoadIC(ContextualMode mode, + TypeFeedbackId id = TypeFeedbackId::None()); + void CallStoreIC(ContextualMode mode, + TypeFeedbackId id = TypeFeedbackId::None()); + void SetFunctionPosition(FunctionLiteral* fun); void SetReturnPosition(FunctionLiteral* fun); void SetStatementPosition(Statement* stmt); @@ -597,6 +602,9 @@ class FullCodeGenerator: public AstVisitor { bool is_eval() { return info_->is_eval(); } bool is_native() { return info_->is_native(); } bool is_classic_mode() { return language_mode() == CLASSIC_MODE; } + StrictModeFlag strict_mode() { + return is_classic_mode() ? kNonStrictMode : kStrictMode; + } LanguageMode language_mode() { return function()->language_mode(); } FunctionLiteral* function() { return info_->function(); } Scope* scope() { return scope_; } diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index d3b1dd8497..d80b93f17b 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -624,7 +624,7 @@ void FullCodeGenerator::DoTest(Expression* condition, Label* if_false, Label* fall_through) { Handle ic = ToBooleanStub::GetUninitialized(isolate()); - CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); + CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); __ test(result_register(), result_register()); // The stub returns nonzero for true. Split(not_zero, if_true, if_false, fall_through); @@ -975,7 +975,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { // Record position before stub call for type feedback. SetSourcePosition(clause->position()); Handle ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); - CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); + CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); patch_site.EmitPatchInfo(); Label skip; @@ -1331,11 +1331,11 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, // load IC call. __ mov(edx, GlobalObjectOperand()); __ mov(ecx, var->name()); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) - ? RelocInfo::CODE_TARGET - : RelocInfo::CODE_TARGET_CONTEXT; - CallIC(ic, mode); + ContextualMode mode = (typeof_state == INSIDE_TYPEOF) + ? NOT_CONTEXTUAL + : CONTEXTUAL; + + CallLoadIC(mode); } @@ -1415,8 +1415,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { // object in eax. __ mov(edx, GlobalObjectOperand()); __ mov(ecx, var->name()); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); + CallLoadIC(CONTEXTUAL); context()->Plug(eax); break; } @@ -1632,10 +1631,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { VisitForAccumulatorValue(value); __ mov(ecx, Immediate(key->value())); __ mov(edx, Operand(esp, 0)); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); + CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); PrepareForBailoutForId(key->id(), NO_REGISTERS); } else { VisitForEffect(value); @@ -2058,19 +2054,17 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ push(eax); // save result __ mov(edx, eax); // result __ mov(ecx, isolate()->factory()->done_string()); // "done" - Handle done_ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(done_ic); // result.done in eax + CallLoadIC(NOT_CONTEXTUAL); // result.done in eax Handle bool_ic = ToBooleanStub::GetUninitialized(isolate()); CallIC(bool_ic); __ test(eax, eax); __ j(zero, &l_try); // result.value - __ pop(edx); // result + __ pop(edx); // result __ mov(ecx, isolate()->factory()->value_string()); // "value" - Handle value_ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(value_ic); // result.value in eax - context()->DropAndPlug(2, eax); // drop iter and g + CallLoadIC(NOT_CONTEXTUAL); // result.value in eax + context()->DropAndPlug(2, eax); // drop iter and g break; } } @@ -2213,15 +2207,14 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { Literal* key = prop->key()->AsLiteral(); ASSERT(!key->value()->IsSmi()); __ mov(ecx, Immediate(key->value())); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); + CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); } void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); Handle ic = isolate()->builtins()->KeyedLoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); } @@ -2242,7 +2235,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, __ bind(&stub_call); __ mov(eax, ecx); BinaryOpICStub stub(op, mode); - CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, + CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, expr->BinaryOperationFeedbackId()); patch_site.EmitPatchInfo(); __ jmp(&done, Label::kNear); @@ -2328,7 +2321,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, __ pop(edx); BinaryOpICStub stub(op, mode); JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. - CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, + CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, expr->BinaryOperationFeedbackId()); patch_site.EmitPatchInfo(); context()->Plug(eax); @@ -2367,10 +2360,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ mov(edx, eax); __ pop(eax); // Restore value. __ mov(ecx, prop->key()->AsLiteral()->value()); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic); + CallStoreIC(NOT_CONTEXTUAL); break; } case KEYED_PROPERTY: { @@ -2397,11 +2387,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, // Global var, const, or let. __ mov(ecx, var->name()); __ mov(edx, GlobalObjectOperand()); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); - + CallStoreIC(CONTEXTUAL); } else if (op == Token::INIT_CONST) { // Const initializers need a write barrier. ASSERT(!var->IsParameter()); // No const parameters. @@ -2495,11 +2481,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { SetSourcePosition(expr->position()); __ mov(ecx, prop->key()->AsLiteral()->value()); __ pop(edx); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); - + CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(eax); } @@ -2518,7 +2500,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { Handle ic = is_classic_mode() ? isolate()->builtins()->KeyedStoreIC_Initialize() : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(eax); @@ -2547,10 +2529,11 @@ void FullCodeGenerator::VisitProperty(Property* expr) { void FullCodeGenerator::CallIC(Handle code, - RelocInfo::Mode rmode, + ContextualMode mode, TypeFeedbackId ast_id) { ic_total_count_++; - __ call(code, rmode, ast_id); + ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); + __ call(code, RelocInfo::CODE_TARGET, ast_id); } @@ -2558,7 +2541,7 @@ void FullCodeGenerator::CallIC(Handle code, void FullCodeGenerator::EmitCallWithIC(Call* expr, Handle name, - RelocInfo::Mode mode) { + ContextualMode mode) { // Code common for calls using the IC. ZoneList* args = expr->arguments(); int arg_count = args->length(); @@ -2572,7 +2555,10 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, SetSourcePosition(expr->position()); Handle ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); - CallIC(ic, mode, expr->CallFeedbackId()); + TypeFeedbackId ast_id = mode == CONTEXTUAL + ? TypeFeedbackId::None() + : expr->CallFeedbackId(); + CallIC(ic, mode, ast_id); RecordJSReturnSite(expr); // Restore context register. __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); @@ -2604,7 +2590,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, Handle ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. - CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); RecordJSReturnSite(expr); // Restore context register. __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); @@ -2714,8 +2700,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { } else if (proxy != NULL && proxy->var()->IsUnallocated()) { // Push global object as receiver for the call IC. __ push(GlobalObjectOperand()); - EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); - + EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { // Call to a lookup slot (dynamically introduced variable). Label slow, done; @@ -2759,7 +2744,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { if (property->key()->IsPropertyName()) { EmitCallWithIC(expr, property->key()->AsLiteral()->value(), - RelocInfo::CODE_TARGET); + NOT_CONTEXTUAL); } else { EmitKeyedCallWithIC(expr, property->key()); } @@ -4150,7 +4135,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->is_jsruntime()) { // Call the JS runtime function via a call IC. __ Set(ecx, Immediate(expr->name())); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET; + ContextualMode mode = NOT_CONTEXTUAL; Handle ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); CallIC(ic, mode, expr->CallRuntimeFeedbackId()); @@ -4410,7 +4395,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ mov(eax, Immediate(Smi::FromInt(1))); BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); CallIC(stub.GetCode(isolate()), - RelocInfo::CODE_TARGET, + NOT_CONTEXTUAL, expr->CountBinOpFeedbackId()); patch_site.EmitPatchInfo(); __ bind(&done); @@ -4442,10 +4427,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { case NAMED_PROPERTY: { __ mov(ecx, prop->key()->AsLiteral()->value()); __ pop(edx); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); + CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { if (!context()->IsEffect()) { @@ -4462,7 +4444,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { Handle ic = is_classic_mode() ? isolate()->builtins()->KeyedStoreIC_Initialize() : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { // Result is on the stack @@ -4487,10 +4469,9 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { Comment cmnt(masm_, "Global variable"); __ mov(edx, GlobalObjectOperand()); __ mov(ecx, Immediate(proxy->name())); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); // Use a regular load, not a contextual load, to avoid a reference // error. - CallIC(ic); + CallLoadIC(NOT_CONTEXTUAL); PrepareForBailout(expr, TOS_REG); context()->Plug(eax); } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { @@ -4652,7 +4633,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { // Record position and call the compare IC. SetSourcePosition(expr->position()); Handle ic = CompareIC::GetUninitialized(isolate(), op); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); patch_site.EmitPatchInfo(); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); @@ -4688,7 +4669,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, Split(equal, if_true, if_false, fall_through); } else { Handle ic = CompareNilICStub::GetUninitialized(isolate(), nil); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); __ test(eax, eax); Split(not_zero, if_true, if_false, fall_through); } diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc index 4db8802f6f..7aa92f23fa 100644 --- a/src/ia32/ic-ia32.cc +++ b/src/ia32/ic-ia32.cc @@ -1319,7 +1319,7 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { } -void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) { // ----------- S t a t e ------------- // -- ecx : name // -- edx : receiver @@ -1327,8 +1327,9 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { // ----------------------------------- // Probe the stub cache. + ExtraICState extra_ic_state = IC::ComputeExtraICState(mode); Code::Flags flags = Code::ComputeFlags( - Code::HANDLER, MONOMORPHIC, kNoExtraICState, + Code::HANDLER, MONOMORPHIC, extra_ic_state, Code::NORMAL, Code::LOAD_IC); masm->isolate()->stub_cache()->GenerateProbe( masm, flags, edx, ecx, ebx, eax); diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index ade9ee3322..bec4924f98 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -3164,10 +3164,9 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { ASSERT(ToRegister(instr->result()).is(eax)); __ mov(ecx, instr->name()); - RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : - RelocInfo::CODE_TARGET_CONTEXT; - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallCode(ic, mode, instr); + ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; + Handle ic = LoadIC::initialize_stub(isolate(), mode); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3196,10 +3195,10 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { ASSERT(ToRegister(instr->value()).is(eax)); __ mov(ecx, instr->name()); - Handle ic = (instr->strict_mode_flag() == kStrictMode) - ? isolate()->builtins()->StoreIC_Initialize_Strict() - : isolate()->builtins()->StoreIC_Initialize(); - CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); + Handle ic = StoreIC::initialize_stub(isolate(), + instr->strict_mode_flag(), + CONTEXTUAL); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3318,7 +3317,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { ASSERT(ToRegister(instr->result()).is(eax)); __ mov(ecx, instr->name()); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); + Handle ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -4228,11 +4227,10 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) { ASSERT(ToRegister(instr->result()).is(eax)); int arity = instr->arity(); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET; Handle ic = - isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL); __ mov(ecx, instr->name()); - CallCode(ic, mode, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -4260,11 +4258,10 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { ASSERT(ToRegister(instr->result()).is(eax)); int arity = instr->arity(); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; Handle ic = - isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL); __ mov(ecx, instr->name()); - CallCode(ic, mode, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -4496,9 +4493,9 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { ASSERT(ToRegister(instr->value()).is(eax)); __ mov(ecx, instr->name()); - Handle ic = (instr->strict_mode_flag() == kStrictMode) - ? isolate()->builtins()->StoreIC_Initialize_Strict() - : isolate()->builtins()->StoreIC_Initialize(); + Handle ic = StoreIC::initialize_stub(isolate(), + instr->strict_mode_flag(), + NOT_CONTEXTUAL); CallCode(ic, RelocInfo::CODE_TARGET, instr); } diff --git a/src/ic.cc b/src/ic.cc index a642230a28..8e5f0ae6b2 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -148,6 +148,9 @@ IC::IC(FrameDepth depth, Isolate* isolate) pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); target_ = handle(raw_target(), isolate); state_ = target_->ic_state(); + extra_ic_state_ = target_->needs_extended_extra_ic_state(target_->kind()) + ? target_->extended_extra_ic_state() + : target_->extra_ic_state(); } @@ -255,9 +258,8 @@ bool CallIC::TryUpdateExtraICState(LookupResult* lookup, argc >= 1 && args[1]->IsNumber()) { double index = DoubleToInteger(args.number_at(1)); if (index < 0 || index >= string->length()) { - extra_ic_state_ = - StringStubState::update(extra_ic_state(), - STRING_INDEX_OUT_OF_BOUNDS); + set_extra_ic_state(StringStubState::update(extra_ic_state(), + STRING_INDEX_OUT_OF_BOUNDS)); return true; } } @@ -398,19 +400,6 @@ void IC::UpdateState(Handle receiver, Handle name) { } -RelocInfo::Mode IC::ComputeMode() { - Address addr = address(); - Code* code = Code::cast(isolate()->FindCodeObject(addr)); - for (RelocIterator it(code, RelocInfo::kCodeTargetMask); - !it.done(); it.next()) { - RelocInfo* info = it.rinfo(); - if (info->pc() == addr) return info->rmode(); - } - UNREACHABLE(); - return RelocInfo::NONE32; -} - - Failure* IC::TypeError(const char* type, Handle object, Handle key) { @@ -500,12 +489,9 @@ void IC::Clear(Isolate* isolate, Address address) { void CallICBase::Clear(Address address, Code* target) { if (IsCleared(target)) return; - bool contextual = CallICBase::Contextual::decode(target->extra_ic_state()); - Code* code = - target->GetIsolate()->stub_cache()->FindCallInitialize( - target->arguments_count(), - contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET, - target->kind()); + ContextualMode mode = IC::GetContextualMode(target->extra_ic_state()); + Code* code = target->GetIsolate()->stub_cache()->FindCallInitialize( + target->arguments_count(), mode, target->kind()); SetTargetAtAddress(address, code); } @@ -521,15 +507,17 @@ void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { if (IsCleared(target)) return; - SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); + Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( + Code::LOAD_IC, target->extra_ic_state()); + SetTargetAtAddress(address, code); } void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { if (IsCleared(target)) return; - SetTargetAtAddress(address, - *pre_monomorphic_stub( - isolate, StoreIC::GetStrictMode(target->extra_ic_state()))); + Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( + Code::STORE_IC, target->extra_ic_state()); + SetTargetAtAddress(address, code); } @@ -1113,6 +1101,26 @@ void IC::PatchCache(Handle type, } +Handle LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) { + Handle ic = isolate->stub_cache()->ComputeLoad( + UNINITIALIZED, IC::ComputeExtraICState(mode)); + return ic; +} + + +Handle LoadIC::pre_monomorphic_stub(Isolate* isolate, + ContextualMode mode) { + return isolate->stub_cache()->ComputeLoad( + PREMONOMORPHIC, IC::ComputeExtraICState(mode)); +} + + +Handle LoadIC::megamorphic_stub() { + return isolate()->stub_cache()->ComputeLoad( + MEGAMORPHIC, extra_ic_state()); +} + + Handle LoadIC::SimpleFieldLoad(int offset, bool inobject, Representation representation) { @@ -1590,6 +1598,35 @@ MaybeObject* StoreIC::Store(Handle object, } +Handle StoreIC::initialize_stub(Isolate* isolate, + StrictModeFlag strict_mode, + ContextualMode mode) { + ExtraICState extra_state = ComputeExtraICState(strict_mode, mode); + Handle ic = isolate->stub_cache()->ComputeStore( + UNINITIALIZED, extra_state); + return ic; +} + + +Handle StoreIC::megamorphic_stub() { + return isolate()->stub_cache()->ComputeStore(MEGAMORPHIC, extra_ic_state()); +} + + +Handle StoreIC::generic_stub() const { + return isolate()->stub_cache()->ComputeStore(GENERIC, extra_ic_state()); +} + + +Handle StoreIC::pre_monomorphic_stub(Isolate* isolate, + StrictModeFlag strict_mode, + ContextualMode contextual_mode) { + ExtraICState state = StoreIC::ComputeExtraICState(strict_mode, + contextual_mode); + return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state); +} + + void StoreIC::UpdateCaches(LookupResult* lookup, Handle receiver, Handle name, diff --git a/src/ic.h b/src/ic.h index 308ab95308..688c227643 100644 --- a/src/ic.h +++ b/src/ic.h @@ -89,6 +89,20 @@ class IC { EXTRA_CALL_FRAME = 1 }; + // ExtraICState shared by all ICs. + class Contextual: public BitField {}; + STATIC_ASSERT(static_cast(NOT_CONTEXTUAL) == 0); + static ExtraICState ComputeExtraICState(ContextualMode mode) { + return Contextual::encode(mode); + } + + static ContextualMode GetContextualMode(ExtraICState state) { + return Contextual::decode(state); + } + + static const ExtraICState kContextualState = + static_cast(CONTEXTUAL) << Contextual::kShift; + // Construct the IC structure with the given number of extra // JavaScript frames on the stack. IC(FrameDepth depth, Isolate* isolate); @@ -106,26 +120,17 @@ class IC { // Clear the inline cache to initial state. static void Clear(Isolate* isolate, Address address); - // Computes the reloc info for this IC. This is a fairly expensive - // operation as it has to search through the heap to find the code - // object that contains this IC site. - RelocInfo::Mode ComputeMode(); - // Returns if this IC is for contextual (no explicit receiver) // access to properties. bool IsUndeclaredGlobal(Handle receiver) { if (receiver->IsGlobalObject()) { - return SlowIsUndeclaredGlobal(); + return IsContextual(); } else { - ASSERT(!SlowIsUndeclaredGlobal()); + ASSERT(!IsContextual()); return false; } } - bool SlowIsUndeclaredGlobal() { - return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT; - } - #ifdef DEBUG bool IsLoadStub() { return target()->is_load_stub() || target()->is_keyed_load_stub(); @@ -169,6 +174,12 @@ class IC { static Type* MapToType(Handle type); static Handle CurrentTypeOf(Handle object, Isolate* isolate); + ContextualMode contextual_mode() const { + return Contextual::decode(extra_ic_state()); + } + + bool IsContextual() const { return contextual_mode() == CONTEXTUAL; } + protected: // Get the call-site target; used for determining the state. Handle target() const { return target_; } @@ -257,7 +268,10 @@ class IC { Handle name); void TryRemoveInvalidHandlers(Handle map, Handle name); - virtual ExtraICState extra_ic_state() { return kNoExtraICState; } + ExtraICState extra_ic_state() const { return extra_ic_state_; } + void set_extra_ic_state(ExtraICState state) { + extra_ic_state_ = state; + } private: Code* raw_target() const { return GetTargetAtAddress(address()); } @@ -278,6 +292,8 @@ class IC { State state_; bool target_set_; + ExtraICState extra_ic_state_; + DISALLOW_IMPLICIT_CONSTRUCTORS(IC); }; @@ -307,7 +323,6 @@ enum StringStubFeedback { class CallICBase: public IC { public: // ExtraICState bits - class Contextual: public BitField {}; class StringStubState: public BitField {}; static ExtraICState ComputeExtraICState(ContextualMode mode, StringStubFeedback feedback) { @@ -368,8 +383,7 @@ class CallICBase: public IC { class CallIC: public CallICBase { public: explicit CallIC(Isolate* isolate) - : CallICBase(Code::CALL_IC, isolate), - extra_ic_state_(target()->extra_ic_state()) { + : CallICBase(Code::CALL_IC, isolate) { ASSERT(target()->is_call_stub()); } @@ -395,12 +409,6 @@ class CallIC: public CallICBase { GenerateMiss(masm, argc, kNoExtraICState); } bool TryUpdateExtraICState(LookupResult* lookup, Handle object); - - protected: - virtual ExtraICState extra_ic_state() { return extra_ic_state_; } - - private: - ExtraICState extra_ic_state_; }; @@ -432,7 +440,8 @@ class KeyedCallIC: public CallICBase { class LoadIC: public IC { public: - explicit LoadIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) { + explicit LoadIC(FrameDepth depth, Isolate* isolate) + : IC(depth, isolate) { ASSERT(IsLoadStub()); } @@ -442,10 +451,12 @@ class LoadIC: public IC { GenerateMiss(masm); } static void GenerateMiss(MacroAssembler* masm); - static void GenerateMegamorphic(MacroAssembler* masm); + static void GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode); static void GenerateNormal(MacroAssembler* masm); static void GenerateRuntimeGetProperty(MacroAssembler* masm); + static Handle initialize_stub(Isolate* isolate, ContextualMode mode); + MUST_USE_RESULT MaybeObject* Load(Handle object, Handle name); @@ -456,9 +467,7 @@ class LoadIC: public IC { return isolate()->builtins()->LoadIC_Slow(); } - virtual Handle megamorphic_stub() { - return isolate()->builtins()->LoadIC_Megamorphic(); - } + virtual Handle megamorphic_stub(); // Update the inline cache and the global stub cache based on the // lookup result. @@ -474,16 +483,11 @@ class LoadIC: public IC { private: // Stub accessors. - static Handle initialize_stub(Isolate* isolate) { - return isolate->builtins()->LoadIC_Initialize(); - } - - static Handle pre_monomorphic_stub(Isolate* isolate) { - return isolate->builtins()->LoadIC_PreMonomorphic(); - } + static Handle pre_monomorphic_stub(Isolate* isolate, + ContextualMode mode); virtual Handle pre_monomorphic_stub() { - return pre_monomorphic_stub(isolate()); + return pre_monomorphic_stub(isolate(), contextual_mode()); } Handle SimpleFieldLoad(int offset, @@ -545,9 +549,6 @@ class KeyedLoadIC: public LoadIC { private: // Stub accessors. - static Handle initialize_stub(Isolate* isolate) { - return isolate->builtins()->KeyedLoadIC_Initialize(); - } static Handle pre_monomorphic_stub(Isolate* isolate) { return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); } @@ -573,11 +574,16 @@ class KeyedLoadIC: public LoadIC { class StoreIC: public IC { public: // ExtraICState bits - class StrictModeState: public BitField {}; + class StrictModeState: public BitField {}; static ExtraICState ComputeExtraICState(StrictModeFlag flag) { return StrictModeState::encode(flag); } + static ExtraICState ComputeExtraICState(StrictModeFlag flag, + ContextualMode mode) { + return StrictModeState::encode(flag) | Contextual::encode(mode); + } + static StrictModeFlag GetStrictMode(ExtraICState state) { return StrictModeState::decode(state); } @@ -588,12 +594,13 @@ class StoreIC: public IC { 1 << StrictModeState::kShift; StoreIC(FrameDepth depth, Isolate* isolate) - : IC(depth, isolate), - strict_mode_(GetStrictMode(target()->extra_ic_state())) { + : IC(depth, isolate) { ASSERT(IsStoreStub()); } - StrictModeFlag strict_mode() const { return strict_mode_; } + StrictModeFlag strict_mode() const { + return StrictModeState::decode(extra_ic_state()); + } // Code generators for stub routines. Only called once at startup. static void GenerateSlow(MacroAssembler* masm); @@ -608,6 +615,10 @@ class StoreIC: public IC { static void GenerateRuntimeSetProperty(MacroAssembler* masm, StrictModeFlag strict_mode); + static Handle initialize_stub(Isolate* isolate, + StrictModeFlag strict_mode, + ContextualMode mode); + MUST_USE_RESULT MaybeObject* Store( Handle object, Handle name, @@ -617,38 +628,22 @@ class StoreIC: public IC { protected: virtual Code::Kind kind() const { return Code::STORE_IC; } - virtual Handle megamorphic_stub() { - if (strict_mode() == kStrictMode) { - return isolate()->builtins()->StoreIC_Megamorphic_Strict(); - } else { - return isolate()->builtins()->StoreIC_Megamorphic(); - } - } + virtual Handle megamorphic_stub(); + // Stub accessors. - virtual Handle generic_stub() const { - if (strict_mode() == kStrictMode) { - return isolate()->builtins()->StoreIC_Generic_Strict(); - } else { - return isolate()->builtins()->StoreIC_Generic(); - } - } + virtual Handle generic_stub() const; virtual Handle slow_stub() const { return isolate()->builtins()->StoreIC_Slow(); } virtual Handle pre_monomorphic_stub() { - return pre_monomorphic_stub(isolate(), strict_mode()); + return pre_monomorphic_stub(isolate(), strict_mode(), contextual_mode()); } static Handle pre_monomorphic_stub(Isolate* isolate, - StrictModeFlag strict_mode) { - if (strict_mode == kStrictMode) { - return isolate->builtins()->StoreIC_PreMonomorphic_Strict(); - } else { - return isolate->builtins()->StoreIC_PreMonomorphic(); - } - } + StrictModeFlag strict_mode, + ContextualMode contextual_mode); // Update the inline cache and the global stub cache based on the // lookup result. @@ -662,31 +657,19 @@ class StoreIC: public IC { Handle value, InlineCacheHolderFlag cache_holder); - virtual ExtraICState extra_ic_state() { - return ComputeExtraICState(strict_mode()); - } - private: void set_target(Code* code) { // Strict mode must be preserved across IC patching. ASSERT(GetStrictMode(code->extra_ic_state()) == GetStrictMode(target()->extra_ic_state())); + // As must the contextual mode + ASSERT(GetContextualMode(code->extra_ic_state()) == + GetContextualMode(target()->extra_ic_state())); IC::set_target(code); } - static Handle initialize_stub(Isolate* isolate, - StrictModeFlag strict_mode) { - if (strict_mode == kStrictMode) { - return isolate->builtins()->StoreIC_Initialize_Strict(); - } else { - return isolate->builtins()->StoreIC_Initialize(); - } - } - static void Clear(Isolate* isolate, Address address, Code* target); - StrictModeFlag strict_mode_; - friend class IC; }; @@ -708,10 +691,10 @@ class KeyedStoreIC: public StoreIC { // ExtraICState bits (building on IC) // ExtraICState bits class ExtraICStateKeyedAccessStoreMode: - public BitField {}; // NOLINT + public BitField {}; // NOLINT static ExtraICState ComputeExtraICState(StrictModeFlag flag, - KeyedAccessStoreMode mode) { + KeyedAccessStoreMode mode) { return StrictModeState::encode(flag) | ExtraICStateKeyedAccessStoreMode::encode(mode); } @@ -747,10 +730,6 @@ class KeyedStoreIC: public StoreIC { virtual void UpdateMegamorphicCache(Type* type, Name* name, Code* code) { } - virtual ExtraICState extra_ic_state() { - return ComputeExtraICState(strict_mode(), STANDARD_STORE); - } - virtual Handle pre_monomorphic_stub() { return pre_monomorphic_stub(isolate(), strict_mode()); } @@ -784,15 +763,6 @@ class KeyedStoreIC: public StoreIC { } // Stub accessors. - static Handle initialize_stub(Isolate* isolate, - StrictModeFlag strict_mode) { - if (strict_mode == kStrictMode) { - return isolate->builtins()->KeyedStoreIC_Initialize_Strict(); - } else { - return isolate->builtins()->KeyedStoreIC_Initialize(); - } - } - virtual Handle generic_stub() const { if (strict_mode() == kStrictMode) { return isolate()->builtins()->KeyedStoreIC_Generic_Strict(); diff --git a/src/log.h b/src/log.h index e53551d8f4..24eaba2cc2 100644 --- a/src/log.h +++ b/src/log.h @@ -119,6 +119,13 @@ struct TickSample; V(CALL_MISS_TAG, "CallMiss") \ V(CALL_NORMAL_TAG, "CallNormal") \ V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic") \ + V(LOAD_INITIALIZE_TAG, "LoadInitialize") \ + V(LOAD_PREMONOMORPHIC_TAG, "LoadPreMonomorphic") \ + V(LOAD_MEGAMORPHIC_TAG, "LoadMegamorphic") \ + V(STORE_INITIALIZE_TAG, "StoreInitialize") \ + V(STORE_PREMONOMORPHIC_TAG, "StorePreMonomorphic") \ + V(STORE_GENERIC_TAG, "StoreGeneric") \ + V(STORE_MEGAMORPHIC_TAG, "StoreMegamorphic") \ V(KEYED_CALL_DEBUG_BREAK_TAG, "KeyedCallDebugBreak") \ V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG, \ "KeyedCallDebugPrepareStepIn") \ diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index 4225270e67..58a0c0150a 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -672,7 +672,7 @@ void FullCodeGenerator::DoTest(Expression* condition, Label* fall_through) { __ mov(a0, result_register()); Handle ic = ToBooleanStub::GetUninitialized(isolate()); - CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); + CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); __ mov(at, zero_reg); Split(ne, v0, Operand(at), if_true, if_false, fall_through); } @@ -1037,7 +1037,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { // Record position before stub call for type feedback. SetSourcePosition(clause->position()); Handle ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); - CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); + CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); patch_site.EmitPatchInfo(); Label skip; @@ -1400,11 +1400,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, __ lw(a0, GlobalObjectOperand()); __ li(a2, Operand(var->name())); - RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) - ? RelocInfo::CODE_TARGET - : RelocInfo::CODE_TARGET_CONTEXT; - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(ic, mode); + ContextualMode mode = (typeof_state == INSIDE_TYPEOF) + ? NOT_CONTEXTUAL + : CONTEXTUAL; + CallLoadIC(mode); } @@ -1487,8 +1486,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { // object (receiver) in a0. __ lw(a0, GlobalObjectOperand()); __ li(a2, Operand(var->name())); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); + CallLoadIC(CONTEXTUAL); context()->Plug(v0); break; } @@ -1700,10 +1698,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ mov(a0, result_register()); __ li(a2, Operand(key->value())); __ lw(a1, MemOperand(sp)); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); + CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); PrepareForBailoutForId(key->id(), NO_REGISTERS); } else { VisitForEffect(value); @@ -2118,8 +2113,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ mov(a0, v0); __ push(a0); // save result __ LoadRoot(a2, Heap::kdone_stringRootIndex); // "done" - Handle done_ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(done_ic); // result.done in v0 + CallLoadIC(NOT_CONTEXTUAL); // result.done in v0 __ mov(a0, v0); Handle bool_ic = ToBooleanStub::GetUninitialized(isolate()); CallIC(bool_ic); @@ -2128,8 +2122,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { // result.value __ pop(a0); // result __ LoadRoot(a2, Heap::kvalue_stringRootIndex); // "value" - Handle value_ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(value_ic); // result.value in v0 + CallLoadIC(NOT_CONTEXTUAL); // result.value in v0 context()->DropAndPlug(2, v0); // drop iter and g break; } @@ -2277,8 +2270,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { __ mov(a0, result_register()); __ li(a2, Operand(key->value())); // Call load IC. It has arguments receiver and property name a0 and a2. - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); + CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); } @@ -2287,7 +2279,7 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { __ mov(a0, result_register()); // Call keyed load IC. It has arguments key and receiver in a0 and a1. Handle ic = isolate()->builtins()->KeyedLoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); } @@ -2315,8 +2307,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, __ bind(&stub_call); BinaryOpICStub stub(op, mode); - CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, - expr->BinaryOperationFeedbackId()); + CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, + expr->BinaryOperationFeedbackId()); patch_site.EmitPatchInfo(); __ jmp(&done); @@ -2398,7 +2390,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, __ pop(a1); BinaryOpICStub stub(op, mode); JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. - CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, + CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, expr->BinaryOperationFeedbackId()); patch_site.EmitPatchInfo(); context()->Plug(v0); @@ -2437,10 +2429,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ mov(a1, result_register()); __ pop(a0); // Restore value. __ li(a2, Operand(prop->key()->AsLiteral()->value())); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic); + CallStoreIC(NOT_CONTEXTUAL); break; } case KEYED_PROPERTY: { @@ -2467,11 +2456,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, __ mov(a0, result_register()); __ li(a2, Operand(var->name())); __ lw(a1, GlobalObjectOperand()); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); - + CallStoreIC(CONTEXTUAL); } else if (op == Token::INIT_CONST) { // Const initializers need a write barrier. ASSERT(!var->IsParameter()); // No const parameters. @@ -2569,10 +2554,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ li(a2, Operand(prop->key()->AsLiteral()->value())); __ pop(a1); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); + CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(v0); @@ -2595,7 +2577,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { Handle ic = is_classic_mode() ? isolate()->builtins()->KeyedStoreIC_Initialize() : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(v0); @@ -2622,16 +2604,17 @@ void FullCodeGenerator::VisitProperty(Property* expr) { void FullCodeGenerator::CallIC(Handle code, - RelocInfo::Mode rmode, + ContextualMode mode, TypeFeedbackId id) { ic_total_count_++; - __ Call(code, rmode, id); + ASSERT(mode != CONTEXTUAL || id.IsNone()); + __ Call(code, RelocInfo::CODE_TARGET, id); } void FullCodeGenerator::EmitCallWithIC(Call* expr, Handle name, - RelocInfo::Mode mode) { + ContextualMode mode) { // Code common for calls using the IC. ZoneList* args = expr->arguments(); int arg_count = args->length(); @@ -2646,7 +2629,10 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, // Call the IC initialization code. Handle ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); - CallIC(ic, mode, expr->CallFeedbackId()); + TypeFeedbackId ast_id = mode == CONTEXTUAL + ? TypeFeedbackId::None() + : expr->CallFeedbackId(); + CallIC(ic, mode, ast_id); RecordJSReturnSite(expr); // Restore context register. __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); @@ -2679,7 +2665,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, Handle ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); __ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. - CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); RecordJSReturnSite(expr); // Restore context register. __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); @@ -2795,7 +2781,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { // Push global object as receiver for the call IC. __ lw(a0, GlobalObjectOperand()); __ push(a0); - EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); + EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { // Call to a lookup slot (dynamically introduced variable). Label slow, done; @@ -2842,7 +2828,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { if (property->key()->IsPropertyName()) { EmitCallWithIC(expr, property->key()->AsLiteral()->value(), - RelocInfo::CODE_TARGET); + NOT_CONTEXTUAL); } else { EmitKeyedCallWithIC(expr, property->key()); } @@ -4213,7 +4199,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->is_jsruntime()) { // Call the JS runtime function. __ li(a2, Operand(expr->name())); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET; + ContextualMode mode = NOT_CONTEXTUAL; Handle ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); CallIC(ic, mode, expr->CallRuntimeFeedbackId()); @@ -4467,7 +4453,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); CallIC(stub.GetCode(isolate()), - RelocInfo::CODE_TARGET, + NOT_CONTEXTUAL, expr->CountBinOpFeedbackId()); patch_site.EmitPatchInfo(); __ bind(&done); @@ -4498,10 +4484,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ mov(a0, result_register()); // Value. __ li(a2, Operand(prop->key()->AsLiteral()->value())); // Name. __ pop(a1); // Receiver. - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); + CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { if (!context()->IsEffect()) { @@ -4518,7 +4501,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { Handle ic = is_classic_mode() ? isolate()->builtins()->KeyedStoreIC_Initialize() : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { if (!context()->IsEffect()) { @@ -4541,10 +4524,9 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { Comment cmnt(masm_, "Global variable"); __ lw(a0, GlobalObjectOperand()); __ li(a2, Operand(proxy->name())); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); // Use a regular load, not a contextual load, to avoid a reference // error. - CallIC(ic); + CallLoadIC(NOT_CONTEXTUAL); PrepareForBailout(expr, TOS_REG); context()->Plug(v0); } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { @@ -4704,7 +4686,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { // Record position and call the compare IC. SetSourcePosition(expr->position()); Handle ic = CompareIC::GetUninitialized(isolate(), op); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); patch_site.EmitPatchInfo(); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); @@ -4738,7 +4720,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, Split(eq, a0, Operand(a1), if_true, if_false, fall_through); } else { Handle ic = CompareNilICStub::GetUninitialized(isolate(), nil); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); Split(ne, v0, Operand(zero_reg), if_true, if_false, fall_through); } context()->Plug(if_true, if_false); diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc index 4c1ddbd5ca..10dc0134c4 100644 --- a/src/mips/ic-mips.cc +++ b/src/mips/ic-mips.cc @@ -646,7 +646,7 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { } -void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) { // ----------- S t a t e ------------- // -- a2 : name // -- ra : return address @@ -654,8 +654,9 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { // ----------------------------------- // Probe the stub cache. + ExtraICState extra_ic_state = IC::ComputeExtraICState(mode); Code::Flags flags = Code::ComputeFlags( - Code::HANDLER, MONOMORPHIC, kNoExtraICState, + Code::HANDLER, MONOMORPHIC, extra_ic_state, Code::NORMAL, Code::LOAD_IC); masm->isolate()->stub_cache()->GenerateProbe( masm, flags, a0, a2, a3, t0, t1, t2); diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 02eb26903e..8f56841a44 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -2815,10 +2815,9 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { ASSERT(ToRegister(instr->result()).is(v0)); __ li(a2, Operand(instr->name())); - RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET - : RelocInfo::CODE_TARGET_CONTEXT; - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallCode(ic, mode, instr); + ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; + Handle ic = LoadIC::initialize_stub(isolate(), mode); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -2853,10 +2852,10 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { ASSERT(ToRegister(instr->value()).is(a0)); __ li(a2, Operand(instr->name())); - Handle ic = (instr->strict_mode_flag() == kStrictMode) - ? isolate()->builtins()->StoreIC_Initialize_Strict() - : isolate()->builtins()->StoreIC_Initialize(); - CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); + Handle ic = StoreIC::initialize_stub(isolate(), + instr->strict_mode_flag(), + CONTEXTUAL); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -2953,7 +2952,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { // Name is always in a2. __ li(a2, Operand(instr->name())); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); + Handle ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3905,11 +3904,10 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) { ASSERT(ToRegister(instr->result()).is(v0)); int arity = instr->arity(); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET; Handle ic = - isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL); __ li(a2, Operand(instr->name())); - CallCode(ic, mode, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3934,11 +3932,10 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { ASSERT(ToRegister(instr->result()).is(v0)); int arity = instr->arity(); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; Handle ic = - isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL); __ li(a2, Operand(instr->name())); - CallCode(ic, mode, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -4135,9 +4132,9 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { // Name is always in a2. __ li(a2, Operand(instr->name())); - Handle ic = (instr->strict_mode_flag() == kStrictMode) - ? isolate()->builtins()->StoreIC_Initialize_Strict() - : isolate()->builtins()->StoreIC_Initialize(); + Handle ic = StoreIC::initialize_stub(isolate(), + instr->strict_mode_flag(), + NOT_CONTEXTUAL); CallCode(ic, RelocInfo::CODE_TARGET, instr); } diff --git a/src/objects.cc b/src/objects.cc index cf21e802eb..a55556de44 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -10617,8 +10617,7 @@ void Code::ClearInlineCaches(Code::Kind kind) { void Code::ClearInlineCaches(Code::Kind* kind) { int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | - RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) | - RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT); + RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); for (RelocIterator it(this, mask); !it.done(); it.next()) { RelocInfo* info = it.rinfo(); Code* target(Code::GetCodeFromTargetAddress(info->target_address())); @@ -10843,6 +10842,17 @@ bool Code::CanDeoptAt(Address pc) { } +bool Code::IsContextual() { + ASSERT(is_inline_cache_stub()); + Kind kind = this->kind(); + if (kind == STORE_IC || kind == LOAD_IC || kind == CALL_IC) { + ExtraICState extra_state = extra_ic_state(); + return IC::GetContextualMode(extra_state) == CONTEXTUAL; + } + return false; +} + + // Identify kind of code. const char* Code::Kind2String(Kind kind) { switch (kind) { diff --git a/src/objects.h b/src/objects.h index 91a2aea2b8..76c2426ad4 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5137,6 +5137,7 @@ class Code: public HeapObject { kind == BINARY_OP_IC; } + bool IsContextual(); // Only valid for IC stubs. inline StubType type(); // Only valid for monomorphic IC stubs. inline int arguments_count(); // Only valid for call IC stubs. diff --git a/src/stub-cache.cc b/src/stub-cache.cc index e8b94f104f..b273a6ea4e 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -147,10 +147,10 @@ Handle StubCache::ComputeMonomorphicIC( } if (kind == Code::LOAD_IC) { - LoadStubCompiler ic_compiler(isolate(), flag); + LoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); ic = ic_compiler.CompileMonomorphicIC(type, handler, name); } else if (kind == Code::KEYED_LOAD_IC) { - KeyedLoadStubCompiler ic_compiler(isolate(), flag); + KeyedLoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); ic = ic_compiler.CompileMonomorphicIC(type, handler, name); } else if (kind == Code::STORE_IC) { StoreStubCompiler ic_compiler(isolate(), extra_ic_state); @@ -419,12 +419,11 @@ static void FillCache(Isolate* isolate, Handle code) { Code* StubCache::FindCallInitialize(int argc, - RelocInfo::Mode mode, + ContextualMode mode, Code::Kind kind) { ExtraICState extra_state = CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) | - CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT - ? CONTEXTUAL : NOT_CONTEXTUAL); + CallICBase::Contextual::encode(mode); Code::Flags flags = Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc); UnseededNumberDictionary* dictionary = @@ -438,13 +437,24 @@ Code* StubCache::FindCallInitialize(int argc, } +Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) { + Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); + UnseededNumberDictionary* dictionary = + isolate()->heap()->non_monomorphic_cache(); + int entry = dictionary->FindEntry(isolate(), flags); + ASSERT(entry != -1); + Object* code = dictionary->ValueAt(entry); + // This might be called during the marking phase of the collector + // hence the unchecked cast. + return reinterpret_cast(code); +} + + Handle StubCache::ComputeCallInitialize(int argc, - RelocInfo::Mode mode, + ContextualMode mode, Code::Kind kind) { ExtraICState extra_state = - CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) | - CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT - ? CONTEXTUAL : NOT_CONTEXTUAL); + CallICBase::ComputeExtraICState(mode, DEFAULT_STRING_STUB); Code::Flags flags = Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc); Handle cache = @@ -459,14 +469,13 @@ Handle StubCache::ComputeCallInitialize(int argc, } -Handle StubCache::ComputeCallInitialize(int argc, RelocInfo::Mode mode) { +Handle StubCache::ComputeCallInitialize(int argc, ContextualMode mode) { return ComputeCallInitialize(argc, mode, Code::CALL_IC); } Handle StubCache::ComputeKeyedCallInitialize(int argc) { - return ComputeCallInitialize(argc, RelocInfo::CODE_TARGET, - Code::KEYED_CALL_IC); + return ComputeCallInitialize(argc, NOT_CONTEXTUAL, Code::KEYED_CALL_IC); } @@ -540,6 +549,57 @@ Handle StubCache::ComputeCallMegamorphic( } +Handle StubCache::ComputeLoad(InlineCacheState ic_state, + ExtraICState extra_state) { + Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); + Handle cache = + isolate_->factory()->non_monomorphic_cache(); + int entry = cache->FindEntry(isolate_, flags); + if (entry != -1) return Handle(Code::cast(cache->ValueAt(entry))); + + StubCompiler compiler(isolate_); + Handle code; + if (ic_state == UNINITIALIZED) { + code = compiler.CompileLoadInitialize(flags); + } else if (ic_state == PREMONOMORPHIC) { + code = compiler.CompileLoadPreMonomorphic(flags); + } else if (ic_state == MEGAMORPHIC) { + code = compiler.CompileLoadMegamorphic(flags); + } else { + UNREACHABLE(); + } + FillCache(isolate_, code); + return code; +} + + +Handle StubCache::ComputeStore(InlineCacheState ic_state, + ExtraICState extra_state) { + Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, ic_state, extra_state); + Handle cache = + isolate_->factory()->non_monomorphic_cache(); + int entry = cache->FindEntry(isolate_, flags); + if (entry != -1) return Handle(Code::cast(cache->ValueAt(entry))); + + StubCompiler compiler(isolate_); + Handle code; + if (ic_state == UNINITIALIZED) { + code = compiler.CompileStoreInitialize(flags); + } else if (ic_state == PREMONOMORPHIC) { + code = compiler.CompileStorePreMonomorphic(flags); + } else if (ic_state == GENERIC) { + code = compiler.CompileStoreGeneric(flags); + } else if (ic_state == MEGAMORPHIC) { + code = compiler.CompileStoreMegamorphic(flags); + } else { + UNREACHABLE(); + } + + FillCache(isolate_, code); + return code; +} + + Handle StubCache::ComputeCallMiss(int argc, Code::Kind kind, ExtraICState extra_state) { @@ -618,13 +678,12 @@ Handle StubCache::ComputePolymorphicIC( Code::StubType type = number_of_valid_types == 1 ? handler->type() : Code::NORMAL; if (kind == Code::LOAD_IC) { - LoadStubCompiler ic_compiler(isolate_); + LoadStubCompiler ic_compiler(isolate_, extra_ic_state); return ic_compiler.CompilePolymorphicIC( types, handlers, name, type, PROPERTY); } else { ASSERT(kind == Code::STORE_IC); - StrictModeFlag strict_mode = StoreIC::GetStrictMode(extra_ic_state); - StoreStubCompiler ic_compiler(isolate_, strict_mode); + StoreStubCompiler ic_compiler(isolate_, extra_ic_state); return ic_compiler.CompilePolymorphicIC( types, handlers, name, type, PROPERTY); } @@ -834,7 +893,9 @@ static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) { HandleScope scope(isolate); IC ic(IC::NO_EXTRA_FRAME, isolate); ASSERT(ic.IsLoadStub()); - if (!ic.SlowIsUndeclaredGlobal()) return isolate->heap()->undefined_value(); + if (!ic.IsContextual()) { + return isolate->heap()->undefined_value(); + } // Throw a reference error. Handle name_handle(name); @@ -1027,6 +1088,81 @@ Handle StubCompiler::CompileCallMegamorphic(Code::Flags flags) { } +Handle StubCompiler::CompileLoadInitialize(Code::Flags flags) { + LoadIC::GenerateInitialize(masm()); + Handle code = GetCodeWithFlags(flags, "CompileLoadInitialize"); + PROFILE(isolate(), + CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); + GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); + return code; +} + + +Handle StubCompiler::CompileLoadPreMonomorphic(Code::Flags flags) { + LoadIC::GeneratePreMonomorphic(masm()); + Handle code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); + PROFILE(isolate(), + CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); + GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); + return code; +} + + +Handle StubCompiler::CompileLoadMegamorphic(Code::Flags flags) { + ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); + ContextualMode mode = IC::GetContextualMode(extra_state); + LoadIC::GenerateMegamorphic(masm(), mode); + Handle code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); + PROFILE(isolate(), + CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); + GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); + return code; +} + + +Handle StubCompiler::CompileStoreInitialize(Code::Flags flags) { + StoreIC::GenerateInitialize(masm()); + Handle code = GetCodeWithFlags(flags, "CompileStoreInitialize"); + PROFILE(isolate(), + CodeCreateEvent(Logger::STORE_INITIALIZE_TAG, *code, 0)); + GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); + return code; +} + + +Handle StubCompiler::CompileStorePreMonomorphic(Code::Flags flags) { + StoreIC::GeneratePreMonomorphic(masm()); + Handle code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic"); + PROFILE(isolate(), + CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG, *code, 0)); + GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); + return code; +} + + +Handle StubCompiler::CompileStoreGeneric(Code::Flags flags) { + ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); + StrictModeFlag strict_mode = StoreIC::GetStrictMode(extra_state); + StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode); + Handle code = GetCodeWithFlags(flags, "CompileStoreGeneric"); + PROFILE(isolate(), + CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0)); + GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); + return code; +} + + +Handle StubCompiler::CompileStoreMegamorphic(Code::Flags flags) { + ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); + StoreIC::GenerateMegamorphic(masm(), extra_state); + Handle code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); + PROFILE(isolate(), + CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); + GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); + return code; +} + + Handle StubCompiler::CompileCallArguments(Code::Flags flags) { int argc = Code::ExtractArgumentsCountFromFlags(flags); KeyedCallIC::GenerateNonStrictArguments(masm(), argc); diff --git a/src/stub-cache.h b/src/stub-cache.h index 0cf9e8fae0..2d061ab2a9 100644 --- a/src/stub-cache.h +++ b/src/stub-cache.h @@ -138,7 +138,7 @@ class StubCache { // --- - Handle ComputeCallInitialize(int argc, RelocInfo::Mode mode); + Handle ComputeCallInitialize(int argc, ContextualMode mode); Handle ComputeKeyedCallInitialize(int argc); @@ -162,6 +162,12 @@ class StubCache { // --- + Handle ComputeLoad(InlineCacheState ic_state, ExtraICState extra_state); + Handle ComputeStore(InlineCacheState ic_state, + ExtraICState extra_state); + + // --- + Handle ComputeCompareNil(Handle receiver_map, CompareNilICStub& stub); @@ -179,7 +185,8 @@ class StubCache { ExtraICState extra_ic_state); // Finds the Code object stored in the Heap::non_monomorphic_cache(). - Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind); + Code* FindCallInitialize(int argc, ContextualMode mode, Code::Kind kind); + Code* FindPreMonomorphicIC(Code::Kind kind, ExtraICState extra_ic_state); #ifdef ENABLE_DEBUGGER_SUPPORT Handle ComputeCallDebugBreak(int argc, Code::Kind kind); @@ -263,7 +270,7 @@ class StubCache { explicit StubCache(Isolate* isolate); Handle ComputeCallInitialize(int argc, - RelocInfo::Mode mode, + ContextualMode mode, Code::Kind kind); // The stub cache has a primary and secondary level. The two levels have @@ -378,6 +385,15 @@ class StubCompiler BASE_EMBEDDED { Handle CompileCallArguments(Code::Flags flags); Handle CompileCallMiss(Code::Flags flags); + Handle CompileLoadInitialize(Code::Flags flags); + Handle CompileLoadPreMonomorphic(Code::Flags flags); + Handle CompileLoadMegamorphic(Code::Flags flags); + + Handle CompileStoreInitialize(Code::Flags flags); + Handle CompileStorePreMonomorphic(Code::Flags flags); + Handle CompileStoreGeneric(Code::Flags flags); + Handle CompileStoreMegamorphic(Code::Flags flags); + #ifdef ENABLE_DEBUGGER_SUPPORT Handle CompileCallDebugBreak(Code::Flags flags); Handle CompileCallDebugPrepareStepIn(Code::Flags flags); @@ -503,6 +519,9 @@ class StubCompiler BASE_EMBEDDED { Isolate* isolate() { return isolate_; } Heap* heap() { return isolate()->heap(); } Factory* factory() { return isolate()->factory(); } + ContextualMode contextual_mode() { + return IC::GetContextualMode(extra_state()); + } static void GenerateTailCall(MacroAssembler* masm, Handle code); diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 99206b97ed..904aba4694 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -630,7 +630,7 @@ void FullCodeGenerator::DoTest(Expression* condition, Label* if_false, Label* fall_through) { Handle ic = ToBooleanStub::GetUninitialized(isolate()); - CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); + CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); __ testq(result_register(), result_register()); // The stub returns nonzero for true. Split(not_zero, if_true, if_false, fall_through); @@ -983,7 +983,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { // Record position before stub call for type feedback. SetSourcePosition(clause->position()); Handle ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); - CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); + CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); patch_site.EmitPatchInfo(); Label skip; @@ -1353,11 +1353,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, // load IC call. __ movq(rax, GlobalObjectOperand()); __ Move(rcx, var->name()); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) - ? RelocInfo::CODE_TARGET - : RelocInfo::CODE_TARGET_CONTEXT; - CallIC(ic, mode); + ContextualMode mode = (typeof_state == INSIDE_TYPEOF) + ? NOT_CONTEXTUAL + : CONTEXTUAL; + CallLoadIC(mode); } @@ -1437,8 +1436,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { // object on the stack. __ Move(rcx, var->name()); __ movq(rax, GlobalObjectOperand()); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); + CallLoadIC(CONTEXTUAL); context()->Plug(rax); break; } @@ -1652,10 +1650,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { VisitForAccumulatorValue(value); __ Move(rcx, key->value()); __ movq(rdx, Operand(rsp, 0)); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); + CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); PrepareForBailoutForId(key->id(), NO_REGISTERS); } else { VisitForEffect(value); @@ -2077,8 +2072,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ bind(&l_loop); __ push(rax); // save result __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done" - Handle done_ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(done_ic); // result.done in rax + CallLoadIC(NOT_CONTEXTUAL); // result.done in rax Handle bool_ic = ToBooleanStub::GetUninitialized(isolate()); CallIC(bool_ic); __ testq(result_register(), result_register()); @@ -2087,8 +2081,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { // result.value __ pop(rax); // result __ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value" - Handle value_ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(value_ic); // result.value in rax + CallLoadIC(NOT_CONTEXTUAL); // result.value in rax context()->DropAndPlug(2, rax); // drop iter and g break; } @@ -2234,15 +2227,14 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); Literal* key = prop->key()->AsLiteral(); __ Move(rcx, key->value()); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); + CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); } void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); Handle ic = isolate()->builtins()->KeyedLoadIC_Initialize(); - CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); } @@ -2264,7 +2256,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, __ bind(&stub_call); __ movq(rax, rcx); BinaryOpICStub stub(op, mode); - CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, + CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, expr->BinaryOperationFeedbackId()); patch_site.EmitPatchInfo(); __ jmp(&done, Label::kNear); @@ -2314,7 +2306,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, __ pop(rdx); BinaryOpICStub stub(op, mode); JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. - CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, + CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, expr->BinaryOperationFeedbackId()); patch_site.EmitPatchInfo(); context()->Plug(rax); @@ -2353,10 +2345,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ movq(rdx, rax); __ pop(rax); // Restore value. __ Move(rcx, prop->key()->AsLiteral()->value()); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic); + CallStoreIC(NOT_CONTEXTUAL); break; } case KEYED_PROPERTY: { @@ -2383,10 +2372,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, // Global var, const, or let. __ Move(rcx, var->name()); __ movq(rdx, GlobalObjectOperand()); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); + CallStoreIC(CONTEXTUAL); } else if (op == Token::INIT_CONST) { // Const initializers need a write barrier. ASSERT(!var->IsParameter()); // No const parameters. @@ -2477,10 +2463,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { SetSourcePosition(expr->position()); __ Move(rcx, prop->key()->AsLiteral()->value()); __ pop(rdx); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); + CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(rax); @@ -2497,7 +2480,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { Handle ic = is_classic_mode() ? isolate()->builtins()->KeyedStoreIC_Initialize() : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(rax); @@ -2524,16 +2507,17 @@ void FullCodeGenerator::VisitProperty(Property* expr) { void FullCodeGenerator::CallIC(Handle code, - RelocInfo::Mode rmode, + ContextualMode mode, TypeFeedbackId ast_id) { ic_total_count_++; - __ call(code, rmode, ast_id); + ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); + __ call(code, RelocInfo::CODE_TARGET, ast_id); } void FullCodeGenerator::EmitCallWithIC(Call* expr, Handle name, - RelocInfo::Mode mode) { + ContextualMode mode) { // Code common for calls using the IC. ZoneList* args = expr->arguments(); int arg_count = args->length(); @@ -2548,7 +2532,10 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, // Call the IC initialization code. Handle ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); - CallIC(ic, mode, expr->CallFeedbackId()); + TypeFeedbackId ast_id = mode == CONTEXTUAL + ? TypeFeedbackId::None() + : expr->CallFeedbackId(); + CallIC(ic, mode, ast_id); RecordJSReturnSite(expr); // Restore context register. __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); @@ -2581,7 +2568,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, Handle ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. - CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); RecordJSReturnSite(expr); // Restore context register. __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); @@ -2693,7 +2680,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { // Call to a global variable. Push global object as receiver for the // call IC lookup. __ push(GlobalObjectOperand()); - EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); + EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { // Call to a lookup slot (dynamically introduced variable). Label slow, done; @@ -2737,7 +2724,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { if (property->key()->IsPropertyName()) { EmitCallWithIC(expr, property->key()->AsLiteral()->value(), - RelocInfo::CODE_TARGET); + NOT_CONTEXTUAL); } else { EmitKeyedCallWithIC(expr, property->key()); } @@ -4146,7 +4133,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->is_jsruntime()) { // Call the JS runtime function using a call IC. __ Move(rcx, expr->name()); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET; + ContextualMode mode = NOT_CONTEXTUAL; Handle ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); CallIC(ic, mode, expr->CallRuntimeFeedbackId()); @@ -4400,7 +4387,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ Move(rax, Smi::FromInt(1)); BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); CallIC(stub.GetCode(isolate()), - RelocInfo::CODE_TARGET, + NOT_CONTEXTUAL, expr->CountBinOpFeedbackId()); patch_site.EmitPatchInfo(); __ bind(&done); @@ -4432,10 +4419,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { case NAMED_PROPERTY: { __ Move(rcx, prop->key()->AsLiteral()->value()); __ pop(rdx); - Handle ic = is_classic_mode() - ? isolate()->builtins()->StoreIC_Initialize() - : isolate()->builtins()->StoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); + CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { if (!context()->IsEffect()) { @@ -4452,7 +4436,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { Handle ic = is_classic_mode() ? isolate()->builtins()->KeyedStoreIC_Initialize() : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { if (!context()->IsEffect()) { @@ -4476,10 +4460,9 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { Comment cmnt(masm_, "Global variable"); __ Move(rcx, proxy->name()); __ movq(rax, GlobalObjectOperand()); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); // Use a regular load, not a contextual load, to avoid a reference // error. - CallIC(ic); + CallLoadIC(NOT_CONTEXTUAL); PrepareForBailout(expr, TOS_REG); context()->Plug(rax); } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { @@ -4641,7 +4624,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { // Record position and call the compare IC. SetSourcePosition(expr->position()); Handle ic = CompareIC::GetUninitialized(isolate(), op); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); patch_site.EmitPatchInfo(); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); @@ -4676,7 +4659,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, Split(equal, if_true, if_false, fall_through); } else { Handle ic = CompareNilICStub::GetUninitialized(isolate(), nil); - CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); + CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); __ testq(rax, rax); Split(not_zero, if_true, if_false, fall_through); } diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc index b2d33e0247..886d50be9c 100644 --- a/src/x64/ic-x64.cc +++ b/src/x64/ic-x64.cc @@ -1345,7 +1345,7 @@ void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm, } -void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) { // ----------- S t a t e ------------- // -- rax : receiver // -- rcx : name @@ -1353,8 +1353,9 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { // ----------------------------------- // Probe the stub cache. + ExtraICState extra_ic_state = IC::ComputeExtraICState(mode); Code::Flags flags = Code::ComputeFlags( - Code::HANDLER, MONOMORPHIC, kNoExtraICState, + Code::HANDLER, MONOMORPHIC, extra_ic_state, Code::NORMAL, Code::LOAD_IC); masm->isolate()->stub_cache()->GenerateProbe( masm, flags, rax, rcx, rbx, rdx); diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index e6a20f21f8..9b32e68c57 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -2708,10 +2708,9 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { ASSERT(ToRegister(instr->result()).is(rax)); __ Move(rcx, instr->name()); - RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : - RelocInfo::CODE_TARGET_CONTEXT; - Handle ic = isolate()->builtins()->LoadIC_Initialize(); - CallCode(ic, mode, instr); + ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; + Handle ic = LoadIC::initialize_stub(isolate(), mode); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -2747,10 +2746,10 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { ASSERT(ToRegister(instr->value()).is(rax)); __ Move(rcx, instr->name()); - Handle ic = (instr->strict_mode_flag() == kStrictMode) - ? isolate()->builtins()->StoreIC_Initialize_Strict() - : isolate()->builtins()->StoreIC_Initialize(); - CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); + Handle ic = StoreIC::initialize_stub(isolate(), + instr->strict_mode_flag(), + CONTEXTUAL); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -2857,7 +2856,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { ASSERT(ToRegister(instr->result()).is(rax)); __ Move(rcx, instr->name()); - Handle ic = isolate()->builtins()->LoadIC_Initialize(); + Handle ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3801,11 +3800,10 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) { ASSERT(ToRegister(instr->result()).is(rax)); int arity = instr->arity(); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET; Handle ic = - isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL); __ Move(rcx, instr->name()); - CallCode(ic, mode, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3832,11 +3830,10 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { ASSERT(ToRegister(instr->context()).is(rsi)); ASSERT(ToRegister(instr->result()).is(rax)); int arity = instr->arity(); - RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; Handle ic = - isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL); __ Move(rcx, instr->name()); - CallCode(ic, mode, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -4075,9 +4072,9 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { ASSERT(ToRegister(instr->value()).is(rax)); __ Move(rcx, instr->hydrogen()->name()); - Handle ic = (instr->strict_mode_flag() == kStrictMode) - ? isolate()->builtins()->StoreIC_Initialize_Strict() - : isolate()->builtins()->StoreIC_Initialize(); + Handle ic = StoreIC::initialize_stub(isolate(), + instr->strict_mode_flag(), + NOT_CONTEXTUAL); CallCode(ic, RelocInfo::CODE_TARGET, instr); } diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc index 59557b8797..d26f0cf38c 100644 --- a/test/cctest/test-debug.cc +++ b/test/cctest/test-debug.cc @@ -1040,13 +1040,13 @@ TEST(DebugStub) { CheckDebugBreakFunction(&env, "function f2(){x=1;}", "f2", 0, - v8::internal::RelocInfo::CODE_TARGET_CONTEXT, + v8::internal::RelocInfo::CODE_TARGET, CcTest::i_isolate()->builtins()->builtin( Builtins::kStoreIC_DebugBreak)); CheckDebugBreakFunction(&env, "function f3(){var a=x;}", "f3", 0, - v8::internal::RelocInfo::CODE_TARGET_CONTEXT, + v8::internal::RelocInfo::CODE_TARGET, CcTest::i_isolate()->builtins()->builtin( Builtins::kLoadIC_DebugBreak)); @@ -1091,19 +1091,19 @@ TEST(DebugStub) { CheckDebugBreakFunction(&env, "function f4_0(){x();}", "f4_0", 0, - v8::internal::RelocInfo::CODE_TARGET_CONTEXT, + v8::internal::RelocInfo::CODE_TARGET, *debug_break_0); CheckDebugBreakFunction(&env, "function f4_1(){x(1);}", "f4_1", 0, - v8::internal::RelocInfo::CODE_TARGET_CONTEXT, + v8::internal::RelocInfo::CODE_TARGET, *debug_break_1); CheckDebugBreakFunction(&env, "function f4_4(){x(1,2,3,4);}", "f4_4", 0, - v8::internal::RelocInfo::CODE_TARGET_CONTEXT, + v8::internal::RelocInfo::CODE_TARGET, *debug_break_4); } diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc index 2b4c82f2b1..722194daa2 100644 --- a/test/cctest/test-disasm-ia32.cc +++ b/test/cctest/test-disasm-ia32.cc @@ -28,6 +28,7 @@ #include #include "v8.h" +#include "stub-cache.h" #include "debug.h" #include "disasm.h" @@ -254,7 +255,7 @@ TEST(DisasmIa320) { __ bind(&L2); __ call(Operand(ebx, ecx, times_4, 10000)); __ nop(); - Handle ic(isolate->builtins()->builtin(Builtins::kLoadIC_Initialize)); + Handle ic(LoadIC::initialize_stub(isolate, NOT_CONTEXTUAL)); __ call(ic, RelocInfo::CODE_TARGET); __ nop(); __ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY); diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index 79e9ba5687..8f664d5ad1 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -2839,8 +2839,7 @@ TEST(IncrementalMarkingClearsTypeFeedbackCells) { static Code* FindFirstIC(Code* code, Code::Kind kind) { int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | - RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) | - RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT); + RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); for (RelocIterator it(code, mask); !it.done(); it.next()) { RelocInfo* info = it.rinfo(); Code* target = Code::GetCodeFromTargetAddress(info->target_address()); @@ -2852,7 +2851,7 @@ static Code* FindFirstIC(Code* code, Code::Kind kind) { } -TEST(IncrementalMarkingPreservesMonomorhpicIC) { +TEST(IncrementalMarkingPreservesMonomorphicIC) { if (i::FLAG_always_opt) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -2877,7 +2876,7 @@ TEST(IncrementalMarkingPreservesMonomorhpicIC) { } -TEST(IncrementalMarkingClearsMonomorhpicIC) { +TEST(IncrementalMarkingClearsMonomorphicIC) { if (i::FLAG_always_opt) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -2911,7 +2910,7 @@ TEST(IncrementalMarkingClearsMonomorhpicIC) { } -TEST(IncrementalMarkingClearsPolymorhpicIC) { +TEST(IncrementalMarkingClearsPolymorphicIC) { if (i::FLAG_always_opt) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -3060,7 +3059,7 @@ TEST(Regression144230) { HandleScope inner_scope(isolate); AlwaysAllocateScope always_allocate; SimulateFullSpace(heap->code_space()); - isolate->stub_cache()->ComputeCallInitialize(9, RelocInfo::CODE_TARGET); + isolate->stub_cache()->ComputeCallInitialize(9, NOT_CONTEXTUAL); } // Second compile a CallIC and execute it once so that it gets patched to diff --git a/test/mjsunit/context-calls-maintained.js b/test/mjsunit/context-calls-maintained.js new file mode 100644 index 0000000000..95bf55240b --- /dev/null +++ b/test/mjsunit/context-calls-maintained.js @@ -0,0 +1,116 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --expose-gc --allow-natives-syntax + +function clear_all_ics() { + %NotifyContextDisposed(); + gc(); + gc(); + gc(); +} + + +// Test: verify that a monomorphic call retains the structural knowledge +// of a global call, correctly throwing either ReferenceError or +// TypeError on undefined depending on how the call is made. +(function() { + foo = function(arg) { return arg + 1; } + + function f() { foo(1); } + + // Drive to monomorphic + f(); f(); f(); + + delete foo; + assertThrows(function() { f(); }, ReferenceError); + foo = function(arg) { return arg * 2; } + assertDoesNotThrow(function() { f(); }); + f(); f(); f(); + delete foo; + assertThrows(function() { f(); }, ReferenceError); + clear_all_ics(); + foo = function(arg) { return arg * 3; } + f(); + %OptimizeFunctionOnNextCall(f); + f(); + delete foo; + assertThrows(function() { f(); }, ReferenceError); + + foo = function(arg) { return arg * 3; } + function g() { this.foo(1); } + g(); g(); g(); + delete foo; + assertThrows(function() { g(); }, TypeError); + foo = function(arg) { return arg * 3; } + g(); + %OptimizeFunctionOnNextCall(g); + g(); + delete foo; + assertThrows(function() { g(); }, TypeError); +})(); + + +// Test: verify that a load with IC does the right thing. +(function() { + var foo = function() { return a; } + a = 3; + foo(); foo(); foo(); + delete a; + assertThrows(function() { foo(); }, ReferenceError); + a = "hi"; + foo(); + clear_all_ics(); + foo(); + %OptimizeFunctionOnNextCall(foo); + foo(); + delete a; + assertThrows(function() { foo(); }, ReferenceError); + foo = function() { return this.a; } + assertDoesNotThrow(function() { foo(); }); +})(); + + +// Test: verify that a store with IC does the right thing. +// If store is contextual and strict mode is set, throw a ReferenceError +// if the variable isn't found. +(function() { + var foo = function() { a = 3; } + var bar = function() { "use strict"; a = 3; } + foo(); foo(); foo(); + delete a; + assertThrows(function() { bar(); }, ReferenceError); + a = 6; + foo(); foo(); foo(); + bar(); bar(); + clear_all_ics(); + bar(); + %OptimizeFunctionOnNextCall(bar); + bar(); + delete a; + assertThrows(function() { bar(); }, ReferenceError); +})();