Commit c2dadb69 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[maglev] Add support for DefineNamedOwnProperty

Add a generic DefineNamedOwn node for DefineNamedOwnProperty, and a
monomorphic fast path identical to SetNamedProperty for simple field
stores.

Bug: v8:7700
Change-Id: I35ff9d54be8bb8e437865e4d1ba38eb726034e24
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3663084
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80736}
parent 9e27dbca
......@@ -808,7 +808,55 @@ void MaglevGraphBuilder::VisitSetNamedProperty() {
feedback_source));
}
MAGLEV_UNIMPLEMENTED_BYTECODE(DefineNamedOwnProperty)
void MaglevGraphBuilder::VisitDefineNamedOwnProperty() {
// DefineNamedOwnProperty <object> <name_index> <slot>
ValueNode* object = LoadRegisterTagged(0);
compiler::NameRef name = GetRefOperand<Name>(1);
FeedbackSlot slot = GetSlotOperand(2);
compiler::FeedbackSource feedback_source{feedback(), slot};
const compiler::ProcessedFeedback& processed_feedback =
broker()->GetFeedbackForPropertyAccess(
feedback_source, compiler::AccessMode::kStore, name);
switch (processed_feedback.kind()) {
case compiler::ProcessedFeedback::kInsufficient:
EmitUnconditionalDeopt();
return;
case compiler::ProcessedFeedback::kNamedAccess: {
const compiler::NamedAccessFeedback& named_feedback =
processed_feedback.AsNamedAccess();
if (named_feedback.maps().size() == 1) {
// Monomorphic store, check the handler.
// TODO(leszeks): Make GetFeedbackForPropertyAccess read the handler.
MaybeObjectHandle handler =
FeedbackNexusForSlot(slot).FindHandlerForMap(
named_feedback.maps()[0].object());
if (!handler.is_null() && handler->IsSmi()) {
int smi_handler = handler->ToSmi().value();
StoreHandler::Kind kind = StoreHandler::KindBits::decode(smi_handler);
if (kind == StoreHandler::Kind::kField) {
AddNewNode<CheckMaps>({object}, named_feedback.maps()[0]);
ValueNode* value = GetAccumulatorTagged();
AddNewNode<StoreField>({object, value}, smi_handler);
return;
}
}
}
} break;
default:
break;
}
// Create a generic store in the fallthrough.
ValueNode* context = GetContext();
ValueNode* value = GetAccumulatorTagged();
SetAccumulator(AddNewNode<DefineNamedOwnGeneric>({context, object, value},
name, feedback_source));
}
MAGLEV_UNIMPLEMENTED_BYTECODE(SetKeyedProperty)
MAGLEV_UNIMPLEMENTED_BYTECODE(DefineKeyedOwnProperty)
MAGLEV_UNIMPLEMENTED_BYTECODE(StaInArrayLiteral)
......
......@@ -135,6 +135,7 @@ class MaglevGraphVerifier {
CheckValueInputIs(node, 1, ValueRepresentation::kTagged);
break;
case Opcode::kSetNamedGeneric:
case Opcode::kDefineNamedOwnGeneric:
DCHECK_EQ(node->input_count(), 3);
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
CheckValueInputIs(node, 1, ValueRepresentation::kTagged);
......
......@@ -781,7 +781,7 @@ void LoadNamedGeneric::PrintParams(std::ostream& os,
void SetNamedGeneric::AllocateVreg(MaglevVregAllocationState* vreg_state,
const ProcessingState& state) {
using D = StoreWithVectorDescriptor;
using D = CallInterfaceDescriptorFor<Builtin::kStoreIC>::type;
UseFixed(context(), kContextRegister);
UseFixed(object_input(), D::GetRegisterParameter(D::kReceiver));
UseFixed(value_input(), D::GetRegisterParameter(D::kValue));
......@@ -789,7 +789,7 @@ void SetNamedGeneric::AllocateVreg(MaglevVregAllocationState* vreg_state,
}
void SetNamedGeneric::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
using D = StoreWithVectorDescriptor;
using D = CallInterfaceDescriptorFor<Builtin::kStoreIC>::type;
DCHECK_EQ(ToRegister(context()), kContextRegister);
DCHECK_EQ(ToRegister(object_input()), D::GetRegisterParameter(D::kReceiver));
DCHECK_EQ(ToRegister(value_input()), D::GetRegisterParameter(D::kValue));
......@@ -805,6 +805,32 @@ void SetNamedGeneric::PrintParams(std::ostream& os,
os << "(" << name_ << ")";
}
void DefineNamedOwnGeneric::AllocateVreg(MaglevVregAllocationState* vreg_state,
const ProcessingState& state) {
using D = CallInterfaceDescriptorFor<Builtin::kDefineNamedOwnIC>::type;
UseFixed(context(), kContextRegister);
UseFixed(object_input(), D::GetRegisterParameter(D::kReceiver));
UseFixed(value_input(), D::GetRegisterParameter(D::kValue));
DefineAsFixed(vreg_state, this, kReturnRegister0);
}
void DefineNamedOwnGeneric::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
using D = CallInterfaceDescriptorFor<Builtin::kDefineNamedOwnIC>::type;
DCHECK_EQ(ToRegister(context()), kContextRegister);
DCHECK_EQ(ToRegister(object_input()), D::GetRegisterParameter(D::kReceiver));
DCHECK_EQ(ToRegister(value_input()), D::GetRegisterParameter(D::kValue));
__ Move(D::GetRegisterParameter(D::kName), name().object());
__ Move(D::GetRegisterParameter(D::kSlot),
Smi::FromInt(feedback().slot.ToInt()));
__ Move(D::GetRegisterParameter(D::kVector), feedback().vector);
__ CallBuiltin(Builtin::kDefineNamedOwnIC);
code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info());
}
void DefineNamedOwnGeneric::PrintParams(
std::ostream& os, MaglevGraphLabeller* graph_labeller) const {
os << "(" << name_ << ")";
}
void GapMove::AllocateVreg(MaglevVregAllocationState* vreg_state,
const ProcessingState& state) {
UNREACHABLE();
......
......@@ -125,6 +125,7 @@ class CompactInterpreterFrameState;
V(LoadGlobal) \
V(LoadNamedGeneric) \
V(SetNamedGeneric) \
V(DefineNamedOwnGeneric) \
V(Phi) \
V(RegisterInput) \
V(CheckedSmiTag) \
......@@ -1793,6 +1794,38 @@ class SetNamedGeneric : public FixedInputValueNodeT<3, SetNamedGeneric> {
const compiler::FeedbackSource feedback_;
};
class DefineNamedOwnGeneric
: public FixedInputValueNodeT<3, DefineNamedOwnGeneric> {
using Base = FixedInputValueNodeT<3, DefineNamedOwnGeneric>;
public:
explicit DefineNamedOwnGeneric(uint32_t bitfield,
const compiler::NameRef& name,
const compiler::FeedbackSource& feedback)
: Base(bitfield), name_(name), feedback_(feedback) {}
// The implementation currently calls runtime.
static constexpr OpProperties kProperties = OpProperties::JSCall();
compiler::NameRef name() const { return name_; }
compiler::FeedbackSource feedback() const { return feedback_; }
static constexpr int kContextIndex = 0;
static constexpr int kObjectIndex = 1;
static constexpr int kValueIndex = 2;
Input& context() { return input(kContextIndex); }
Input& object_input() { return input(kObjectIndex); }
Input& value_input() { return input(kValueIndex); }
void AllocateVreg(MaglevVregAllocationState*, const ProcessingState&);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const;
private:
const compiler::NameRef name_;
const compiler::FeedbackSource feedback_;
};
class GapMove : public FixedInputNodeT<0, GapMove> {
using Base = FixedInputNodeT<0, GapMove>;
......
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