[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:
parent
cd02fe8edb
commit
5f2d828274
@ -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>
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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>;
|
||||
|
||||
|
35
test/mjsunit/maglev/super-ic.js
Normal file
35
test/mjsunit/maglev/super-ic.js
Normal 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));
|
Loading…
Reference in New Issue
Block a user