Commit 81736c71 authored by franzih's avatar franzih Committed by Commit bot

[runtime] Collect IC feedback in DefineDataPropertyInLiteral.

Add a feedback vector slot for computed property names in object
and class literals. Introduce new slot kind for storing
computed property names.

Change StaDataPropertyInLiteral to use the accumulator (again), so
we don't exceed Bytecodes::kMaxOperands.

We assume that most computed property names are
symbols. Therefore we should see performance
improvements, even if we deal with monomorphic ICs only.

This CL only collects feedback but does not use
it in Reduce() yet.

BUG=v8:5624

Review-Url: https://codereview.chromium.org/2587393006
Cr-Commit-Position: refs/heads/master@{#42082}
parent c4e0b159
...@@ -349,6 +349,16 @@ ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory, ...@@ -349,6 +349,16 @@ ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
} }
} }
FeedbackVectorSlot LiteralProperty::GetStoreDataPropertySlot() const {
int offset = FunctionLiteral::NeedsHomeObject(value_) ? 1 : 0;
return GetSlot(offset);
}
void LiteralProperty::SetStoreDataPropertySlot(FeedbackVectorSlot slot) {
int offset = FunctionLiteral::NeedsHomeObject(value_) ? 1 : 0;
return SetSlot(slot, offset);
}
bool LiteralProperty::NeedsSetFunctionName() const { bool LiteralProperty::NeedsSetFunctionName() const {
return is_computed_name_ && return is_computed_name_ &&
(value_->IsAnonymousFunctionDefinition() || (value_->IsAnonymousFunctionDefinition() ||
...@@ -382,6 +392,8 @@ void ClassLiteral::AssignFeedbackVectorSlots(Isolate* isolate, ...@@ -382,6 +392,8 @@ void ClassLiteral::AssignFeedbackVectorSlots(Isolate* isolate,
if (FunctionLiteral::NeedsHomeObject(value)) { if (FunctionLiteral::NeedsHomeObject(value)) {
property->SetSlot(spec->AddStoreICSlot()); property->SetSlot(spec->AddStoreICSlot());
} }
property->SetStoreDataPropertySlot(
spec->AddStoreDataPropertyInLiteralICSlot());
} }
} }
...@@ -456,6 +468,8 @@ void ObjectLiteral::AssignFeedbackVectorSlots(Isolate* isolate, ...@@ -456,6 +468,8 @@ void ObjectLiteral::AssignFeedbackVectorSlots(Isolate* isolate,
property->SetSlot(spec->AddStoreICSlot()); property->SetSlot(spec->AddStoreICSlot());
} }
} }
property->SetStoreDataPropertySlot(
spec->AddStoreDataPropertyInLiteralICSlot());
} }
} }
......
...@@ -1328,11 +1328,15 @@ class LiteralProperty : public ZoneObject { ...@@ -1328,11 +1328,15 @@ class LiteralProperty : public ZoneObject {
return slots_[offset]; return slots_[offset];
} }
FeedbackVectorSlot GetStoreDataPropertySlot() const;
void SetSlot(FeedbackVectorSlot slot, int offset = 0) { void SetSlot(FeedbackVectorSlot slot, int offset = 0) {
DCHECK_LT(offset, static_cast<int>(arraysize(slots_))); DCHECK_LT(offset, static_cast<int>(arraysize(slots_)));
slots_[offset] = slot; slots_[offset] = slot;
} }
void SetStoreDataPropertySlot(FeedbackVectorSlot slot);
bool NeedsSetFunctionName() const; bool NeedsSetFunctionName() const;
protected: protected:
......
...@@ -779,11 +779,12 @@ void BytecodeGraphBuilder::VisitStaDataPropertyInLiteral() { ...@@ -779,11 +779,12 @@ void BytecodeGraphBuilder::VisitStaDataPropertyInLiteral() {
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* name = Node* name =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
Node* value = Node* value = environment()->LookupAccumulator();
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); int flags = bytecode_iterator().GetFlagOperand(2);
int flags = bytecode_iterator().GetFlagOperand(3); VectorSlotPair feedback =
CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(3));
const Operator* op = javascript()->StoreDataPropertyInLiteral(); const Operator* op = javascript()->StoreDataPropertyInLiteral(feedback);
Node* node = NewNode(op, object, name, value, jsgraph()->Constant(flags)); Node* node = NewNode(op, object, name, value, jsgraph()->Constant(flags));
environment()->RecordAfterState(node, Environment::kAttachFrameState); environment()->RecordAfterState(node, Environment::kAttachFrameState);
} }
......
...@@ -495,11 +495,11 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function, Node* context, ...@@ -495,11 +495,11 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function, Node* context,
return return_value; return return_value;
} }
// Instantiate CallRuntime() with up to 5 arguments. // Instantiate CallRuntime() with up to 6 arguments.
#define INSTANTIATE(...) \ #define INSTANTIATE(...) \
template V8_EXPORT_PRIVATE Node* CodeAssembler::CallRuntime( \ template V8_EXPORT_PRIVATE Node* CodeAssembler::CallRuntime( \
Runtime::FunctionId, __VA_ARGS__); Runtime::FunctionId, __VA_ARGS__);
REPEAT_1_TO_6(INSTANTIATE, Node*) REPEAT_1_TO_7(INSTANTIATE, Node*)
#undef INSTANTIATE #undef INSTANTIATE
template <class... TArgs> template <class... TArgs>
......
...@@ -264,6 +264,10 @@ void JSGenericLowering::LowerJSStoreGlobal(Node* node) { ...@@ -264,6 +264,10 @@ void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
} }
void JSGenericLowering::LowerJSStoreDataPropertyInLiteral(Node* node) { void JSGenericLowering::LowerJSStoreDataPropertyInLiteral(Node* node) {
DataPropertyParameters const& p = DataPropertyParametersOf(node->op());
node->InsertInputs(zone(), 4, 2);
node->ReplaceInput(4, jsgraph()->HeapConstant(p.feedback().vector()));
node->ReplaceInput(5, jsgraph()->SmiConstant(p.feedback().index()));
ReplaceWithRuntimeCall(node, Runtime::kDefineDataPropertyInLiteral); ReplaceWithRuntimeCall(node, Runtime::kDefineDataPropertyInLiteral);
} }
......
...@@ -83,6 +83,8 @@ Reduction JSNativeContextSpecialization::Reduce(Node* node) { ...@@ -83,6 +83,8 @@ Reduction JSNativeContextSpecialization::Reduce(Node* node) {
return ReduceJSLoadProperty(node); return ReduceJSLoadProperty(node);
case IrOpcode::kJSStoreProperty: case IrOpcode::kJSStoreProperty:
return ReduceJSStoreProperty(node); return ReduceJSStoreProperty(node);
case IrOpcode::kJSStoreDataPropertyInLiteral:
return ReduceJSStoreDataPropertyInLiteral(node);
default: default:
break; break;
} }
...@@ -1252,6 +1254,12 @@ JSNativeContextSpecialization::BuildPropertyAccess( ...@@ -1252,6 +1254,12 @@ JSNativeContextSpecialization::BuildPropertyAccess(
return ValueEffectControl(value, effect, control); return ValueEffectControl(value, effect, control);
} }
Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral(
Node* node) {
// TODO(franzih): Use feedback
return NoChange();
}
namespace { namespace {
ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) { ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) {
......
...@@ -60,6 +60,7 @@ class JSNativeContextSpecialization final : public AdvancedReducer { ...@@ -60,6 +60,7 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
Reduction ReduceJSStoreNamed(Node* node); Reduction ReduceJSStoreNamed(Node* node);
Reduction ReduceJSLoadProperty(Node* node); Reduction ReduceJSLoadProperty(Node* node);
Reduction ReduceJSStoreProperty(Node* node); Reduction ReduceJSStoreProperty(Node* node);
Reduction ReduceJSStoreDataPropertyInLiteral(Node* node);
Reduction ReduceElementAccess(Node* node, Node* index, Node* value, Reduction ReduceElementAccess(Node* node, Node* index, Node* value,
MapHandleList const& receiver_maps, MapHandleList const& receiver_maps,
......
...@@ -246,6 +246,29 @@ CreateFunctionContextParameters const& CreateFunctionContextParametersOf( ...@@ -246,6 +246,29 @@ CreateFunctionContextParameters const& CreateFunctionContextParametersOf(
return OpParameter<CreateFunctionContextParameters>(op); return OpParameter<CreateFunctionContextParameters>(op);
} }
bool operator==(DataPropertyParameters const& lhs,
DataPropertyParameters const& rhs) {
return lhs.feedback() == rhs.feedback();
}
bool operator!=(DataPropertyParameters const& lhs,
DataPropertyParameters const& rhs) {
return !(lhs == rhs);
}
size_t hash_value(DataPropertyParameters const& p) {
return base::hash_combine(p.feedback());
}
std::ostream& operator<<(std::ostream& os, DataPropertyParameters const& p) {
return os;
}
DataPropertyParameters const& DataPropertyParametersOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kJSStoreDataPropertyInLiteral);
return OpParameter<DataPropertyParameters>(op);
}
bool operator==(NamedAccess const& lhs, NamedAccess const& rhs) { bool operator==(NamedAccess const& lhs, NamedAccess const& rhs) {
return lhs.name().location() == rhs.name().location() && return lhs.name().location() == rhs.name().location() &&
lhs.language_mode() == rhs.language_mode() && lhs.language_mode() == rhs.language_mode() &&
...@@ -511,8 +534,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) { ...@@ -511,8 +534,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) {
V(StoreMessage, Operator::kNoThrow, 1, 0) \ V(StoreMessage, Operator::kNoThrow, 1, 0) \
V(GeneratorRestoreContinuation, Operator::kNoThrow, 1, 1) \ V(GeneratorRestoreContinuation, Operator::kNoThrow, 1, 1) \
V(StackCheck, Operator::kNoWrite, 0, 0) \ V(StackCheck, Operator::kNoWrite, 0, 0) \
V(GetSuperConstructor, Operator::kNoWrite, 1, 1) \ V(GetSuperConstructor, Operator::kNoWrite, 1, 1)
V(StoreDataPropertyInLiteral, Operator::kNoProperties, 4, 0)
#define BINARY_OP_LIST(V) \ #define BINARY_OP_LIST(V) \
V(BitwiseOr) \ V(BitwiseOr) \
...@@ -651,6 +673,17 @@ BINARY_OP_LIST(BINARY_OP) ...@@ -651,6 +673,17 @@ BINARY_OP_LIST(BINARY_OP)
COMPARE_OP_LIST(COMPARE_OP) COMPARE_OP_LIST(COMPARE_OP)
#undef COMPARE_OP #undef COMPARE_OP
const Operator* JSOperatorBuilder::StoreDataPropertyInLiteral(
const VectorSlotPair& feedback) {
DataPropertyParameters parameters(feedback);
return new (zone()) Operator1<DataPropertyParameters>( // --
IrOpcode::kJSStoreDataPropertyInLiteral,
Operator::kNoThrow, // opcode
"JSStoreDataPropertyInLiteral", // name
4, 1, 1, 0, 1, 0, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::ToBoolean(ToBooleanHints hints) { const Operator* JSOperatorBuilder::ToBoolean(ToBooleanHints hints) {
// TODO(turbofan): Cache most important versions of this operator. // TODO(turbofan): Cache most important versions of this operator.
return new (zone()) Operator1<ToBooleanHints>( //-- return new (zone()) Operator1<ToBooleanHints>( //--
......
...@@ -268,6 +268,29 @@ std::ostream& operator<<(std::ostream& os, ...@@ -268,6 +268,29 @@ std::ostream& operator<<(std::ostream& os,
CreateFunctionContextParameters const& CreateFunctionContextParametersOf( CreateFunctionContextParameters const& CreateFunctionContextParametersOf(
Operator const*); Operator const*);
// Defines the feedback, i.e., vector and index, for storing a data property in
// an object literal. This is
// used as a parameter by the JSStoreDataPropertyInLiteral operator.
class DataPropertyParameters final {
public:
explicit DataPropertyParameters(VectorSlotPair const& feedback)
: feedback_(feedback) {}
VectorSlotPair const& feedback() const { return feedback_; }
private:
VectorSlotPair const feedback_;
};
bool operator==(DataPropertyParameters const&, DataPropertyParameters const&);
bool operator!=(DataPropertyParameters const&, DataPropertyParameters const&);
size_t hash_value(DataPropertyParameters const&);
std::ostream& operator<<(std::ostream&, DataPropertyParameters const&);
const DataPropertyParameters& DataPropertyParametersOf(const Operator* op);
// Defines the property of an object for a named access. This is // Defines the property of an object for a named access. This is
// used as a parameter by the JSLoadNamed and JSStoreNamed operators. // used as a parameter by the JSLoadNamed and JSStoreNamed operators.
class NamedAccess final { class NamedAccess final {
...@@ -542,7 +565,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final ...@@ -542,7 +565,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* StoreNamed(LanguageMode language_mode, Handle<Name> name, const Operator* StoreNamed(LanguageMode language_mode, Handle<Name> name,
VectorSlotPair const& feedback); VectorSlotPair const& feedback);
const Operator* StoreDataPropertyInLiteral(); const Operator* StoreDataPropertyInLiteral(const VectorSlotPair& feedback);
const Operator* DeleteProperty(LanguageMode language_mode); const Operator* DeleteProperty(LanguageMode language_mode);
......
...@@ -554,9 +554,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( ...@@ -554,9 +554,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral( BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
Register object, Register name, Register value, Register object, Register name, DataPropertyInLiteralFlags flags,
DataPropertyInLiteralFlags flags) { int feedback_slot) {
OutputStaDataPropertyInLiteral(object, name, value, flags); OutputStaDataPropertyInLiteral(object, name, flags, feedback_slot);
return *this; return *this;
} }
......
...@@ -125,8 +125,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final ...@@ -125,8 +125,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
// Store properties. Flag for NeedsSetFunctionName() should // Store properties. Flag for NeedsSetFunctionName() should
// be in the accumulator. // be in the accumulator.
BytecodeArrayBuilder& StoreDataPropertyInLiteral( BytecodeArrayBuilder& StoreDataPropertyInLiteral(
Register object, Register name, Register value, Register object, Register name, DataPropertyInLiteralFlags flags,
DataPropertyInLiteralFlags flags); int feedback_slot);
// Store properties. The value to be stored should be in the accumulator. // Store properties. The value to be stored should be in the accumulator.
BytecodeArrayBuilder& StoreNamedProperty(Register object, BytecodeArrayBuilder& StoreNamedProperty(Register object,
......
...@@ -1503,7 +1503,14 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr, ...@@ -1503,7 +1503,14 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
if (property->NeedsSetFunctionName()) { if (property->NeedsSetFunctionName()) {
flags |= DataPropertyInLiteralFlag::kSetFunctionName; flags |= DataPropertyInLiteralFlag::kSetFunctionName;
} }
builder()->StoreDataPropertyInLiteral(receiver, key, value, flags);
FeedbackVectorSlot slot = property->GetStoreDataPropertySlot();
DCHECK(!slot.IsInvalid());
builder()
->LoadAccumulatorWithRegister(value)
.StoreDataPropertyInLiteral(receiver, key, flags,
feedback_index(slot));
break; break;
} }
case ClassLiteral::Property::GETTER: { case ClassLiteral::Property::GETTER: {
...@@ -1745,8 +1752,13 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1745,8 +1752,13 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
data_property_flags |= DataPropertyInLiteralFlag::kSetFunctionName; data_property_flags |= DataPropertyInLiteralFlag::kSetFunctionName;
} }
builder()->StoreDataPropertyInLiteral(literal, key, value, FeedbackVectorSlot slot = property->GetStoreDataPropertySlot();
data_property_flags); DCHECK(!slot.IsInvalid());
builder()
->LoadAccumulatorWithRegister(value)
.StoreDataPropertyInLiteral(literal, key, data_property_flags,
feedback_index(slot));
break; break;
} }
case ObjectLiteral::Property::GETTER: case ObjectLiteral::Property::GETTER:
......
...@@ -98,8 +98,8 @@ namespace interpreter { ...@@ -98,8 +98,8 @@ namespace interpreter {
OperandType::kReg, OperandType::kIdx) \ OperandType::kReg, OperandType::kIdx) \
V(StaKeyedPropertyStrict, AccumulatorUse::kRead, OperandType::kReg, \ V(StaKeyedPropertyStrict, AccumulatorUse::kRead, OperandType::kReg, \
OperandType::kReg, OperandType::kIdx) \ OperandType::kReg, OperandType::kIdx) \
V(StaDataPropertyInLiteral, AccumulatorUse::kNone, OperandType::kReg, \ V(StaDataPropertyInLiteral, AccumulatorUse::kRead, OperandType::kReg, \
OperandType::kReg, OperandType::kReg, OperandType::kFlag8) \ OperandType::kReg, OperandType::kFlag8, OperandType::kIdx) \
\ \
/* Binary Operators */ \ /* Binary Operators */ \
V(Add, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx) \ V(Add, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx) \
......
...@@ -861,27 +861,26 @@ void Interpreter::DoStaKeyedPropertyStrict(InterpreterAssembler* assembler) { ...@@ -861,27 +861,26 @@ void Interpreter::DoStaKeyedPropertyStrict(InterpreterAssembler* assembler) {
DoKeyedStoreIC(ic, assembler); DoKeyedStoreIC(ic, assembler);
} }
// StaDataPropertyInLiteral <object> <name> <value> <flags> // StaDataPropertyInLiteral <object> <name> <flags>
// //
// Define a property <name> with value <value> in <object>. Property attributes // Define a property <name> with value from the accumulator in <object>.
// and whether set_function_name are stored in DataPropertyInLiteralFlags // Property attributes and whether set_function_name are stored in
// <flags>. // DataPropertyInLiteralFlags <flags>.
// //
// This definition is not observable and is used only for definitions // This definition is not observable and is used only for definitions
// in object or class literals. // in object or class literals.
void Interpreter::DoStaDataPropertyInLiteral(InterpreterAssembler* assembler) { void Interpreter::DoStaDataPropertyInLiteral(InterpreterAssembler* assembler) {
Node* object_reg_index = __ BytecodeOperandReg(0); Node* object = __ LoadRegister(__ BytecodeOperandReg(0));
Node* object = __ LoadRegister(object_reg_index); Node* name = __ LoadRegister(__ BytecodeOperandReg(1));
Node* name_reg_index = __ BytecodeOperandReg(1); Node* value = __ GetAccumulator();
Node* name = __ LoadRegister(name_reg_index); Node* flags = __ SmiFromWord32(__ BytecodeOperandFlag(2));
Node* value_reg_index = __ BytecodeOperandReg(2); Node* vector_index = __ SmiTag(__ BytecodeOperandIdx(3));
Node* value = __ LoadRegister(value_reg_index);
Node* flags = __ SmiFromWord32(__ BytecodeOperandFlag(3));
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Node* context = __ GetContext(); Node* context = __ GetContext();
__ CallRuntime(Runtime::kDefineDataPropertyInLiteral, context, object, name, __ CallRuntime(Runtime::kDefineDataPropertyInLiteral, context, object, name,
value, flags); value, flags, type_feedback_vector, vector_index);
__ Dispatch(); __ Dispatch();
} }
......
...@@ -799,6 +799,11 @@ void TypeFeedbackVector::TypeFeedbackVectorPrint(std::ostream& os) { // NOLINT ...@@ -799,6 +799,11 @@ void TypeFeedbackVector::TypeFeedbackVectorPrint(std::ostream& os) { // NOLINT
os << Code::ICState2String(nexus.StateFromFeedback()); os << Code::ICState2String(nexus.StateFromFeedback());
break; break;
} }
case FeedbackVectorSlotKind::STORE_DATA_PROPERTY_IN_LITERAL_IC: {
StoreDataPropertyInLiteralICNexus nexus(this, slot);
os << Code::ICState2String(nexus.StateFromFeedback());
break;
}
case FeedbackVectorSlotKind::GENERAL: case FeedbackVectorSlotKind::GENERAL:
break; break;
case FeedbackVectorSlotKind::INVALID: case FeedbackVectorSlotKind::INVALID:
......
...@@ -648,11 +648,27 @@ RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) { ...@@ -648,11 +648,27 @@ RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) { RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 4); DCHECK_EQ(6, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
CONVERT_SMI_ARG_CHECKED(flag, 3); CONVERT_SMI_ARG_CHECKED(flag, 3);
CONVERT_ARG_HANDLE_CHECKED(TypeFeedbackVector, vector, 4);
CONVERT_SMI_ARG_CHECKED(index, 5);
StoreDataPropertyInLiteralICNexus nexus(vector, vector->ToSlot(index));
if (nexus.ic_state() == UNINITIALIZED) {
if (name->IsUniqueName()) {
nexus.ConfigureMonomorphic(name, handle(object->map()));
} else {
nexus.ConfigureMegamorphic();
}
} else if (nexus.ic_state() == MONOMORPHIC) {
if (nexus.FindFirstMap() != object->map() ||
nexus.GetFeedbackExtra() != *name) {
nexus.ConfigureMegamorphic();
}
}
DataPropertyInLiteralFlags flags = DataPropertyInLiteralFlags flags =
static_cast<DataPropertyInLiteralFlag>(flag); static_cast<DataPropertyInLiteralFlag>(flag);
......
...@@ -409,7 +409,7 @@ namespace internal { ...@@ -409,7 +409,7 @@ namespace internal {
F(TryMigrateInstance, 1, 1) \ F(TryMigrateInstance, 1, 1) \
F(IsJSGlobalProxy, 1, 1) \ F(IsJSGlobalProxy, 1, 1) \
F(DefineAccessorPropertyUnchecked, 5, 1) \ F(DefineAccessorPropertyUnchecked, 5, 1) \
F(DefineDataPropertyInLiteral, 4, 1) \ F(DefineDataPropertyInLiteral, 6, 1) \
F(GetDataProperty, 2, 1) \ F(GetDataProperty, 2, 1) \
F(GetConstructorName, 1, 1) \ F(GetConstructorName, 1, 1) \
F(HasFastPackedElements, 1, 1) \ F(HasFastPackedElements, 1, 1) \
......
...@@ -82,7 +82,7 @@ int TypeFeedbackVector::invocation_count() const { ...@@ -82,7 +82,7 @@ int TypeFeedbackVector::invocation_count() const {
// Conversion from an integer index to either a slot or an ic slot. // Conversion from an integer index to either a slot or an ic slot.
// static // static
FeedbackVectorSlot TypeFeedbackVector::ToSlot(int index) { FeedbackVectorSlot TypeFeedbackVector::ToSlot(int index) {
DCHECK(index >= kReservedIndexCount); DCHECK_GE(index, kReservedIndexCount);
return FeedbackVectorSlot(index - kReservedIndexCount); return FeedbackVectorSlot(index - kReservedIndexCount);
} }
...@@ -159,7 +159,8 @@ void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic, ...@@ -159,7 +159,8 @@ void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic,
case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
case FeedbackVectorSlotKind::KEYED_LOAD_IC: case FeedbackVectorSlotKind::KEYED_LOAD_IC:
case FeedbackVectorSlotKind::STORE_IC: case FeedbackVectorSlotKind::STORE_IC:
case FeedbackVectorSlotKind::KEYED_STORE_IC: { case FeedbackVectorSlotKind::KEYED_STORE_IC:
case FeedbackVectorSlotKind::STORE_DATA_PROPERTY_IN_LITERAL_IC: {
if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) { if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
with++; with++;
} else if (obj == megamorphic_sentinel) { } else if (obj == megamorphic_sentinel) {
......
...@@ -161,6 +161,8 @@ const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) { ...@@ -161,6 +161,8 @@ const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) {
return "INTERPRETER_BINARYOP_IC"; return "INTERPRETER_BINARYOP_IC";
case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC: case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC:
return "INTERPRETER_COMPARE_IC"; return "INTERPRETER_COMPARE_IC";
case FeedbackVectorSlotKind::STORE_DATA_PROPERTY_IN_LITERAL_IC:
return "STORE_DATA_PROPERTY_IN_LITERAL_IC";
case FeedbackVectorSlotKind::GENERAL: case FeedbackVectorSlotKind::GENERAL:
return "STUB"; return "STUB";
case FeedbackVectorSlotKind::KINDS_NUMBER: case FeedbackVectorSlotKind::KINDS_NUMBER:
...@@ -316,6 +318,11 @@ void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared, ...@@ -316,6 +318,11 @@ void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
} }
break; break;
} }
case FeedbackVectorSlotKind::STORE_DATA_PROPERTY_IN_LITERAL_IC: {
StoreDataPropertyInLiteralICNexus nexus(this, slot);
nexus.Clear(shared->code());
break;
}
case FeedbackVectorSlotKind::INVALID: case FeedbackVectorSlotKind::INVALID:
case FeedbackVectorSlotKind::KINDS_NUMBER: case FeedbackVectorSlotKind::KINDS_NUMBER:
UNREACHABLE(); UNREACHABLE();
...@@ -987,5 +994,27 @@ CompareOperationHint CompareICNexus::GetCompareOperationFeedback() const { ...@@ -987,5 +994,27 @@ CompareOperationHint CompareICNexus::GetCompareOperationFeedback() const {
return CompareOperationHintFromFeedback(feedback); return CompareOperationHintFromFeedback(feedback);
} }
InlineCacheState StoreDataPropertyInLiteralICNexus::StateFromFeedback() const {
Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback();
if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
return UNINITIALIZED;
} else if (feedback->IsWeakCell()) {
// Don't check if the map is cleared.
return MONOMORPHIC;
}
return MEGAMORPHIC;
}
void StoreDataPropertyInLiteralICNexus::ConfigureMonomorphic(
Handle<Name> name, Handle<Map> receiver_map) {
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
SetFeedback(*cell);
SetFeedbackExtra(*name);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -30,6 +30,7 @@ enum class FeedbackVectorSlotKind { ...@@ -30,6 +30,7 @@ enum class FeedbackVectorSlotKind {
KEYED_STORE_IC, KEYED_STORE_IC,
INTERPRETER_BINARYOP_IC, INTERPRETER_BINARYOP_IC,
INTERPRETER_COMPARE_IC, INTERPRETER_COMPARE_IC,
STORE_DATA_PROPERTY_IN_LITERAL_IC,
// This is a general purpose slot that occupies one feedback vector element. // This is a general purpose slot that occupies one feedback vector element.
GENERAL, GENERAL,
...@@ -81,6 +82,10 @@ class FeedbackVectorSpecBase { ...@@ -81,6 +82,10 @@ class FeedbackVectorSpecBase {
return AddSlot(FeedbackVectorSlotKind::GENERAL); return AddSlot(FeedbackVectorSlotKind::GENERAL);
} }
FeedbackVectorSlot AddStoreDataPropertyInLiteralICSlot() {
return AddSlot(FeedbackVectorSlotKind::STORE_DATA_PROPERTY_IN_LITERAL_IC);
}
#ifdef OBJECT_PRINT #ifdef OBJECT_PRINT
// For gdb debugging. // For gdb debugging.
void Print(); void Print();
...@@ -667,6 +672,28 @@ class CompareICNexus final : public FeedbackNexus { ...@@ -667,6 +672,28 @@ class CompareICNexus final : public FeedbackNexus {
} }
}; };
class StoreDataPropertyInLiteralICNexus : public FeedbackNexus {
public:
StoreDataPropertyInLiteralICNexus(Handle<TypeFeedbackVector> vector,
FeedbackVectorSlot slot)
: FeedbackNexus(vector, slot) {
DCHECK_EQ(FeedbackVectorSlotKind::STORE_DATA_PROPERTY_IN_LITERAL_IC,
vector->GetKind(slot));
}
StoreDataPropertyInLiteralICNexus(TypeFeedbackVector* vector,
FeedbackVectorSlot slot)
: FeedbackNexus(vector, slot) {
DCHECK_EQ(FeedbackVectorSlotKind::STORE_DATA_PROPERTY_IN_LITERAL_IC,
vector->GetKind(slot));
}
void Clear(Code* host) { ConfigureUninitialized(); }
void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map);
InlineCacheState StateFromFeedback() const override;
};
inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback); inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback); inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);
......
...@@ -12,9 +12,9 @@ snippet: " ...@@ -12,9 +12,9 @@ snippet: "
speak() { console.log(this.name + ' is speaking.'); } speak() { console.log(this.name + ' is speaking.'); }
} }
" "
frame size: 8 frame size: 9
parameter count: 1 parameter count: 1
bytecode array length: 69 bytecode array length: 73
bytecodes: [ bytecodes: [
B(LdaTheHole), B(LdaTheHole),
B(Star), R(2), B(Star), R(2),
...@@ -37,7 +37,9 @@ bytecodes: [ ...@@ -37,7 +37,9 @@ bytecodes: [
B(CreateClosure), U8(2), U8(2), B(CreateClosure), U8(2), U8(2),
B(Star), R(7), B(Star), R(7),
B(LdaSmi), U8(2), B(LdaSmi), U8(2),
B(StaDataPropertyInLiteral), R(4), R(6), R(7), U8(1), B(Star), R(8),
B(Ldar), R(7),
B(StaDataPropertyInLiteral), R(4), R(6), U8(1), U8(2),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1), B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1), B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(0), B(Star), R(0),
...@@ -61,9 +63,9 @@ snippet: " ...@@ -61,9 +63,9 @@ snippet: "
speak() { console.log(this.name + ' is speaking.'); } speak() { console.log(this.name + ' is speaking.'); }
} }
" "
frame size: 8 frame size: 9
parameter count: 1 parameter count: 1
bytecode array length: 69 bytecode array length: 73
bytecodes: [ bytecodes: [
B(LdaTheHole), B(LdaTheHole),
B(Star), R(2), B(Star), R(2),
...@@ -86,7 +88,9 @@ bytecodes: [ ...@@ -86,7 +88,9 @@ bytecodes: [
B(CreateClosure), U8(2), U8(2), B(CreateClosure), U8(2), U8(2),
B(Star), R(7), B(Star), R(7),
B(LdaSmi), U8(2), B(LdaSmi), U8(2),
B(StaDataPropertyInLiteral), R(4), R(6), R(7), U8(1), B(Star), R(8),
B(Ldar), R(7),
B(StaDataPropertyInLiteral), R(4), R(6), U8(1), U8(2),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1), B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1), B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(0), B(Star), R(0),
...@@ -114,7 +118,7 @@ snippet: " ...@@ -114,7 +118,7 @@ snippet: "
" "
frame size: 10 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 112 bytecode array length: 114
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(2), B(CreateFunctionContext), U8(2),
B(PushContext), R(3), B(PushContext), R(3),
...@@ -143,8 +147,9 @@ bytecodes: [ ...@@ -143,8 +147,9 @@ bytecodes: [
B(CreateClosure), U8(3), U8(2), B(CreateClosure), U8(3), U8(2),
B(Star), R(8), B(Star), R(8),
B(LdaSmi), U8(2), B(LdaSmi), U8(2),
B(StaDataPropertyInLiteral), R(5), R(7), R(8), U8(3),
B(Star), R(9), B(Star), R(9),
B(Ldar), R(8),
B(StaDataPropertyInLiteral), R(5), R(7), U8(3), U8(2),
B(LdaCurrentContextSlot), U8(5), B(LdaCurrentContextSlot), U8(5),
/* 106 E> */ B(ToName), R(7), /* 106 E> */ B(ToName), R(7),
B(LdaConstant), U8(4), B(LdaConstant), U8(4),
...@@ -154,7 +159,7 @@ bytecodes: [ ...@@ -154,7 +159,7 @@ bytecodes: [
B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0), B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0),
B(CreateClosure), U8(5), U8(2), B(CreateClosure), U8(5), U8(2),
B(Star), R(8), B(Star), R(8),
B(StaDataPropertyInLiteral), R(6), R(7), R(8), U8(3), B(StaDataPropertyInLiteral), R(6), R(7), U8(3), U8(4),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessorWithCheck), R(4), U8(1), B(CallRuntime), U16(Runtime::kInstallClassNameAccessorWithCheck), R(4), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1),
B(Star), R(0), B(Star), R(0),
...@@ -224,9 +229,9 @@ snippet: " ...@@ -224,9 +229,9 @@ snippet: "
(class {}) (class {})
class E { static name () {}} class E { static name () {}}
" "
frame size: 9 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 95 bytecode array length: 99
bytecodes: [ bytecodes: [
B(LdaTheHole), B(LdaTheHole),
B(Star), R(3), B(Star), R(3),
...@@ -262,7 +267,9 @@ bytecodes: [ ...@@ -262,7 +267,9 @@ bytecodes: [
B(CreateClosure), U8(3), U8(2), B(CreateClosure), U8(3), U8(2),
B(Star), R(8), B(Star), R(8),
B(LdaSmi), U8(2), B(LdaSmi), U8(2),
B(StaDataPropertyInLiteral), R(6), R(7), R(8), U8(1), B(Star), R(9),
B(Ldar), R(8),
B(StaDataPropertyInLiteral), R(6), R(7), U8(1), U8(2),
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1),
B(Star), R(0), B(Star), R(0),
B(Star), R(2), B(Star), R(2),
......
...@@ -296,7 +296,7 @@ bytecodes: [ ...@@ -296,7 +296,7 @@ bytecodes: [
/* 60 E> */ B(ToName), R(2), /* 60 E> */ B(ToName), R(2),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
B(Star), R(3), B(Star), R(3),
B(StaDataPropertyInLiteral), R(1), R(2), R(3), U8(0), B(StaDataPropertyInLiteral), R(1), R(2), U8(0), U8(2),
B(Ldar), R(1), B(Ldar), R(1),
/* 69 S> */ B(Return), /* 69 S> */ B(Return),
] ]
...@@ -323,7 +323,7 @@ bytecodes: [ ...@@ -323,7 +323,7 @@ bytecodes: [
/* 68 E> */ B(ToName), R(2), /* 68 E> */ B(ToName), R(2),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
B(Star), R(3), B(Star), R(3),
B(StaDataPropertyInLiteral), R(1), R(2), R(3), U8(0), B(StaDataPropertyInLiteral), R(1), R(2), U8(0), U8(4),
B(Ldar), R(1), B(Ldar), R(1),
/* 77 S> */ B(Return), /* 77 S> */ B(Return),
] ]
...@@ -350,7 +350,7 @@ bytecodes: [ ...@@ -350,7 +350,7 @@ bytecodes: [
/* 60 E> */ B(ToName), R(2), /* 60 E> */ B(ToName), R(2),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
B(Star), R(3), B(Star), R(3),
B(StaDataPropertyInLiteral), R(1), R(2), R(3), U8(0), B(StaDataPropertyInLiteral), R(1), R(2), U8(0), U8(2),
B(CreateObjectLiteral), U8(1), U8(0), U8(35), R(4), B(CreateObjectLiteral), U8(1), U8(0), U8(35), R(4),
B(Mov), R(1), R(2), B(Mov), R(1), R(2),
B(Mov), R(4), R(3), B(Mov), R(4), R(3),
...@@ -380,7 +380,7 @@ bytecodes: [ ...@@ -380,7 +380,7 @@ bytecodes: [
/* 60 E> */ B(ToName), R(2), /* 60 E> */ B(ToName), R(2),
B(LdaConstant), U8(2), B(LdaConstant), U8(2),
B(Star), R(3), B(Star), R(3),
B(StaDataPropertyInLiteral), R(1), R(2), R(3), U8(0), B(StaDataPropertyInLiteral), R(1), R(2), U8(0), U8(2),
B(LdaConstant), U8(3), B(LdaConstant), U8(3),
B(ToName), R(3), B(ToName), R(3),
B(CreateClosure), U8(4), U8(2), B(CreateClosure), U8(4), U8(2),
......
...@@ -324,8 +324,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -324,8 +324,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.StoreNamedProperty(reg, wide_name, 0, LanguageMode::STRICT) .StoreNamedProperty(reg, wide_name, 0, LanguageMode::STRICT)
.StoreKeyedProperty(reg, reg, 2056, LanguageMode::STRICT); .StoreKeyedProperty(reg, reg, 2056, LanguageMode::STRICT);
builder.StoreDataPropertyInLiteral(reg, reg, reg, builder.StoreDataPropertyInLiteral(reg, reg,
DataPropertyInLiteralFlag::kNoFlags); DataPropertyInLiteralFlag::kNoFlags, 0);
// Emit wide context operations. // Emit wide context operations.
builder.LoadContextSlot(reg, 1024, 0).StoreContextSlot(reg, 1024, 0); builder.LoadContextSlot(reg, 1024, 0).StoreContextSlot(reg, 1024, 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment