[Turbofan] Add CallFunctionWithSpread JSOperator.
Add the operator in preparation for actual perf work. The operator is replaced by the same runtime call as before, during lowering. BUG=v8:5511 Review-Url: https://codereview.chromium.org/2639233002 Cr-Commit-Position: refs/heads/master@{#42593}
This commit is contained in:
parent
68289fd9f5
commit
53a887e4c6
@ -1273,6 +1273,16 @@ void BytecodeGraphBuilder::VisitCall() {
|
||||
BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kAny);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitCallWithSpread() {
|
||||
PrepareEagerCheckpoint();
|
||||
interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(0);
|
||||
size_t arg_count = bytecode_iterator().GetRegisterCountOperand(1);
|
||||
const Operator* op =
|
||||
javascript()->CallFunctionWithSpread(static_cast<int>(arg_count));
|
||||
Node* value = ProcessCallRuntimeArguments(op, first_arg, arg_count);
|
||||
environment()->BindAccumulator(value, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitCallProperty() {
|
||||
BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNotNullOrUndefined);
|
||||
}
|
||||
@ -1353,16 +1363,6 @@ Node* BytecodeGraphBuilder::ProcessCallNewWithSpreadArguments(
|
||||
return value;
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitCallWithSpread() {
|
||||
PrepareEagerCheckpoint();
|
||||
interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(0);
|
||||
size_t arg_count = bytecode_iterator().GetRegisterCountOperand(1);
|
||||
const Operator* call =
|
||||
javascript()->CallRuntime(Runtime::kCallWithSpread, arg_count);
|
||||
Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count);
|
||||
environment()->BindAccumulator(value, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitNewWithSpread() {
|
||||
PrepareEagerCheckpoint();
|
||||
interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
|
||||
|
@ -548,6 +548,12 @@ void JSGenericLowering::LowerJSCallFunction(Node* node) {
|
||||
NodeProperties::ChangeOp(node, common()->Call(desc));
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSCallFunctionWithSpread(Node* node) {
|
||||
CallFunctionWithSpreadParameters const& p =
|
||||
CallFunctionWithSpreadParametersOf(node->op());
|
||||
ReplaceWithRuntimeCall(node, Runtime::kCallWithSpread,
|
||||
static_cast<int>(p.arity()));
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSCallRuntime(Node* node) {
|
||||
const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
|
||||
|
@ -118,6 +118,30 @@ const CallFunctionParameters& CallFunctionParametersOf(const Operator* op) {
|
||||
return OpParameter<CallFunctionParameters>(op);
|
||||
}
|
||||
|
||||
bool operator==(CallFunctionWithSpreadParameters const& lhs,
|
||||
CallFunctionWithSpreadParameters const& rhs) {
|
||||
return lhs.arity() == rhs.arity();
|
||||
}
|
||||
|
||||
bool operator!=(CallFunctionWithSpreadParameters const& lhs,
|
||||
CallFunctionWithSpreadParameters const& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
size_t hash_value(CallFunctionWithSpreadParameters const& p) {
|
||||
return base::hash_combine(p.arity());
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os,
|
||||
CallFunctionWithSpreadParameters const& p) {
|
||||
return os << p.arity();
|
||||
}
|
||||
|
||||
CallFunctionWithSpreadParameters const& CallFunctionWithSpreadParametersOf(
|
||||
Operator const* op) {
|
||||
DCHECK_EQ(IrOpcode::kJSCallFunctionWithSpread, op->opcode());
|
||||
return OpParameter<CallFunctionWithSpreadParameters>(op);
|
||||
}
|
||||
|
||||
bool operator==(CallRuntimeParameters const& lhs,
|
||||
CallRuntimeParameters const& rhs) {
|
||||
@ -712,6 +736,14 @@ const Operator* JSOperatorBuilder::CallFunction(
|
||||
parameters); // parameter
|
||||
}
|
||||
|
||||
const Operator* JSOperatorBuilder::CallFunctionWithSpread(uint32_t arity) {
|
||||
CallFunctionWithSpreadParameters parameters(arity);
|
||||
return new (zone()) Operator1<CallFunctionWithSpreadParameters>( // --
|
||||
IrOpcode::kJSCallFunctionWithSpread, Operator::kNoProperties, // opcode
|
||||
"JSCallFunctionWithSpread", // name
|
||||
parameters.arity(), 1, 1, 1, 1, 2, // counts
|
||||
parameters); // parameter
|
||||
}
|
||||
|
||||
const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id) {
|
||||
const Runtime::Function* f = Runtime::FunctionForId(id);
|
||||
|
@ -159,6 +159,31 @@ std::ostream& operator<<(std::ostream&, CallFunctionParameters const&);
|
||||
|
||||
const CallFunctionParameters& CallFunctionParametersOf(const Operator* op);
|
||||
|
||||
// Defines the arity for a JavaScript constructor call with a spread as the last
|
||||
// parameters. This is used as a parameter by JSCallConstructWithSpread
|
||||
// operators.
|
||||
class CallFunctionWithSpreadParameters final {
|
||||
public:
|
||||
explicit CallFunctionWithSpreadParameters(uint32_t arity) : arity_(arity) {}
|
||||
|
||||
uint32_t arity() const { return arity_; }
|
||||
|
||||
private:
|
||||
uint32_t const arity_;
|
||||
};
|
||||
|
||||
bool operator==(CallFunctionWithSpreadParameters const&,
|
||||
CallFunctionWithSpreadParameters const&);
|
||||
bool operator!=(CallFunctionWithSpreadParameters const&,
|
||||
CallFunctionWithSpreadParameters const&);
|
||||
|
||||
size_t hash_value(CallFunctionWithSpreadParameters const&);
|
||||
|
||||
std::ostream& operator<<(std::ostream&,
|
||||
CallFunctionWithSpreadParameters const&);
|
||||
|
||||
CallFunctionWithSpreadParameters const& CallFunctionWithSpreadParametersOf(
|
||||
Operator const*);
|
||||
|
||||
// Defines the arity and the ID for a runtime function call. This is used as a
|
||||
// parameter by JSCallRuntime operators.
|
||||
@ -552,6 +577,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
|
||||
VectorSlotPair const& feedback = VectorSlotPair(),
|
||||
ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny,
|
||||
TailCallMode tail_call_mode = TailCallMode::kDisallow);
|
||||
const Operator* CallFunctionWithSpread(uint32_t arity);
|
||||
const Operator* CallRuntime(Runtime::FunctionId id);
|
||||
const Operator* CallRuntime(Runtime::FunctionId id, size_t arity);
|
||||
const Operator* CallRuntime(const Runtime::Function* function, size_t arity);
|
||||
|
@ -161,6 +161,7 @@
|
||||
V(JSCallConstruct) \
|
||||
V(JSCallConstructWithSpread) \
|
||||
V(JSCallFunction) \
|
||||
V(JSCallFunctionWithSpread) \
|
||||
V(JSCallRuntime) \
|
||||
V(JSConvertReceiver) \
|
||||
V(JSForInNext) \
|
||||
|
@ -96,6 +96,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) {
|
||||
case IrOpcode::kJSCallConstruct:
|
||||
case IrOpcode::kJSCallConstructWithSpread:
|
||||
case IrOpcode::kJSCallFunction:
|
||||
case IrOpcode::kJSCallFunctionWithSpread:
|
||||
|
||||
// Misc operations
|
||||
case IrOpcode::kJSConvertReceiver:
|
||||
|
@ -1582,6 +1582,9 @@ Type* Typer::Visitor::TypeJSCallFunction(Node* node) {
|
||||
return TypeUnaryOp(node, JSCallFunctionTyper);
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeJSCallFunctionWithSpread(Node* node) {
|
||||
return TypeUnaryOp(node, JSCallFunctionTyper);
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeJSCallRuntime(Node* node) {
|
||||
switch (CallRuntimeParametersOf(node->op()).id()) {
|
||||
|
@ -681,6 +681,7 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
CheckTypeIs(node, Type::Receiver());
|
||||
break;
|
||||
case IrOpcode::kJSCallFunction:
|
||||
case IrOpcode::kJSCallFunctionWithSpread:
|
||||
case IrOpcode::kJSCallRuntime:
|
||||
// Type can be anything.
|
||||
CheckTypeIs(node, Type::Any());
|
||||
|
Loading…
Reference in New Issue
Block a user