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
This commit is contained in:
parent
b9cc56dd34
commit
52575220d4
@ -3015,7 +3015,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
}
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code();
|
||||
Handle<Code> 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<LLoadNamedGeneric>(instr);
|
||||
}
|
||||
Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code();
|
||||
Handle<Code> 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<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
||||
}
|
||||
|
||||
|
@ -3391,7 +3391,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
}
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code();
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3645,7 +3645,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
Handle<Code> 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<LLoadNamedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
|
||||
DCHECK(ToRegister(instr->result()).is(x0));
|
||||
|
@ -19,13 +19,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),
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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> 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> 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> 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<String> 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> 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<Node*>(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> 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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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<int> 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<LoadPropertyParameters>(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<LoadNamedParameters>(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>& name,
|
||||
const VectorSlotPair& feedback,
|
||||
ContextualMode contextual_mode) {
|
||||
LoadNamedParameters parameters(name, contextual_mode);
|
||||
LoadNamedParameters parameters(name, feedback, contextual_mode);
|
||||
return new (zone()) Operator1<LoadNamedParameters>(
|
||||
IrOpcode::kJSLoadNamed, Operator::kNoProperties, 1, 1, "JSLoadNamed",
|
||||
parameters);
|
||||
}
|
||||
|
||||
|
||||
const Operator* JSOperatorBuilder::LoadProperty(
|
||||
const VectorSlotPair& feedback) {
|
||||
LoadPropertyParameters parameters(feedback);
|
||||
return new (zone()) Operator1<LoadPropertyParameters>(
|
||||
IrOpcode::kJSLoadProperty, Operator::kNoProperties, 2, 1,
|
||||
"JSLoadProperty", parameters);
|
||||
}
|
||||
|
||||
|
||||
const Operator* JSOperatorBuilder::StoreProperty(StrictMode strict_mode) {
|
||||
return new (zone())
|
||||
Operator1<StrictMode>(IrOpcode::kJSStoreProperty, Operator::kNoProperties,
|
||||
|
@ -96,19 +96,40 @@ std::ostream& operator<<(std::ostream&, ContextAccess const&);
|
||||
ContextAccess const& ContextAccessOf(Operator const*);
|
||||
|
||||
|
||||
class VectorSlotPair {
|
||||
public:
|
||||
VectorSlotPair(Handle<TypeFeedbackVector> vector, int slot)
|
||||
: vector_(vector), slot_(slot) {}
|
||||
|
||||
Handle<TypeFeedbackVector> vector() const { return vector_; }
|
||||
int slot() const { return slot_; }
|
||||
|
||||
private:
|
||||
const Handle<TypeFeedbackVector> 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>& name, ContextualMode contextual_mode)
|
||||
: name_(name), contextual_mode_(contextual_mode) {}
|
||||
LoadNamedParameters(const Unique<Name>& name, const VectorSlotPair& feedback,
|
||||
ContextualMode contextual_mode)
|
||||
: name_(name), contextual_mode_(contextual_mode), feedback_(feedback) {}
|
||||
|
||||
const Unique<Name>& name() const { return name_; }
|
||||
ContextualMode contextual_mode() const { return contextual_mode_; }
|
||||
|
||||
const VectorSlotPair& feedback() const { return feedback_; }
|
||||
|
||||
private:
|
||||
const Unique<Name> 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>& name,
|
||||
const VectorSlotPair& feedback,
|
||||
ContextualMode contextual_mode = NOT_CONTEXTUAL);
|
||||
|
||||
const Operator* StoreProperty(StrictMode strict_mode);
|
||||
|
@ -2849,7 +2849,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
}
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code();
|
||||
Handle<Code> 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<LLoadNamedGeneric>(instr);
|
||||
}
|
||||
Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3211,7 +3212,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
26
src/ic/ic.cc
26
src/ic/ic.cc
@ -832,6 +832,32 @@ Handle<Code> LoadIC::initialize_stub(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> 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<Code> KeyedLoadIC::initialize_stub(Isolate* isolate) {
|
||||
if (FLAG_vector_ics) {
|
||||
return KeyedLoadICTrampolineStub(isolate).GetCode();
|
||||
}
|
||||
|
||||
return isolate->builtins()->KeyedLoadIC_Initialize();
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code(Isolate* isolate) {
|
||||
if (FLAG_vector_ics) {
|
||||
return VectorKeyedLoadStub(isolate).GetCode();
|
||||
}
|
||||
return initialize_stub(isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadIC::megamorphic_stub() {
|
||||
if (kind() == Code::LOAD_IC) {
|
||||
MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state()));
|
||||
|
@ -353,6 +353,8 @@ class LoadIC : public IC {
|
||||
|
||||
static Handle<Code> initialize_stub(Isolate* isolate,
|
||||
ExtraICState extra_state);
|
||||
static Handle<Code> initialize_stub_in_optimized_code(
|
||||
Isolate* isolate, ExtraICState extra_state);
|
||||
|
||||
MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
|
||||
Handle<Name> name);
|
||||
@ -420,6 +422,8 @@ class KeyedLoadIC : public LoadIC {
|
||||
static const int kSlowCaseBitFieldMask =
|
||||
(1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
|
||||
|
||||
static Handle<Code> initialize_stub(Isolate* isolate);
|
||||
static Handle<Code> initialize_stub_in_optimized_code(Isolate* isolate);
|
||||
static Handle<Code> generic_stub(Isolate* isolate);
|
||||
static Handle<Code> pre_monomorphic_stub(Isolate* isolate);
|
||||
|
||||
|
@ -2908,7 +2908,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
}
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code();
|
||||
Handle<Code> 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<LLoadNamedGeneric>(instr);
|
||||
}
|
||||
Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3343,7 +3344,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
@ -2871,7 +2871,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
}
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code();
|
||||
Handle<Code> 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<LLoadNamedGeneric>(instr);
|
||||
}
|
||||
Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3295,7 +3296,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -78,6 +78,7 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) {
|
||||
uint8_t backing_store[kLength * 8];
|
||||
Handle<JSArrayBuffer> buffer =
|
||||
NewArrayBuffer(backing_store, arraysize(backing_store));
|
||||
VectorSlotPair feedback(Handle<TypeFeedbackVector>::null(), 0);
|
||||
TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
|
||||
Handle<JSTypedArray> 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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user