Commit 53a887e4 authored by petermarshall's avatar petermarshall Committed by Commit bot

[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}
parent 68289fd9
......@@ -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());
......
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