Commit 229687ba authored by Victor Gomes's avatar Victor Gomes Committed by V8 LUCI CQ

[maglev] Support CallWithSpread and ContructWithSpread

Bug: v8:7700
Change-Id: I4d74ca2d063869978226586c81fc45e0fd45dffa
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3804665
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Auto-Submit: Victor Gomes <victorgomes@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82175}
parent acb93dbe
......@@ -1707,7 +1707,20 @@ void MaglevGraphBuilder::VisitCallUndefinedReceiver2() {
BuildCallFromRegisters(2, ConvertReceiverMode::kNullOrUndefined);
}
MAGLEV_UNIMPLEMENTED_BYTECODE(CallWithSpread)
void MaglevGraphBuilder::VisitCallWithSpread() {
ValueNode* function = LoadRegisterTagged(0);
interpreter::RegisterList args = iterator_.GetRegisterListOperand(1);
ValueNode* context = GetContext();
size_t input_count = args.register_count() + CallWithSpread::kFixedInputCount;
CallWithSpread* call =
CreateNewNode<CallWithSpread>(input_count, function, context);
for (int i = 0; i < args.register_count(); ++i) {
call->set_arg(i, GetTaggedValue(args[i]));
}
SetAccumulator(AddNode(call));
}
void MaglevGraphBuilder::VisitCallRuntime() {
Runtime::FunctionId function_id = iterator_.GetRuntimeIdOperand(0);
......@@ -1893,7 +1906,25 @@ void MaglevGraphBuilder::VisitConstruct() {
SetAccumulator(AddNode(construct));
}
MAGLEV_UNIMPLEMENTED_BYTECODE(ConstructWithSpread)
void MaglevGraphBuilder::VisitConstructWithSpread() {
ValueNode* new_target = GetAccumulatorTagged();
ValueNode* constructor = LoadRegisterTagged(0);
interpreter::RegisterList args = iterator_.GetRegisterListOperand(1);
ValueNode* context = GetContext();
int kReceiver = 1;
size_t input_count =
args.register_count() + kReceiver + ConstructWithSpread::kFixedInputCount;
ConstructWithSpread* construct = CreateNewNode<ConstructWithSpread>(
input_count, constructor, new_target, context);
int arg_index = 0;
// Add undefined receiver.
construct->set_arg(arg_index++, GetRootConstant(RootIndex::kUndefinedValue));
for (int i = 0; i < args.register_count(); ++i) {
construct->set_arg(arg_index++, GetTaggedValue(args[i]));
}
SetAccumulator(AddNode(construct));
}
void MaglevGraphBuilder::VisitTestEqual() {
VisitCompareOperation<Operation::kEqual>();
......
......@@ -247,7 +247,9 @@ class MaglevGraphVerifier {
break;
case Opcode::kCall:
case Opcode::kCallRuntime:
case Opcode::kCallWithSpread:
case Opcode::kConstruct:
case Opcode::kConstructWithSpread:
case Opcode::kPhi:
// All inputs should be tagged.
for (int i = 0; i < node->input_count(); i++) {
......
......@@ -2601,6 +2601,60 @@ void CallRuntime::PrintParams(std::ostream& os,
os << "(" << Runtime::FunctionForId(function_id())->name << ")";
}
void CallWithSpread::AllocateVreg(MaglevVregAllocationState* vreg_state) {
using D = CallInterfaceDescriptorFor<Builtin::kCallWithSpread>::type;
UseFixed(function(), D::GetRegisterParameter(D::kTarget));
UseFixed(context(), kContextRegister);
for (int i = 0; i < num_args() - 1; i++) {
UseAny(arg(i));
}
UseFixed(spread(), D::GetRegisterParameter(D::kSpread));
DefineAsFixed(vreg_state, this, kReturnRegister0);
}
void CallWithSpread::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
using D = CallInterfaceDescriptorFor<Builtin::kCallWithSpread>::type;
DCHECK_EQ(ToRegister(function()), D::GetRegisterParameter(D::kTarget));
DCHECK_EQ(ToRegister(context()), kContextRegister);
// Push other arguments (other than the spread) to the stack.
int argc_no_spread = num_args() - 1;
for (int i = argc_no_spread - 1; i >= 0; --i) {
PushInput(code_gen_state, arg(i));
}
__ Move(D::GetRegisterParameter(D::kArgumentsCount),
Immediate(argc_no_spread));
__ CallBuiltin(Builtin::kCallWithSpread);
code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info());
}
void ConstructWithSpread::AllocateVreg(MaglevVregAllocationState* vreg_state) {
using D = CallInterfaceDescriptorFor<Builtin::kConstructWithSpread>::type;
UseFixed(function(), D::GetRegisterParameter(D::kTarget));
UseFixed(new_target(), D::GetRegisterParameter(D::kNewTarget));
UseFixed(context(), kContextRegister);
for (int i = 0; i < num_args() - 1; i++) {
UseAny(arg(i));
}
UseFixed(spread(), D::GetRegisterParameter(D::kSpread));
DefineAsFixed(vreg_state, this, kReturnRegister0);
}
void ConstructWithSpread::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
using D = CallInterfaceDescriptorFor<Builtin::kConstructWithSpread>::type;
DCHECK_EQ(ToRegister(function()), D::GetRegisterParameter(D::kTarget));
DCHECK_EQ(ToRegister(new_target()), D::GetRegisterParameter(D::kNewTarget));
DCHECK_EQ(ToRegister(context()), kContextRegister);
// Push other arguments (other than the spread) to the stack.
int argc_no_spread = num_args() - 1;
for (int i = argc_no_spread - 1; i >= 0; --i) {
PushInput(code_gen_state, arg(i));
}
__ Move(D::GetRegisterParameter(D::kActualArgumentsCount),
Immediate(argc_no_spread));
__ CallBuiltin(Builtin::kConstructWithSpread);
code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info());
}
void IncreaseInterruptBudget::AllocateVreg(
MaglevVregAllocationState* vreg_state) {
set_temporaries_needed(1);
......
......@@ -120,7 +120,9 @@ class CompactInterpreterFrameState;
V(Call) \
V(CallBuiltin) \
V(CallRuntime) \
V(CallWithSpread) \
V(Construct) \
V(ConstructWithSpread) \
V(CreateEmptyArrayLiteral) \
V(CreateArrayLiteral) \
V(CreateShallowArrayLiteral) \
......@@ -2951,6 +2953,87 @@ class CallRuntime : public ValueNodeT<CallRuntime> {
Runtime::FunctionId function_id_;
};
class CallWithSpread : public ValueNodeT<CallWithSpread> {
using Base = ValueNodeT<CallWithSpread>;
public:
// We assume function and context as fixed inputs.
static constexpr int kFunctionIndex = 0;
static constexpr int kContextIndex = 1;
static constexpr int kFixedInputCount = 2;
// This ctor is used when for variable input counts.
// Inputs must be initialized manually.
CallWithSpread(uint64_t bitfield, ValueNode* function, ValueNode* context)
: Base(bitfield) {
set_input(kFunctionIndex, function);
set_input(kContextIndex, context);
}
static constexpr OpProperties kProperties = OpProperties::JSCall();
Input& function() { return input(kFunctionIndex); }
const Input& function() const { return input(kFunctionIndex); }
Input& context() { return input(kContextIndex); }
const Input& context() const { return input(kContextIndex); }
int num_args() const { return input_count() - kFixedInputCount; }
Input& arg(int i) { return input(i + kFixedInputCount); }
void set_arg(int i, ValueNode* node) {
set_input(i + kFixedInputCount, node);
}
Input& spread() {
// Spread is the last argument/input.
return input(input_count() - 1);
}
void AllocateVreg(MaglevVregAllocationState*);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
};
class ConstructWithSpread : public ValueNodeT<ConstructWithSpread> {
using Base = ValueNodeT<ConstructWithSpread>;
public:
// We assume function and context as fixed inputs.
static constexpr int kFunctionIndex = 0;
static constexpr int kNewTargetIndex = 1;
static constexpr int kContextIndex = 2;
static constexpr int kFixedInputCount = 3;
// This ctor is used when for variable input counts.
// Inputs must be initialized manually.
ConstructWithSpread(uint64_t bitfield, ValueNode* function,
ValueNode* new_target, ValueNode* context)
: Base(bitfield) {
set_input(kFunctionIndex, function);
set_input(kNewTargetIndex, new_target);
set_input(kContextIndex, context);
}
static constexpr OpProperties kProperties = OpProperties::JSCall();
Input& function() { return input(kFunctionIndex); }
const Input& function() const { return input(kFunctionIndex); }
Input& new_target() { return input(kNewTargetIndex); }
const Input& new_target() const { return input(kNewTargetIndex); }
Input& context() { return input(kContextIndex); }
const Input& context() const { return input(kContextIndex); }
int num_args() const { return input_count() - kFixedInputCount; }
Input& arg(int i) { return input(i + kFixedInputCount); }
void set_arg(int i, ValueNode* node) {
set_input(i + kFixedInputCount, node);
}
Input& spread() {
// Spread is the last argument/input.
return input(input_count() - 1);
}
void AllocateVreg(MaglevVregAllocationState*);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
};
class IncreaseInterruptBudget
: public FixedInputNodeT<0, IncreaseInterruptBudget> {
using Base = FixedInputNodeT<0, IncreaseInterruptBudget>;
......
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