From 52575220d4f87e47aacc2b9507db18f5007e4002 Mon Sep 17 00:00:00 2001 From: "mvstanton@chromium.org" Date: Fri, 10 Oct 2014 09:49:43 +0000 Subject: [PATCH] Teach TurboFan to call vector-based ICs. Additional static information needs to be passed to Load and KeyedLoad calls if --vector-ics is turned on. R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/633423002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24519 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-codegen-arm.cc | 7 ++- src/arm64/lithium-codegen-arm64.cc | 7 ++- src/code-factory.cc | 24 +++++++- src/code-factory.h | 2 + src/compiler/ast-graph-builder.cc | 68 +++++++++++++++------- src/compiler/ast-graph-builder.h | 6 +- src/compiler/js-generic-lowering.cc | 14 ++++- src/compiler/js-operator.cc | 59 +++++++++++++++++-- src/compiler/js-operator.h | 51 +++++++++++++++- src/ia32/lithium-codegen-ia32.cc | 7 ++- src/ic/ic.cc | 26 +++++++++ src/ic/ic.h | 4 ++ src/mips/lithium-codegen-mips.cc | 7 ++- src/x64/lithium-codegen-x64.cc | 7 ++- test/unittests/compiler/js-operator-unittest.cc | 1 - .../compiler/js-typed-lowering-unittest.cc | 5 +- 16 files changed, 246 insertions(+), 49 deletions(-) diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 1474096..96561ed 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -3015,7 +3015,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { EmitVectorLoadICRegisters(instr); } ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; - Handle ic = CodeFactory::LoadIC(isolate(), mode).code(); + Handle ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3137,7 +3137,8 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { if (FLAG_vector_ics) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code(); + Handle ic = + CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } @@ -3428,7 +3429,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::KeyedLoadIC(isolate()).code(); + Handle ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc index b9b67d9..346142b 100644 --- a/src/arm64/lithium-codegen-arm64.cc +++ b/src/arm64/lithium-codegen-arm64.cc @@ -3391,7 +3391,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { EmitVectorLoadICRegisters(instr); } ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; - Handle ic = CodeFactory::LoadIC(isolate(), mode).code(); + Handle ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3645,7 +3645,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::KeyedLoadIC(isolate()).code(); + Handle ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); DCHECK(ToRegister(instr->result()).Is(x0)); @@ -3701,7 +3701,8 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code(); + Handle ic = + CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); DCHECK(ToRegister(instr->result()).is(x0)); diff --git a/src/code-factory.cc b/src/code-factory.cc index c969c8f..ae94fd5 100644 --- a/src/code-factory.cc +++ b/src/code-factory.cc @@ -20,13 +20,35 @@ Callable CodeFactory::LoadIC(Isolate* isolate, ContextualMode mode) { // static +Callable CodeFactory::LoadICInOptimizedCode(Isolate* isolate, + ContextualMode mode) { + if (FLAG_vector_ics) { + return Callable(LoadIC::initialize_stub_in_optimized_code( + isolate, LoadICState(mode).GetExtraICState()), + VectorLoadICDescriptor(isolate)); + } + return CodeFactory::LoadIC(isolate, mode); +} + + +// static Callable CodeFactory::KeyedLoadIC(Isolate* isolate) { - return Callable(isolate->builtins()->KeyedLoadIC_Initialize(), + return Callable(KeyedLoadIC::initialize_stub(isolate), LoadDescriptor(isolate)); } // static +Callable CodeFactory::KeyedLoadICInOptimizedCode(Isolate* isolate) { + if (FLAG_vector_ics) { + return Callable(KeyedLoadIC::initialize_stub_in_optimized_code(isolate), + VectorLoadICDescriptor(isolate)); + } + return CodeFactory::KeyedLoadIC(isolate); +} + + +// static Callable CodeFactory::StoreIC(Isolate* isolate, StrictMode mode) { return Callable(StoreIC::initialize_stub(isolate, mode), StoreDescriptor(isolate)); diff --git a/src/code-factory.h b/src/code-factory.h index 3add384..2426cf0 100644 --- a/src/code-factory.h +++ b/src/code-factory.h @@ -33,7 +33,9 @@ class CodeFactory FINAL { public: // Initial states for ICs. static Callable LoadIC(Isolate* isolate, ContextualMode mode); + static Callable LoadICInOptimizedCode(Isolate* isolate, ContextualMode mode); static Callable KeyedLoadIC(Isolate* isolate); + static Callable KeyedLoadICInOptimizedCode(Isolate* isolate); static Callable StoreIC(Isolate* isolate, StrictMode mode); static Callable KeyedStoreIC(Isolate* isolate, StrictMode mode); diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index fa3e88b..cbc4e51 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -837,7 +837,8 @@ void AstGraphBuilder::VisitConditional(Conditional* expr) { void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) { - Node* value = BuildVariableLoad(expr->var(), expr->id()); + VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot()); + Node* value = BuildVariableLoad(expr->var(), expr->id(), pair); ast_context()->ProduceValue(value); } @@ -1091,15 +1092,19 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { Node* old_value = NULL; switch (assign_type) { case VARIABLE: { - Variable* variable = expr->target()->AsVariableProxy()->var(); - old_value = BuildVariableLoad(variable, expr->target()->id()); + VariableProxy* proxy = expr->target()->AsVariableProxy(); + VectorSlotPair pair = + CreateVectorSlotPair(proxy->VariableFeedbackSlot()); + old_value = BuildVariableLoad(proxy->var(), expr->target()->id(), pair); break; } case NAMED_PROPERTY: { Node* object = environment()->Top(); Unique name = MakeUnique(property->key()->AsLiteral()->AsPropertyName()); - old_value = NewNode(javascript()->LoadNamed(name), object); + VectorSlotPair pair = + CreateVectorSlotPair(property->PropertyFeedbackSlot()); + old_value = NewNode(javascript()->LoadNamed(name, pair), object); PrepareFrameState(old_value, property->LoadId(), OutputFrameStateCombine::Push()); break; @@ -1107,7 +1112,9 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { case KEYED_PROPERTY: { Node* key = environment()->Top(); Node* object = environment()->Peek(1); - old_value = NewNode(javascript()->LoadProperty(), object, key); + VectorSlotPair pair = + CreateVectorSlotPair(property->PropertyFeedbackSlot()); + old_value = NewNode(javascript()->LoadProperty(pair), object, key); PrepareFrameState(old_value, property->LoadId(), OutputFrameStateCombine::Push()); break; @@ -1179,17 +1186,18 @@ void AstGraphBuilder::VisitThrow(Throw* expr) { void AstGraphBuilder::VisitProperty(Property* expr) { Node* value; + VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot()); if (expr->key()->IsPropertyName()) { VisitForValue(expr->obj()); Node* object = environment()->Pop(); Unique name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); - value = NewNode(javascript()->LoadNamed(name), object); + value = NewNode(javascript()->LoadNamed(name, pair), object); } else { VisitForValue(expr->obj()); VisitForValue(expr->key()); Node* key = environment()->Pop(); Node* object = environment()->Pop(); - value = NewNode(javascript()->LoadProperty(), object, key); + value = NewNode(javascript()->LoadProperty(pair), object, key); } PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); ast_context()->ProduceValue(value); @@ -1208,8 +1216,10 @@ void AstGraphBuilder::VisitCall(Call* expr) { bool possibly_eval = false; switch (call_type) { case Call::GLOBAL_CALL: { - Variable* variable = callee->AsVariableProxy()->var(); - callee_value = BuildVariableLoad(variable, expr->expression()->id()); + VariableProxy* proxy = callee->AsVariableProxy(); + VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); + callee_value = + BuildVariableLoad(proxy->var(), expr->expression()->id(), pair); receiver_value = jsgraph()->UndefinedConstant(); break; } @@ -1231,14 +1241,16 @@ void AstGraphBuilder::VisitCall(Call* expr) { Property* property = callee->AsProperty(); VisitForValue(property->obj()); Node* object = environment()->Top(); + VectorSlotPair pair = + CreateVectorSlotPair(property->PropertyFeedbackSlot()); if (property->key()->IsPropertyName()) { Unique name = MakeUnique(property->key()->AsLiteral()->AsPropertyName()); - callee_value = NewNode(javascript()->LoadNamed(name), object); + callee_value = NewNode(javascript()->LoadNamed(name, pair), object); } else { VisitForValue(property->key()); Node* key = environment()->Pop(); - callee_value = NewNode(javascript()->LoadProperty(), object, key); + callee_value = NewNode(javascript()->LoadProperty(pair), object, key); } PrepareFrameState(callee_value, property->LoadId(), OutputFrameStateCombine::Push()); @@ -1326,7 +1338,9 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) { CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; Node* receiver_value = BuildLoadBuiltinsObject(); Unique unique = MakeUnique(name); - Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value); + VectorSlotPair pair = CreateVectorSlotPair(expr->CallRuntimeFeedbackSlot()); + Node* callee_value = + NewNode(javascript()->LoadNamed(unique, pair), receiver_value); // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft // refuses to optimize functions with jsruntime calls). PrepareFrameState(callee_value, BailoutId::None(), @@ -1401,8 +1415,10 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { int stack_depth = -1; switch (assign_type) { case VARIABLE: { - Variable* variable = expr->expression()->AsVariableProxy()->var(); - old_value = BuildVariableLoad(variable, expr->expression()->id()); + VariableProxy* proxy = expr->expression()->AsVariableProxy(); + VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); + old_value = + BuildVariableLoad(proxy->var(), expr->expression()->id(), pair); stack_depth = 0; break; } @@ -1411,7 +1427,9 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { Node* object = environment()->Top(); Unique name = MakeUnique(property->key()->AsLiteral()->AsPropertyName()); - old_value = NewNode(javascript()->LoadNamed(name), object); + VectorSlotPair pair = + CreateVectorSlotPair(property->PropertyFeedbackSlot()); + old_value = NewNode(javascript()->LoadNamed(name, pair), object); PrepareFrameState(old_value, property->LoadId(), OutputFrameStateCombine::Push()); stack_depth = 1; @@ -1422,7 +1440,9 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { VisitForValue(property->key()); Node* key = environment()->Top(); Node* object = environment()->Peek(1); - old_value = NewNode(javascript()->LoadProperty(), object, key); + VectorSlotPair pair = + CreateVectorSlotPair(property->PropertyFeedbackSlot()); + old_value = NewNode(javascript()->LoadProperty(pair), object, key); PrepareFrameState(old_value, property->LoadId(), OutputFrameStateCombine::Push()); stack_depth = 2; @@ -1632,9 +1652,10 @@ void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { if (expr->expression()->IsVariableProxy()) { // Typeof does not throw a reference error on global variables, hence we // perform a non-contextual load in case the operand is a variable proxy. - Variable* variable = expr->expression()->AsVariableProxy()->var(); - operand = - BuildVariableLoad(variable, expr->expression()->id(), NOT_CONTEXTUAL); + VariableProxy* proxy = expr->expression()->AsVariableProxy(); + VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); + operand = BuildVariableLoad(proxy->var(), expr->expression()->id(), pair, + NOT_CONTEXTUAL); } else { VisitForValue(expr->expression()); operand = environment()->Pop(); @@ -1690,6 +1711,11 @@ StrictMode AstGraphBuilder::strict_mode() const { } +VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(int slot) const { + return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot); +} + + Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) { DCHECK(environment()->stack_height() >= arity); Node** all = info()->zone()->NewArray(arity); @@ -1779,6 +1805,7 @@ Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable, Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, BailoutId bailout_id, + const VectorSlotPair& feedback, ContextualMode contextual_mode) { Node* the_hole = jsgraph()->TheHoleConstant(); VariableMode mode = variable->mode(); @@ -1787,7 +1814,8 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, // Global var, const, or let variable. Node* global = BuildLoadGlobalObject(); Unique name = MakeUnique(variable->name()); - const Operator* op = javascript()->LoadNamed(name, contextual_mode); + const Operator* op = + javascript()->LoadNamed(name, feedback, contextual_mode); Node* node = NewNode(op, global); PrepareFrameState(node, bailout_id, OutputFrameStateCombine::Push()); return node; diff --git a/src/compiler/ast-graph-builder.h b/src/compiler/ast-graph-builder.h index 967b24b..3e4bb8c 100644 --- a/src/compiler/ast-graph-builder.h +++ b/src/compiler/ast-graph-builder.h @@ -82,7 +82,8 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor { BailoutId bailout_id); Node* BuildVariableDelete(Variable* var, BailoutId bailout_id, OutputFrameStateCombine state_combine); - Node* BuildVariableLoad(Variable* var, BailoutId bailout_id, + Node* BuildVariableLoad(Variable* proxy, BailoutId bailout_id, + const VectorSlotPair& feedback, ContextualMode mode = CONTEXTUAL); // Builders for accessing the function context. @@ -143,6 +144,9 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor { // Current scope during visitation. inline Scope* current_scope() const; + // Named and keyed loads require a VectorSlotPair for successful lowering. + VectorSlotPair CreateVectorSlotPair(int slot) const; + // Process arguments to a call by popping {arity} elements off the operand // stack and build a call node using the given call operator. Node* ProcessArguments(const Operator* op, int arity); diff --git a/src/compiler/js-generic-lowering.cc b/src/compiler/js-generic-lowering.cc index 5affb77..d1951e0 100644 --- a/src/compiler/js-generic-lowering.cc +++ b/src/compiler/js-generic-lowering.cc @@ -272,15 +272,25 @@ void JSGenericLowering::LowerJSToObject(Node* node) { void JSGenericLowering::LowerJSLoadProperty(Node* node) { - Callable callable = CodeFactory::KeyedLoadIC(isolate()); + const LoadPropertyParameters& p = LoadPropertyParametersOf(node->op()); + Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate()); + if (FLAG_vector_ics) { + PatchInsertInput(node, 2, jsgraph()->SmiConstant(p.feedback().slot())); + PatchInsertInput(node, 3, jsgraph()->HeapConstant(p.feedback().vector())); + } ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite); } void JSGenericLowering::LowerJSLoadNamed(Node* node) { const LoadNamedParameters& p = LoadNamedParametersOf(node->op()); - Callable callable = CodeFactory::LoadIC(isolate(), p.contextual_mode()); + Callable callable = + CodeFactory::LoadICInOptimizedCode(isolate(), p.contextual_mode()); PatchInsertInput(node, 1, jsgraph()->HeapConstant(p.name())); + if (FLAG_vector_ics) { + PatchInsertInput(node, 2, jsgraph()->SmiConstant(p.feedback().slot())); + PatchInsertInput(node, 3, jsgraph()->HeapConstant(p.feedback().vector())); + } ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite); } diff --git a/src/compiler/js-operator.cc b/src/compiler/js-operator.cc index e0ce3de..cf7d65e 100644 --- a/src/compiler/js-operator.cc +++ b/src/compiler/js-operator.cc @@ -108,10 +108,23 @@ ContextAccess const& ContextAccessOf(Operator const* op) { } +bool operator==(VectorSlotPair const& lhs, VectorSlotPair const& rhs) { + return lhs.slot() == rhs.slot() && lhs.vector().is_identical_to(rhs.vector()); +} + + +size_t hash_value(VectorSlotPair const& p) { + // TODO(mvstanton): include the vector in the hash. + base::hash h; + return h(p.slot()); +} + + bool operator==(LoadNamedParameters const& lhs, LoadNamedParameters const& rhs) { return lhs.name() == rhs.name() && - lhs.contextual_mode() == rhs.contextual_mode(); + lhs.contextual_mode() == rhs.contextual_mode() && + lhs.feedback() == rhs.feedback(); } @@ -122,7 +135,7 @@ bool operator!=(LoadNamedParameters const& lhs, size_t hash_value(LoadNamedParameters const& p) { - return base::hash_combine(p.name(), p.contextual_mode()); + return base::hash_combine(p.name(), p.contextual_mode(), p.feedback()); } @@ -131,6 +144,35 @@ std::ostream& operator<<(std::ostream& os, LoadNamedParameters const& p) { } +std::ostream& operator<<(std::ostream& os, LoadPropertyParameters const& p) { + // Nothing special to print. + return os; +} + + +bool operator==(LoadPropertyParameters const& lhs, + LoadPropertyParameters const& rhs) { + return lhs.feedback() == rhs.feedback(); +} + + +bool operator!=(LoadPropertyParameters const& lhs, + LoadPropertyParameters const& rhs) { + return !(lhs == rhs); +} + + +const LoadPropertyParameters& LoadPropertyParametersOf(const Operator* op) { + DCHECK_EQ(IrOpcode::kJSLoadProperty, op->opcode()); + return OpParameter(op); +} + + +size_t hash_value(LoadPropertyParameters const& p) { + return hash_value(p.feedback()); +} + + const LoadNamedParameters& LoadNamedParametersOf(const Operator* op) { DCHECK_EQ(IrOpcode::kJSLoadNamed, op->opcode()); return OpParameter(op); @@ -193,7 +235,6 @@ const StoreNamedParameters& StoreNamedParametersOf(const Operator* op) { V(ToObject, Operator::kNoProperties, 1, 1) \ V(Yield, Operator::kNoProperties, 1, 1) \ V(Create, Operator::kEliminatable, 0, 1) \ - V(LoadProperty, Operator::kNoProperties, 2, 1) \ V(HasProperty, Operator::kNoProperties, 2, 1) \ V(TypeOf, Operator::kPure, 1, 1) \ V(InstanceOf, Operator::kNoProperties, 2, 1) \ @@ -261,14 +302,24 @@ const Operator* JSOperatorBuilder::CallConstruct(int arguments) { const Operator* JSOperatorBuilder::LoadNamed(const Unique& name, + const VectorSlotPair& feedback, ContextualMode contextual_mode) { - LoadNamedParameters parameters(name, contextual_mode); + LoadNamedParameters parameters(name, feedback, contextual_mode); return new (zone()) Operator1( IrOpcode::kJSLoadNamed, Operator::kNoProperties, 1, 1, "JSLoadNamed", parameters); } +const Operator* JSOperatorBuilder::LoadProperty( + const VectorSlotPair& feedback) { + LoadPropertyParameters parameters(feedback); + return new (zone()) Operator1( + IrOpcode::kJSLoadProperty, Operator::kNoProperties, 2, 1, + "JSLoadProperty", parameters); +} + + const Operator* JSOperatorBuilder::StoreProperty(StrictMode strict_mode) { return new (zone()) Operator1(IrOpcode::kJSStoreProperty, Operator::kNoProperties, diff --git a/src/compiler/js-operator.h b/src/compiler/js-operator.h index 1d658aa..3f94ff6 100644 --- a/src/compiler/js-operator.h +++ b/src/compiler/js-operator.h @@ -96,19 +96,40 @@ std::ostream& operator<<(std::ostream&, ContextAccess const&); ContextAccess const& ContextAccessOf(Operator const*); +class VectorSlotPair { + public: + VectorSlotPair(Handle vector, int slot) + : vector_(vector), slot_(slot) {} + + Handle vector() const { return vector_; } + int slot() const { return slot_; } + + private: + const Handle vector_; + const int slot_; +}; + + +bool operator==(VectorSlotPair const& lhs, VectorSlotPair const& rhs); + + // Defines the property being loaded from an object by a named load. This is // used as a parameter by JSLoadNamed operators. class LoadNamedParameters FINAL { public: - LoadNamedParameters(const Unique& name, ContextualMode contextual_mode) - : name_(name), contextual_mode_(contextual_mode) {} + LoadNamedParameters(const Unique& name, const VectorSlotPair& feedback, + ContextualMode contextual_mode) + : name_(name), contextual_mode_(contextual_mode), feedback_(feedback) {} const Unique& name() const { return name_; } ContextualMode contextual_mode() const { return contextual_mode_; } + const VectorSlotPair& feedback() const { return feedback_; } + private: const Unique name_; const ContextualMode contextual_mode_; + const VectorSlotPair feedback_; }; bool operator==(LoadNamedParameters const&, LoadNamedParameters const&); @@ -121,6 +142,29 @@ std::ostream& operator<<(std::ostream&, LoadNamedParameters const&); const LoadNamedParameters& LoadNamedParametersOf(const Operator* op); +// Defines the property being loaded from an object. This is +// used as a parameter by JSLoadProperty operators. +class LoadPropertyParameters FINAL { + public: + explicit LoadPropertyParameters(const VectorSlotPair& feedback) + : feedback_(feedback) {} + + const VectorSlotPair& feedback() const { return feedback_; } + + private: + const VectorSlotPair feedback_; +}; + +bool operator==(LoadPropertyParameters const&, LoadPropertyParameters const&); +bool operator!=(LoadPropertyParameters const&, LoadPropertyParameters const&); + +size_t hash_value(LoadPropertyParameters const&); + +std::ostream& operator<<(std::ostream&, LoadPropertyParameters const&); + +const LoadPropertyParameters& LoadPropertyParametersOf(const Operator* op); + + // Defines the property being stored to an object by a named store. This is // used as a parameter by JSStoreNamed operators. class StoreNamedParameters FINAL { @@ -188,8 +232,9 @@ class JSOperatorBuilder FINAL { const Operator* CallConstruct(int arguments); - const Operator* LoadProperty(); + const Operator* LoadProperty(const VectorSlotPair& feedback); const Operator* LoadNamed(const Unique& name, + const VectorSlotPair& feedback, ContextualMode contextual_mode = NOT_CONTEXTUAL); const Operator* StoreProperty(StrictMode strict_mode); diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 1d7c8c1..bb656d6 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -2849,7 +2849,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { EmitVectorLoadICRegisters(instr); } ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; - Handle ic = CodeFactory::LoadIC(isolate(), mode).code(); + Handle ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -2985,7 +2985,8 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { if (FLAG_vector_ics) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code(); + Handle ic = + CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3211,7 +3212,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::KeyedLoadIC(isolate()).code(); + Handle ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } diff --git a/src/ic/ic.cc b/src/ic/ic.cc index 6b47f03..1c621fe 100644 --- a/src/ic/ic.cc +++ b/src/ic/ic.cc @@ -832,6 +832,32 @@ Handle LoadIC::initialize_stub(Isolate* isolate, } +Handle LoadIC::initialize_stub_in_optimized_code( + Isolate* isolate, ExtraICState extra_state) { + if (FLAG_vector_ics) { + return VectorLoadStub(isolate, LoadICState(extra_state)).GetCode(); + } + return initialize_stub(isolate, extra_state); +} + + +Handle KeyedLoadIC::initialize_stub(Isolate* isolate) { + if (FLAG_vector_ics) { + return KeyedLoadICTrampolineStub(isolate).GetCode(); + } + + return isolate->builtins()->KeyedLoadIC_Initialize(); +} + + +Handle KeyedLoadIC::initialize_stub_in_optimized_code(Isolate* isolate) { + if (FLAG_vector_ics) { + return VectorKeyedLoadStub(isolate).GetCode(); + } + return initialize_stub(isolate); +} + + Handle LoadIC::megamorphic_stub() { if (kind() == Code::LOAD_IC) { MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state())); diff --git a/src/ic/ic.h b/src/ic/ic.h index f96c6f0..1547937 100644 --- a/src/ic/ic.h +++ b/src/ic/ic.h @@ -353,6 +353,8 @@ class LoadIC : public IC { static Handle initialize_stub(Isolate* isolate, ExtraICState extra_state); + static Handle initialize_stub_in_optimized_code( + Isolate* isolate, ExtraICState extra_state); MUST_USE_RESULT MaybeHandle Load(Handle object, Handle name); @@ -420,6 +422,8 @@ class KeyedLoadIC : public LoadIC { static const int kSlowCaseBitFieldMask = (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor); + static Handle initialize_stub(Isolate* isolate); + static Handle initialize_stub_in_optimized_code(Isolate* isolate); static Handle generic_stub(Isolate* isolate); static Handle pre_monomorphic_stub(Isolate* isolate); diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index ef72560..168965f 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -2908,7 +2908,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { EmitVectorLoadICRegisters(instr); } ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; - Handle ic = CodeFactory::LoadIC(isolate(), mode).code(); + Handle ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3035,7 +3035,8 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { if (FLAG_vector_ics) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code(); + Handle ic = + CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3343,7 +3344,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::KeyedLoadIC(isolate()).code(); + Handle ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 1981d55..bfcb338 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -2871,7 +2871,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { EmitVectorLoadICRegisters(instr); } ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; - Handle ic = CodeFactory::LoadIC(isolate(), mode).code(); + Handle ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3013,7 +3013,8 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { if (FLAG_vector_ics) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code(); + Handle ic = + CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3295,7 +3296,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { EmitVectorLoadICRegisters(instr); } - Handle ic = CodeFactory::KeyedLoadIC(isolate()).code(); + Handle ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } diff --git a/test/unittests/compiler/js-operator-unittest.cc b/test/unittests/compiler/js-operator-unittest.cc index 061a597..8e601ba 100644 --- a/test/unittests/compiler/js-operator-unittest.cc +++ b/test/unittests/compiler/js-operator-unittest.cc @@ -69,7 +69,6 @@ const SharedOperator kSharedOperators[] = { SHARED(ToObject, Operator::kNoProperties, 1, 0, 1, 1, 1, 1), SHARED(Yield, Operator::kNoProperties, 1, 0, 1, 1, 1, 1), SHARED(Create, Operator::kEliminatable, 0, 0, 1, 0, 1, 1), - SHARED(LoadProperty, Operator::kNoProperties, 2, 1, 1, 1, 1, 1), SHARED(HasProperty, Operator::kNoProperties, 2, 0, 1, 1, 1, 1), SHARED(TypeOf, Operator::kPure, 1, 0, 0, 0, 1, 0), SHARED(InstanceOf, Operator::kNoProperties, 2, 0, 1, 1, 1, 1), diff --git a/test/unittests/compiler/js-typed-lowering-unittest.cc b/test/unittests/compiler/js-typed-lowering-unittest.cc index 3f3506f..08d2031 100644 --- a/test/unittests/compiler/js-typed-lowering-unittest.cc +++ b/test/unittests/compiler/js-typed-lowering-unittest.cc @@ -78,6 +78,7 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) { uint8_t backing_store[kLength * 8]; Handle buffer = NewArrayBuffer(backing_store, arraysize(backing_store)); + VectorSlotPair feedback(Handle::null(), 0); TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) { Handle array = factory()->NewJSTypedArray(type, buffer, kLength); @@ -87,8 +88,8 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) { Node* context = UndefinedConstant(); Node* effect = graph()->start(); Node* control = graph()->start(); - Node* node = - graph()->NewNode(javascript()->LoadProperty(), base, key, context); + Node* node = graph()->NewNode(javascript()->LoadProperty(feedback), base, + key, context); if (FLAG_turbo_deoptimization) { node->AppendInput(zone(), UndefinedConstant()); } -- 2.7.4