From 37ebdc7da50ce0542f1bccb50250ff7c218a50cd Mon Sep 17 00:00:00 2001 From: "mvstanton@chromium.org" Date: Wed, 23 Jul 2014 07:48:19 +0000 Subject: [PATCH] X87: Introduce FLAG_vector_ics. port r22500. original commit message: Introduce FLAG_vector_ics. When FLAG_vector_ics is true, then AST nodes that use Load and KeyedLoad ICs will allocate a type vector slot to store feedback information. Full codegen will emit a load of the slot into a register if the flag is on. Support is incomplete, right now the IC doesn't know how to use the feedback slot. BUG= R=mvstanton@chromium.org Review URL: https://codereview.chromium.org/405343002 Patch from Chunyang Dai . git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22542 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/x87/builtins-x87.cc | 3 ++ src/x87/full-codegen-x87.cc | 64 +++++++++++++++++++++++++++++++++++------- src/x87/ic-x87.cc | 12 ++++++++ src/x87/lithium-codegen-x87.cc | 28 ++++++++++++++++++ src/x87/lithium-x87.cc | 21 +++++++++++--- src/x87/lithium-x87.h | 21 ++++++++++---- 6 files changed, 129 insertions(+), 20 deletions(-) diff --git a/src/x87/builtins-x87.cc b/src/x87/builtins-x87.cc index a795a18..332f0a8 100644 --- a/src/x87/builtins-x87.cc +++ b/src/x87/builtins-x87.cc @@ -1003,6 +1003,9 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { __ mov(receiver, Operand(ebp, kArgumentsOffset)); // load arguments // Use inline caching to speed up access to arguments. + if (FLAG_vector_ics) { + __ mov(LoadIC::SlotRegister(), Immediate(Smi::FromInt(0))); + } Handle ic = masm->isolate()->builtins()->KeyedLoadIC_Initialize(); __ call(ic, RelocInfo::CODE_TARGET); // It is important that we do not have a test instruction after the diff --git a/src/x87/full-codegen-x87.cc b/src/x87/full-codegen-x87.cc index 8801665..fe67a99 100644 --- a/src/x87/full-codegen-x87.cc +++ b/src/x87/full-codegen-x87.cc @@ -1284,7 +1284,7 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { } -void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, +void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, TypeofState typeof_state, Label* slow) { Register context = esi; @@ -1335,7 +1335,12 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, // All extension objects were empty and it is safe to use a global // load IC call. __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand()); - __ mov(LoadIC::NameRegister(), var->name()); + __ mov(LoadIC::NameRegister(), proxy->var()->name()); + if (FLAG_vector_ics) { + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(proxy->VariableFeedbackSlot()))); + } + ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL : CONTEXTUAL; @@ -1374,7 +1379,7 @@ MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, } -void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, +void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, TypeofState typeof_state, Label* slow, Label* done) { @@ -1383,8 +1388,9 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, // introducing variables. In those cases, we do not want to // perform a runtime call for all variables in the scope // containing the eval. + Variable* var = proxy->var(); if (var->mode() == DYNAMIC_GLOBAL) { - EmitLoadGlobalCheckExtensions(var, typeof_state, slow); + EmitLoadGlobalCheckExtensions(proxy, typeof_state, slow); __ jmp(done); } else if (var->mode() == DYNAMIC_LOCAL) { Variable* local = var->local_if_not_shadowed(); @@ -1417,6 +1423,10 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { Comment cmnt(masm_, "[ Global variable"); __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand()); __ mov(LoadIC::NameRegister(), var->name()); + if (FLAG_vector_ics) { + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(proxy->VariableFeedbackSlot()))); + } CallLoadIC(CONTEXTUAL); context()->Plug(eax); break; @@ -1492,7 +1502,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { Label done, slow; // Generate code for loading from variables potentially shadowed // by eval-introduced variables. - EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); + EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); __ bind(&slow); __ push(esi); // Context. __ push(Immediate(var->name())); @@ -2016,6 +2026,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) { // result = receiver[f](arg); __ bind(&l_call); __ mov(load_receiver, Operand(esp, kPointerSize)); + if (FLAG_vector_ics) { + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(expr->KeyedLoadFeedbackSlot()))); + } Handle ic = isolate()->builtins()->KeyedLoadIC_Initialize(); CallIC(ic, TypeFeedbackId::None()); __ mov(edi, eax); @@ -2032,6 +2046,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ Move(load_receiver, eax); // result __ mov(load_name, isolate()->factory()->done_string()); // "done" + if (FLAG_vector_ics) { + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(expr->DoneFeedbackSlot()))); + } CallLoadIC(NOT_CONTEXTUAL); // result.done in eax Handle bool_ic = ToBooleanStub::GetUninitialized(isolate()); CallIC(bool_ic); @@ -2042,6 +2060,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ pop(load_receiver); // result __ mov(load_name, isolate()->factory()->value_string()); // "value" + if (FLAG_vector_ics) { + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(expr->ValueFeedbackSlot()))); + } CallLoadIC(NOT_CONTEXTUAL); // result.value in eax context()->DropAndPlug(2, eax); // drop iter and g break; @@ -2202,14 +2224,26 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { Literal* key = prop->key()->AsLiteral(); ASSERT(!key->value()->IsSmi()); __ mov(LoadIC::NameRegister(), Immediate(key->value())); - CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); + if (FLAG_vector_ics) { + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(prop->PropertyFeedbackSlot()))); + CallLoadIC(NOT_CONTEXTUAL); + } else { + CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); + } } void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); Handle ic = isolate()->builtins()->KeyedLoadIC_Initialize(); - CallIC(ic, prop->PropertyFeedbackId()); + if (FLAG_vector_ics) { + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(prop->PropertyFeedbackSlot()))); + CallIC(ic); + } else { + CallIC(ic, prop->PropertyFeedbackId()); + } } @@ -2674,7 +2708,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { { PreservePositionScope scope(masm()->positions_recorder()); // Generate code for loading from variables potentially shadowed by // eval-introduced variables. - EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); + EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); } __ bind(&slow); // Call the runtime to find the function to call (returned in eax) and @@ -4015,7 +4049,13 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { // Load the function from the receiver. __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); __ mov(LoadIC::NameRegister(), Immediate(expr->name())); - CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); + if (FLAG_vector_ics) { + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(expr->CallRuntimeFeedbackSlot()))); + CallLoadIC(NOT_CONTEXTUAL); + } else { + CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); + } // Push the target function under the receiver. __ push(Operand(esp, 0)); @@ -4363,6 +4403,10 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { Comment cmnt(masm_, "[ Global variable"); __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand()); __ mov(LoadIC::NameRegister(), Immediate(proxy->name())); + if (FLAG_vector_ics) { + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(proxy->VariableFeedbackSlot()))); + } // Use a regular load, not a contextual load, to avoid a reference // error. CallLoadIC(NOT_CONTEXTUAL); @@ -4374,7 +4418,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { // Generate code for loading from variables potentially shadowed // by eval-introduced variables. - EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); + EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done); __ bind(&slow); __ push(esi); diff --git a/src/x87/ic-x87.cc b/src/x87/ic-x87.cc index 5db2598..c577efb 100644 --- a/src/x87/ic-x87.cc +++ b/src/x87/ic-x87.cc @@ -974,6 +974,18 @@ const Register LoadIC::ReceiverRegister() { return edx; } const Register LoadIC::NameRegister() { return ecx; } +const Register LoadIC::SlotRegister() { + ASSERT(FLAG_vector_ics); + return eax; +} + + +const Register LoadIC::VectorRegister() { + ASSERT(FLAG_vector_ics); + return ebx; +} + + const Register StoreIC::ReceiverRegister() { return edx; } const Register StoreIC::NameRegister() { return ecx; } const Register StoreIC::ValueRegister() { return eax; } diff --git a/src/x87/lithium-codegen-x87.cc b/src/x87/lithium-codegen-x87.cc index e78df97..f2074fd 100644 --- a/src/x87/lithium-codegen-x87.cc +++ b/src/x87/lithium-codegen-x87.cc @@ -2971,6 +2971,15 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { ASSERT(ToRegister(instr->result()).is(eax)); __ mov(LoadIC::NameRegister(), instr->name()); + if (FLAG_vector_ics) { + Register vector = ToRegister(instr->temp_vector()); + ASSERT(vector.is(LoadIC::VectorRegister())); + __ mov(vector, instr->hydrogen()->feedback_vector()); + // No need to allocate this register. + ASSERT(LoadIC::SlotRegister().is(eax)); + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(instr->hydrogen()->slot()))); + } ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; Handle ic = LoadIC::initialize_stub(isolate(), mode); CallCode(ic, RelocInfo::CODE_TARGET, instr); @@ -3103,6 +3112,15 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { ASSERT(ToRegister(instr->result()).is(eax)); __ mov(LoadIC::NameRegister(), instr->name()); + if (FLAG_vector_ics) { + Register vector = ToRegister(instr->temp_vector()); + ASSERT(vector.is(LoadIC::VectorRegister())); + __ mov(vector, instr->hydrogen()->feedback_vector()); + // No need to allocate this register. + ASSERT(LoadIC::SlotRegister().is(eax)); + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(instr->hydrogen()->slot()))); + } Handle ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3340,6 +3358,16 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); ASSERT(ToRegister(instr->key()).is(LoadIC::NameRegister())); + if (FLAG_vector_ics) { + Register vector = ToRegister(instr->temp_vector()); + ASSERT(vector.is(LoadIC::VectorRegister())); + __ mov(vector, instr->hydrogen()->feedback_vector()); + // No need to allocate this register. + ASSERT(LoadIC::SlotRegister().is(eax)); + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(instr->hydrogen()->slot()))); + } + Handle ic = isolate()->builtins()->KeyedLoadIC_Initialize(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } diff --git a/src/x87/lithium-x87.cc b/src/x87/lithium-x87.cc index 533d36b..290f4f2 100644 --- a/src/x87/lithium-x87.cc +++ b/src/x87/lithium-x87.cc @@ -2073,8 +2073,13 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { LOperand* context = UseFixed(instr->context(), esi); LOperand* global_object = UseFixed(instr->global_object(), LoadIC::ReceiverRegister()); + LOperand* vector = NULL; + if (FLAG_vector_ics) { + vector = FixedTemp(LoadIC::VectorRegister()); + } + LLoadGlobalGeneric* result = - new(zone()) LLoadGlobalGeneric(context, global_object); + new(zone()) LLoadGlobalGeneric(context, global_object, vector); return MarkAsCall(DefineFixed(result, eax), instr); } @@ -2128,7 +2133,12 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { LOperand* context = UseFixed(instr->context(), esi); LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister()); - LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(context, object); + LOperand* vector = NULL; + if (FLAG_vector_ics) { + vector = FixedTemp(LoadIC::VectorRegister()); + } + LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric( + context, object, vector); return MarkAsCall(DefineFixed(result, eax), instr); } @@ -2187,9 +2197,12 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { LOperand* context = UseFixed(instr->context(), esi); LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister()); LOperand* key = UseFixed(instr->key(), LoadIC::NameRegister()); - + LOperand* vector = NULL; + if (FLAG_vector_ics) { + vector = FixedTemp(LoadIC::VectorRegister()); + } LLoadKeyedGeneric* result = - new(zone()) LLoadKeyedGeneric(context, object, key); + new(zone()) LLoadKeyedGeneric(context, object, key, vector); return MarkAsCall(DefineFixed(result, eax), instr); } diff --git a/src/x87/lithium-x87.h b/src/x87/lithium-x87.h index 245af49..ea76738 100644 --- a/src/x87/lithium-x87.h +++ b/src/x87/lithium-x87.h @@ -1593,15 +1593,17 @@ class LLoadNamedField V8_FINAL : public LTemplateInstruction<1, 1, 0> { }; -class LLoadNamedGeneric V8_FINAL : public LTemplateInstruction<1, 2, 0> { +class LLoadNamedGeneric V8_FINAL : public LTemplateInstruction<1, 2, 1> { public: - LLoadNamedGeneric(LOperand* context, LOperand* object) { + LLoadNamedGeneric(LOperand* context, LOperand* object, LOperand* vector) { inputs_[0] = context; inputs_[1] = object; + temps_[0] = vector; } LOperand* context() { return inputs_[0]; } LOperand* object() { return inputs_[1]; } + LOperand* temp_vector() { return temps_[0]; } DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic") DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric) @@ -1682,19 +1684,23 @@ inline static bool ExternalArrayOpRequiresTemp( } -class LLoadKeyedGeneric V8_FINAL : public LTemplateInstruction<1, 3, 0> { +class LLoadKeyedGeneric V8_FINAL : public LTemplateInstruction<1, 3, 1> { public: - LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key) { + LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key, + LOperand* vector) { inputs_[0] = context; inputs_[1] = obj; inputs_[2] = key; + temps_[0] = vector; } LOperand* context() { return inputs_[0]; } LOperand* object() { return inputs_[1]; } LOperand* key() { return inputs_[2]; } + LOperand* temp_vector() { return temps_[0]; } DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic") + DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric) }; @@ -1705,15 +1711,18 @@ class LLoadGlobalCell V8_FINAL : public LTemplateInstruction<1, 0, 0> { }; -class LLoadGlobalGeneric V8_FINAL : public LTemplateInstruction<1, 2, 0> { +class LLoadGlobalGeneric V8_FINAL : public LTemplateInstruction<1, 2, 1> { public: - LLoadGlobalGeneric(LOperand* context, LOperand* global_object) { + LLoadGlobalGeneric(LOperand* context, LOperand* global_object, + LOperand* vector) { inputs_[0] = context; inputs_[1] = global_object; + temps_[0] = vector; } LOperand* context() { return inputs_[0]; } LOperand* global_object() { return inputs_[1]; } + LOperand* temp_vector() { return temps_[0]; } DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic") DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric) -- 2.7.4