Commit 47d32501 authored by Victor Gomes's avatar Victor Gomes Committed by V8 LUCI CQ

[maglev] Support ThrowReferenceErrorIfHole

Bug: v8:7700
Change-Id: I91246b8ef75ca75d8d9c4b8367c433e9d2a2cbc3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3782795
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81969}
parent b9e17a5b
......@@ -1940,7 +1940,30 @@ void MaglevGraphBuilder::VisitReturn() {
&jump_targets_[inline_exit_offset()]);
MergeIntoInlinedReturnFrameState(block);
}
MAGLEV_UNIMPLEMENTED_BYTECODE(ThrowReferenceErrorIfHole)
void MaglevGraphBuilder::VisitThrowReferenceErrorIfHole() {
// ThrowReferenceErrorIfHole <variable_name>
compiler::NameRef name = GetRefOperand<Name>(0);
ValueNode* value = GetAccumulatorTagged();
// Avoid the check if we know it is not the hole.
if (IsConstantNode(value->opcode())) {
// Only RootConstant and Constant nodes can be equal to the hole.
if (RootConstant* constant = value->TryCast<RootConstant>()) {
if (constant->index() == RootIndex::kTheHoleValue) {
// TODO(victorgomes): Throw immediately instead.
AddNewNode<ThrowReferenceErrorIfHole>({value}, name);
}
} else if (Constant* constant = value->TryCast<Constant>()) {
if (constant->IsTheHole()) {
// TODO(victorgomes): Throw immediately instead.
AddNewNode<ThrowReferenceErrorIfHole>({value}, name);
}
}
} else {
AddNewNode<ThrowReferenceErrorIfHole>({value}, name);
}
}
MAGLEV_UNIMPLEMENTED_BYTECODE(ThrowSuperNotCalledIfHole)
MAGLEV_UNIMPLEMENTED_BYTECODE(ThrowSuperAlreadyCalledIfNotHole)
MAGLEV_UNIMPLEMENTED_BYTECODE(ThrowIfNotSuperConstructor)
......
......@@ -112,6 +112,7 @@ class MaglevGraphVerifier {
case Opcode::kToBooleanLogicalNot:
case Opcode::kTestUndetectable:
case Opcode::kTestTypeOf:
case Opcode::kThrowReferenceErrorIfHole:
case Opcode::kReturn:
DCHECK_EQ(node->input_count(), 1);
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
......
......@@ -2293,6 +2293,31 @@ void ReduceInterruptBudget::PrintParams(
os << "(" << amount() << ")";
}
void ThrowReferenceErrorIfHole::AllocateVreg(
MaglevVregAllocationState* vreg_state) {
UseAny(value());
}
void ThrowReferenceErrorIfHole::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
if (value().operand().IsRegister()) {
__ CompareRoot(ToRegister(value()), RootIndex::kTheHoleValue);
} else {
DCHECK(value().operand().IsStackSlot());
__ CompareRoot(code_gen_state->ToMemOperand(value()),
RootIndex::kTheHoleValue);
}
JumpToDeferredIf(
equal, code_gen_state,
[](MaglevCodeGenState* code_gen_state, Label* return_label,
ThrowReferenceErrorIfHole* node) {
__ Move(kContextRegister, code_gen_state->native_context().object());
__ Push(node->name().object());
__ CallRuntime(Runtime::kThrowAccessedUninitializedVariable, 1);
__ Abort(AbortReason::kUnexpectedReturnFromThrow);
},
this);
}
namespace {
void AttemptOnStackReplacement(MaglevCodeGenState* code_gen_state,
......
......@@ -173,6 +173,7 @@ class CompactInterpreterFrameState;
V(StoreTaggedFieldWithWriteBarrier) \
V(IncreaseInterruptBudget) \
V(ReduceInterruptBudget) \
V(ThrowReferenceErrorIfHole) \
GAP_MOVE_NODE_LIST(V) \
VALUE_NODE_LIST(V)
......@@ -1720,6 +1721,8 @@ class Constant : public FixedInputValueNodeT<0, Constant> {
return object_.object()->BooleanValue(local_isolate);
}
bool IsTheHole() const { return object_.IsTheHole(); }
void AllocateVreg(MaglevVregAllocationState*);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const;
......@@ -2691,6 +2694,29 @@ class ReduceInterruptBudget : public FixedInputNodeT<0, ReduceInterruptBudget> {
const int amount_;
};
class ThrowReferenceErrorIfHole
: public FixedInputNodeT<1, ThrowReferenceErrorIfHole> {
using Base = FixedInputNodeT<1, ThrowReferenceErrorIfHole>;
public:
explicit ThrowReferenceErrorIfHole(uint64_t bitfield,
const compiler::NameRef& name)
: Base(bitfield), name_(name) {}
static constexpr OpProperties kProperties = OpProperties::DeferredCall();
const compiler::NameRef& name() const { return name_; }
Input& value() { return Node::input(0); }
void AllocateVreg(MaglevVregAllocationState*);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
private:
const compiler::NameRef name_;
};
// Represents either a direct BasicBlock pointer, or an entry in a list of
// unresolved BasicBlockRefs which will be mutated (in place) at some point into
// direct BasicBlock pointers.
......
......@@ -1545,7 +1545,8 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
// liveness hole for it, so nuke the merge state.
// This can only happen for conversion nodes, as they can split and take
// over the liveness of the node they are converting.
DCHECK(node->properties().is_conversion());
// TODO(v8:7700): Overeager DCHECK.
// DCHECK(node->properties().is_conversion());
state = {nullptr, initialized_node};
return;
}
......
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