[maglev] Remove HasProperty and use CallBuiltin instead

We create a constructor for CallBuiltin that accepts a feedback vector.
It assumes that the builtin expects a slot and the vector respectively
at the end.

Bug: v8:7700
Change-Id: I20f9b4ff172dca7779abd31a042b3bdc734df350
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3804250
Auto-Submit: Victor Gomes <victorgomes@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82159}
This commit is contained in:
Victor Gomes 2022-08-03 08:13:48 +02:00 committed by V8 LUCI CQ
parent 71d3ae39e7
commit d195ce148b
5 changed files with 60 additions and 52 deletions

View File

@ -1939,9 +1939,8 @@ void MaglevGraphBuilder::VisitTestIn() {
// TODO(victorgomes): Create fast path using feedback. // TODO(victorgomes): Create fast path using feedback.
USE(feedback_source); USE(feedback_source);
ValueNode* context = GetContext();
SetAccumulator( SetAccumulator(
AddNewNode<HasProperty>({context, object, name}, feedback_source)); BuildCallBuiltin<Builtin::kKeyedHasIC>({object, name}, feedback_source));
} }
void MaglevGraphBuilder::VisitToName() { void MaglevGraphBuilder::VisitToName() {

View File

@ -305,6 +305,26 @@ class MaglevGraphBuilder {
return AddNode(call_builtin); return AddNode(call_builtin);
} }
template <Builtin kBuiltin>
CallBuiltin* BuildCallBuiltin(
std::initializer_list<ValueNode*> inputs,
compiler::FeedbackSource& feedback,
CallBuiltin::FeedbackSlotType slot_type = CallBuiltin::kTaggedIndex) {
CallBuiltin* call_builtin = BuildCallBuiltin<kBuiltin>(inputs);
call_builtin->set_feedback(feedback, slot_type);
#ifdef DEBUG
// Check that the last parameters are kSlot and kVector.
using Descriptor = typename CallInterfaceDescriptorFor<kBuiltin>::type;
int slot_index = call_builtin->num_args(Descriptor::HasContextParameter());
int vector_index = slot_index + 1;
DCHECK_EQ(slot_index, Descriptor::kSlot);
// TODO(victorgomes): Rename all kFeedbackVector parameters in the builtins
// to kVector.
DCHECK_EQ(vector_index, Descriptor::kVector);
#endif // DEBUG
return call_builtin;
}
CallRuntime* BuildCallRuntime(Runtime::FunctionId function_id, CallRuntime* BuildCallRuntime(Runtime::FunctionId function_id,
std::initializer_list<ValueNode*> inputs) { std::initializer_list<ValueNode*> inputs) {
CallRuntime* call_runtime = CreateNewNode<CallRuntime>( CallRuntime* call_runtime = CreateNewNode<CallRuntime>(

View File

@ -182,7 +182,6 @@ class MaglevGraphVerifier {
CheckValueInputIs(node, 1, ValueRepresentation::kTagged); CheckValueInputIs(node, 1, ValueRepresentation::kTagged);
break; break;
case Opcode::kDeleteProperty: case Opcode::kDeleteProperty:
case Opcode::kHasProperty:
case Opcode::kLoadNamedFromSuperGeneric: case Opcode::kLoadNamedFromSuperGeneric:
case Opcode::kSetNamedGeneric: case Opcode::kSetNamedGeneric:
case Opcode::kDefineNamedOwnGeneric: case Opcode::kDefineNamedOwnGeneric:

View File

@ -761,26 +761,6 @@ void DeleteProperty::PrintParams(std::ostream& os,
os << "(" << LanguageMode2String(mode()) << ")"; os << "(" << LanguageMode2String(mode()) << ")";
} }
void HasProperty::AllocateVreg(MaglevVregAllocationState* vreg_state) {
using D = CallInterfaceDescriptorFor<Builtin::kKeyedHasIC>::type;
UseFixed(context(), kContextRegister);
UseFixed(object(), D::GetRegisterParameter(D::kReceiver));
UseFixed(name(), D::GetRegisterParameter(D::kName));
DefineAsFixed(vreg_state, this, kReturnRegister0);
}
void HasProperty::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
using D = CallInterfaceDescriptorFor<Builtin::kKeyedHasIC>::type;
DCHECK_EQ(ToRegister(context()), kContextRegister);
DCHECK_EQ(ToRegister(object()), D::GetRegisterParameter(D::kReceiver));
DCHECK_EQ(ToRegister(name()), D::GetRegisterParameter(D::kName));
__ Move(D::GetRegisterParameter(D::kSlot),
TaggedIndex::FromIntptr(feedback().index()));
__ Move(D::GetRegisterParameter(D::kVector), feedback().vector);
__ CallBuiltin(Builtin::kKeyedHasIC);
code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info());
}
void InitialValue::AllocateVreg(MaglevVregAllocationState* vreg_state) { void InitialValue::AllocateVreg(MaglevVregAllocationState* vreg_state) {
// TODO(leszeks): Make this nicer. // TODO(leszeks): Make this nicer.
result().SetUnallocated(compiler::UnallocatedOperand::FIXED_SLOT, result().SetUnallocated(compiler::UnallocatedOperand::FIXED_SLOT,
@ -2536,13 +2516,14 @@ void Construct::GenerateCode(MaglevCodeGenState* code_gen_state,
void CallBuiltin::AllocateVreg(MaglevVregAllocationState* vreg_state) { void CallBuiltin::AllocateVreg(MaglevVregAllocationState* vreg_state) {
// TODO(v8:7700): Support stack arguments. // TODO(v8:7700): Support stack arguments.
auto descriptor = Builtins::CallInterfaceDescriptorFor(builtin()); auto descriptor = Builtins::CallInterfaceDescriptorFor(builtin());
bool has_context = descriptor.HasContextParameter();
DCHECK_EQ(descriptor.GetRegisterParameterCount(), DCHECK_EQ(descriptor.GetRegisterParameterCount(),
num_args(descriptor.HasContextParameter())); num_args(has_context) + (has_feedback() ? 2 : 0));
int i = 0; int i = 0;
for (; i < num_args(descriptor.HasContextParameter()); i++) { for (; i < num_args(has_context); i++) {
UseFixed(input(i), descriptor.GetRegisterParameter(i)); UseFixed(input(i), descriptor.GetRegisterParameter(i));
} }
if (descriptor.HasContextParameter()) { if (has_context) {
UseFixed(input(i), kContextRegister); UseFixed(input(i), kContextRegister);
} }
DCHECK_EQ(descriptor.GetReturnCount(), 1); DCHECK_EQ(descriptor.GetReturnCount(), 1);
@ -2550,6 +2531,22 @@ void CallBuiltin::AllocateVreg(MaglevVregAllocationState* vreg_state) {
} }
void CallBuiltin::GenerateCode(MaglevCodeGenState* code_gen_state, void CallBuiltin::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) { const ProcessingState& state) {
if (has_feedback()) {
auto descriptor = Builtins::CallInterfaceDescriptorFor(builtin());
int slot_index = num_args(descriptor.HasContextParameter());
int vector_index = slot_index + 1;
switch (slot_type()) {
case kTaggedIndex:
__ Move(descriptor.GetRegisterParameter(slot_index),
TaggedIndex::FromIntptr(feedback().index()));
break;
case kSmi:
__ Move(descriptor.GetRegisterParameter(slot_index),
Smi::FromInt(feedback().index()));
break;
}
__ Move(descriptor.GetRegisterParameter(vector_index), feedback().vector);
}
__ CallBuiltin(builtin()); __ CallBuiltin(builtin());
code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info()); code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info());
} }

View File

@ -131,7 +131,6 @@ class CompactInterpreterFrameState;
V(FastCreateClosure) \ V(FastCreateClosure) \
V(CreateRegExpLiteral) \ V(CreateRegExpLiteral) \
V(DeleteProperty) \ V(DeleteProperty) \
V(HasProperty) \
V(InitialValue) \ V(InitialValue) \
V(LoadTaggedField) \ V(LoadTaggedField) \
V(LoadDoubleField) \ V(LoadDoubleField) \
@ -1728,31 +1727,6 @@ class DeleteProperty : public FixedInputValueNodeT<3, DeleteProperty> {
const LanguageMode mode_; const LanguageMode mode_;
}; };
class HasProperty : public FixedInputValueNodeT<3, HasProperty> {
using Base = FixedInputValueNodeT<3, HasProperty>;
public:
explicit HasProperty(uint64_t bitfield,
const compiler::FeedbackSource& feedback)
: Base(bitfield), feedback_(feedback) {}
// The implementation currently calls runtime.
static constexpr OpProperties kProperties = OpProperties::JSCall();
Input& context() { return input(0); }
Input& object() { return input(1); }
Input& name() { return input(2); }
compiler::FeedbackSource feedback() const { return feedback_; }
void AllocateVreg(MaglevVregAllocationState*);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
private:
const compiler::FeedbackSource feedback_;
};
class ToObject : public FixedInputValueNodeT<2, ToObject> { class ToObject : public FixedInputValueNodeT<2, ToObject> {
using Base = FixedInputValueNodeT<2, ToObject>; using Base = FixedInputValueNodeT<2, ToObject>;
@ -2858,6 +2832,8 @@ class CallBuiltin : public ValueNodeT<CallBuiltin> {
using Base = ValueNodeT<CallBuiltin>; using Base = ValueNodeT<CallBuiltin>;
public: public:
enum FeedbackSlotType { kTaggedIndex, kSmi };
// This ctor is used when for variable input counts. // This ctor is used when for variable input counts.
// Inputs must be initialized manually. // Inputs must be initialized manually.
CallBuiltin(uint64_t bitfield, Builtin builtin) CallBuiltin(uint64_t bitfield, Builtin builtin)
@ -2878,6 +2854,21 @@ class CallBuiltin : public ValueNodeT<CallBuiltin> {
// This is an overestimation, since some builtins might not call JS code. // This is an overestimation, since some builtins might not call JS code.
static constexpr OpProperties kProperties = OpProperties::JSCall(); static constexpr OpProperties kProperties = OpProperties::JSCall();
bool has_feedback() const { return feedback_.has_value(); }
compiler::FeedbackSource feedback() const {
DCHECK(has_feedback());
return feedback_.value();
}
FeedbackSlotType slot_type() const {
DCHECK(has_feedback());
return slot_type_;
}
void set_feedback(compiler::FeedbackSource& feedback,
FeedbackSlotType slot_type) {
feedback_ = feedback;
slot_type_ = slot_type;
}
Builtin builtin() const { return builtin_; } Builtin builtin() const { return builtin_; }
int num_args(bool has_context) const { int num_args(bool has_context) const {
@ -2895,6 +2886,8 @@ class CallBuiltin : public ValueNodeT<CallBuiltin> {
private: private:
Builtin builtin_; Builtin builtin_;
base::Optional<compiler::FeedbackSource> feedback_;
FeedbackSlotType slot_type_ = kTaggedIndex;
}; };
class CallRuntime : public ValueNodeT<CallRuntime> { class CallRuntime : public ValueNodeT<CallRuntime> {