[maglev] Support GetNamedPropertyFromSuper

Bug: v8:7700
Change-Id: Id5fddd337635b2932bb1ab0609db38ecc72d95b4
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3790961
Auto-Submit: Victor Gomes <victorgomes@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82042}
This commit is contained in:
Victor Gomes 2022-07-28 16:17:12 +02:00 committed by V8 LUCI CQ
parent cd02fe8edb
commit 5f2d828274
5 changed files with 144 additions and 1 deletions

View File

@ -940,7 +940,53 @@ void MaglevGraphBuilder::VisitGetNamedProperty() {
AddNewNode<LoadNamedGeneric>({context, object}, name, feedback_source));
}
MAGLEV_UNIMPLEMENTED_BYTECODE(GetNamedPropertyFromSuper)
void MaglevGraphBuilder::VisitGetNamedPropertyFromSuper() {
// GetNamedPropertyFromSuper <receiver> <name_index> <slot>
ValueNode* receiver = LoadRegisterTagged(0);
ValueNode* home_object = GetAccumulatorTagged();
compiler::NameRef name = GetRefOperand<Name>(1);
FeedbackSlot slot = GetSlotOperand(2);
compiler::FeedbackSource feedback_source{feedback(), slot};
// {home_object} is guaranteed to be a HeapObject.
ValueNode* home_object_map =
AddNewNode<LoadTaggedField>({home_object}, HeapObject::kMapOffset);
ValueNode* lookup_start_object =
AddNewNode<LoadTaggedField>({home_object_map}, Map::kPrototypeOffset);
const compiler::ProcessedFeedback& processed_feedback =
broker()->GetFeedbackForPropertyAccess(feedback_source,
compiler::AccessMode::kLoad, name);
switch (processed_feedback.kind()) {
case compiler::ProcessedFeedback::kInsufficient:
EmitUnconditionalDeopt(
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
return;
case compiler::ProcessedFeedback::kNamedAccess: {
const compiler::NamedAccessFeedback& named_feedback =
processed_feedback.AsNamedAccess();
if (named_feedback.maps().size() != 1) break;
compiler::MapRef map = named_feedback.maps()[0];
// Monomorphic load, check the handler.
// TODO(leszeks): Make GetFeedbackForPropertyAccess read the handler.
MaybeObjectHandle handler =
FeedbackNexusForSlot(slot).FindHandlerForMap(map.object());
if (TryBuildMonomorphicLoad(lookup_start_object, map, handler)) return;
} break;
default:
break;
}
// Create a generic load.
ValueNode* context = GetContext();
SetAccumulator(AddNewNode<LoadNamedFromSuperGeneric>(
{context, receiver, lookup_start_object}, name, feedback_source));
}
void MaglevGraphBuilder::VisitGetKeyedProperty() {
// GetKeyedProperty <object> <slot>

View File

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

View File

@ -1321,6 +1321,34 @@ void LoadNamedGeneric::PrintParams(std::ostream& os,
os << "(" << name_ << ")";
}
void LoadNamedFromSuperGeneric::AllocateVreg(
MaglevVregAllocationState* vreg_state) {
using D = LoadWithReceiverAndVectorDescriptor;
UseFixed(context(), kContextRegister);
UseFixed(receiver(), D::GetRegisterParameter(D::kReceiver));
UseFixed(lookup_start_object(),
D::GetRegisterParameter(D::kLookupStartObject));
DefineAsFixed(vreg_state, this, kReturnRegister0);
}
void LoadNamedFromSuperGeneric::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
using D = LoadWithReceiverAndVectorDescriptor;
DCHECK_EQ(ToRegister(context()), kContextRegister);
DCHECK_EQ(ToRegister(receiver()), D::GetRegisterParameter(D::kReceiver));
DCHECK_EQ(ToRegister(lookup_start_object()),
D::GetRegisterParameter(D::kLookupStartObject));
__ 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::kLoadSuperIC);
code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info());
}
void LoadNamedFromSuperGeneric::PrintParams(
std::ostream& os, MaglevGraphLabeller* graph_labeller) const {
os << "(" << name_ << ")";
}
void SetNamedGeneric::AllocateVreg(MaglevVregAllocationState* vreg_state) {
using D = CallInterfaceDescriptorFor<Builtin::kStoreIC>::type;
UseFixed(context(), kContextRegister);

View File

@ -133,6 +133,7 @@ class CompactInterpreterFrameState;
V(LoadDoubleField) \
V(LoadGlobal) \
V(LoadNamedGeneric) \
V(LoadNamedFromSuperGeneric) \
V(SetNamedGeneric) \
V(DefineNamedOwnGeneric) \
V(StoreInArrayLiteralGeneric) \
@ -2356,6 +2357,38 @@ class LoadNamedGeneric : public FixedInputValueNodeT<2, LoadNamedGeneric> {
const compiler::FeedbackSource feedback_;
};
class LoadNamedFromSuperGeneric
: public FixedInputValueNodeT<3, LoadNamedFromSuperGeneric> {
using Base = FixedInputValueNodeT<3, LoadNamedFromSuperGeneric>;
public:
explicit LoadNamedFromSuperGeneric(uint64_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 kReceiverIndex = 1;
static constexpr int kLookupStartObjectIndex = 2;
Input& context() { return input(kContextIndex); }
Input& receiver() { return input(kReceiverIndex); }
Input& lookup_start_object() { return input(kLookupStartObjectIndex); }
void AllocateVreg(MaglevVregAllocationState*);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const;
private:
const compiler::NameRef name_;
const compiler::FeedbackSource feedback_;
};
class SetNamedGeneric : public FixedInputValueNodeT<3, SetNamedGeneric> {
using Base = FixedInputValueNodeT<3, SetNamedGeneric>;

View File

@ -0,0 +1,35 @@
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --maglev --no-stress-opt
class A {
foo() {
return 42;
}
};
class B extends A {
bar() {
return super.foo();
}
};
class C {
foo() {
return 24;
}
};
var o = new B();
%PrepareFunctionForOptimization(o.bar);
assertEquals(o.bar(), 42);
%OptimizeMaglevOnNextCall(o.bar);
assertEquals(o.bar(), 42);
assertTrue(isMaglevved(o.bar));
// This should deopt.
o.__proto__.__proto__ = new C();
assertEquals(o.bar(), 24);
assertFalse(isMaglevved(o.bar));