[turbofan] Make new.target explicit in JSCallDescriptor.
This adds an explicit parameter to the call descriptor having kind kJSCallFunction representing the new.target value. Note that for now this parameter is not yet passed in and hence cannot be used yet. Also contains some refactoring of how parameter index value are calculated, establishing Linkage as the central point for such index computations. This is a preparatory CL to allows us passing new.target in a register instead of via a side-channel through the construct stub frame. R=bmeurer@chromium.org BUG=v8:4544 LOG=n Review URL: https://codereview.chromium.org/1461973002 Cr-Commit-Position: refs/heads/master@{#32112}
This commit is contained in:
parent
dad635ee7a
commit
0227857d26
@ -24,6 +24,7 @@ const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r5};
|
|||||||
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r6};
|
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r6};
|
||||||
const Register kInterpreterDispatchTableRegister = {Register::kCode_r8};
|
const Register kInterpreterDispatchTableRegister = {Register::kCode_r8};
|
||||||
const Register kJavaScriptCallArgCountRegister = {Register::kCode_r0};
|
const Register kJavaScriptCallArgCountRegister = {Register::kCode_r0};
|
||||||
|
const Register kJavaScriptCallNewTargetRegister = {Register::kCode_r3};
|
||||||
const Register kRuntimeCallFunctionRegister = {Register::kCode_r1};
|
const Register kRuntimeCallFunctionRegister = {Register::kCode_r1};
|
||||||
const Register kRuntimeCallArgCountRegister = {Register::kCode_r0};
|
const Register kRuntimeCallArgCountRegister = {Register::kCode_r0};
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ namespace internal {
|
|||||||
#define kInterpreterBytecodeArrayRegister x20
|
#define kInterpreterBytecodeArrayRegister x20
|
||||||
#define kInterpreterDispatchTableRegister x21
|
#define kInterpreterDispatchTableRegister x21
|
||||||
#define kJavaScriptCallArgCountRegister x0
|
#define kJavaScriptCallArgCountRegister x0
|
||||||
|
#define kJavaScriptCallNewTargetRegister x3
|
||||||
#define kRuntimeCallFunctionRegister x1
|
#define kRuntimeCallFunctionRegister x1
|
||||||
#define kRuntimeCallArgCountRegister x0
|
#define kRuntimeCallArgCountRegister x0
|
||||||
|
|
||||||
|
@ -472,8 +472,8 @@ Node* AstGraphBuilder::GetFunctionClosureForContext() {
|
|||||||
|
|
||||||
Node* AstGraphBuilder::GetFunctionClosure() {
|
Node* AstGraphBuilder::GetFunctionClosure() {
|
||||||
if (!function_closure_.is_set()) {
|
if (!function_closure_.is_set()) {
|
||||||
const Operator* op = common()->Parameter(
|
int index = Linkage::kJSCallClosureParamIndex;
|
||||||
Linkage::kJSFunctionCallClosureParamIndex, "%closure");
|
const Operator* op = common()->Parameter(index, "%closure");
|
||||||
Node* node = NewNode(op, graph()->start());
|
Node* node = NewNode(op, graph()->start());
|
||||||
function_closure_.set(node);
|
function_closure_.set(node);
|
||||||
}
|
}
|
||||||
@ -483,9 +483,9 @@ Node* AstGraphBuilder::GetFunctionClosure() {
|
|||||||
|
|
||||||
Node* AstGraphBuilder::GetFunctionContext() {
|
Node* AstGraphBuilder::GetFunctionContext() {
|
||||||
if (!function_context_.is_set()) {
|
if (!function_context_.is_set()) {
|
||||||
// Parameter (arity + 2) is special for the outer context of the function
|
int params = info()->num_parameters_including_this();
|
||||||
const Operator* op = common()->Parameter(
|
int index = Linkage::GetJSCallContextParamIndex(params);
|
||||||
info()->num_parameters_including_this() + 1, "%context");
|
const Operator* op = common()->Parameter(index, "%context");
|
||||||
Node* node = NewNode(op, graph()->start());
|
Node* node = NewNode(op, graph()->start());
|
||||||
function_context_.set(node);
|
function_context_.set(node);
|
||||||
}
|
}
|
||||||
@ -498,9 +498,9 @@ bool AstGraphBuilder::CreateGraph(bool stack_check) {
|
|||||||
DCHECK(graph() != NULL);
|
DCHECK(graph() != NULL);
|
||||||
|
|
||||||
// Set up the basic structure of the graph. Outputs for {Start} are the formal
|
// Set up the basic structure of the graph. Outputs for {Start} are the formal
|
||||||
// parameters (including the receiver) plus number of arguments, context and
|
// parameters (including the receiver) plus new target, number of arguments,
|
||||||
// closure.
|
// context and closure.
|
||||||
int actual_parameter_count = info()->num_parameters_including_this() + 3;
|
int actual_parameter_count = info()->num_parameters_including_this() + 4;
|
||||||
graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
|
graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
|
||||||
|
|
||||||
// Initialize the top-level environment.
|
// Initialize the top-level environment.
|
||||||
|
@ -113,9 +113,9 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
|
|||||||
|
|
||||||
Node* BytecodeGraphBuilder::GetFunctionContext() {
|
Node* BytecodeGraphBuilder::GetFunctionContext() {
|
||||||
if (!function_context_.is_set()) {
|
if (!function_context_.is_set()) {
|
||||||
// Parameter (arity + 1) is special for the outer context of the function
|
int params = bytecode_array()->parameter_count();
|
||||||
const Operator* op = common()->Parameter(
|
int index = Linkage::GetJSCallContextParamIndex(params);
|
||||||
bytecode_array()->parameter_count() + 1, "%context");
|
const Operator* op = common()->Parameter(index, "%context");
|
||||||
Node* node = NewNode(op, graph()->start());
|
Node* node = NewNode(op, graph()->start());
|
||||||
function_context_.set(node);
|
function_context_.set(node);
|
||||||
}
|
}
|
||||||
@ -125,8 +125,8 @@ Node* BytecodeGraphBuilder::GetFunctionContext() {
|
|||||||
|
|
||||||
Node* BytecodeGraphBuilder::GetFunctionClosure() {
|
Node* BytecodeGraphBuilder::GetFunctionClosure() {
|
||||||
if (!function_closure_.is_set()) {
|
if (!function_closure_.is_set()) {
|
||||||
const Operator* op = common()->Parameter(
|
int index = Linkage::kJSCallClosureParamIndex;
|
||||||
Linkage::kJSFunctionCallClosureParamIndex, "%closure");
|
const Operator* op = common()->Parameter(index, "%closure");
|
||||||
Node* node = NewNode(op, graph()->start());
|
Node* node = NewNode(op, graph()->start());
|
||||||
function_closure_.set(node);
|
function_closure_.set(node);
|
||||||
}
|
}
|
||||||
@ -180,9 +180,9 @@ bool BytecodeGraphBuilder::CreateGraph(bool stack_check) {
|
|||||||
// closure.
|
// closure.
|
||||||
|
|
||||||
// Set up the basic structure of the graph. Outputs for {Start} are the formal
|
// Set up the basic structure of the graph. Outputs for {Start} are the formal
|
||||||
// parameters (including the receiver) plus number of arguments, context and
|
// parameters (including the receiver) plus new target, number of arguments,
|
||||||
// closure.
|
// context and closure.
|
||||||
int actual_parameter_count = bytecode_array()->parameter_count() + 3;
|
int actual_parameter_count = bytecode_array()->parameter_count() + 4;
|
||||||
graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
|
graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
|
||||||
|
|
||||||
Environment env(this, bytecode_array()->register_count(),
|
Environment env(this, bytecode_array()->register_count(),
|
||||||
|
@ -49,13 +49,14 @@ Reduction JSFrameSpecialization::ReduceParameter(Node* node) {
|
|||||||
Object* object;
|
Object* object;
|
||||||
int const index = ParameterIndexOf(node->op());
|
int const index = ParameterIndexOf(node->op());
|
||||||
int const parameters_count = frame()->ComputeParametersCount() + 1;
|
int const parameters_count = frame()->ComputeParametersCount() + 1;
|
||||||
if (index == Linkage::kJSFunctionCallClosureParamIndex) {
|
if (index == Linkage::kJSCallClosureParamIndex) {
|
||||||
|
// The Parameter index references the closure.
|
||||||
object = frame()->function();
|
object = frame()->function();
|
||||||
} else if (index == parameters_count) {
|
} else if (index == Linkage::GetJSCallArgCountParamIndex(parameters_count)) {
|
||||||
// The Parameter index (arity + 1) is the parameter count.
|
// The Parameter index references the parameter count.
|
||||||
object = Smi::FromInt(parameters_count - 1);
|
object = Smi::FromInt(parameters_count - 1);
|
||||||
} else if (index == parameters_count + 1) {
|
} else if (index == Linkage::GetJSCallContextParamIndex(parameters_count)) {
|
||||||
// The Parameter index (arity + 2) is the context.
|
// The Parameter index references the context.
|
||||||
object = frame()->context();
|
object = frame()->context();
|
||||||
} else {
|
} else {
|
||||||
// The Parameter index 0 is the receiver.
|
// The Parameter index 0 is the receiver.
|
||||||
|
@ -133,22 +133,23 @@ class CopyVisitor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Reduction JSInliner::InlineCall(Node* call, Node* context, Node* frame_state,
|
Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context,
|
||||||
Node* start, Node* end) {
|
Node* frame_state, Node* start, Node* end) {
|
||||||
// The scheduler is smart enough to place our code; we just ensure {control}
|
// The scheduler is smart enough to place our code; we just ensure {control}
|
||||||
// becomes the control input of the start of the inlinee, and {effect} becomes
|
// becomes the control input of the start of the inlinee, and {effect} becomes
|
||||||
// the effect input of the start of the inlinee.
|
// the effect input of the start of the inlinee.
|
||||||
Node* control = NodeProperties::GetControlInput(call);
|
Node* control = NodeProperties::GetControlInput(call);
|
||||||
Node* effect = NodeProperties::GetEffectInput(call);
|
Node* effect = NodeProperties::GetEffectInput(call);
|
||||||
|
|
||||||
|
int const inlinee_new_target_index =
|
||||||
|
static_cast<int>(start->op()->ValueOutputCount()) - 3;
|
||||||
int const inlinee_arity_index =
|
int const inlinee_arity_index =
|
||||||
static_cast<int>(start->op()->ValueOutputCount()) - 2;
|
static_cast<int>(start->op()->ValueOutputCount()) - 2;
|
||||||
// Context is last parameter.
|
|
||||||
int const inlinee_context_index =
|
int const inlinee_context_index =
|
||||||
static_cast<int>(start->op()->ValueOutputCount()) - 1;
|
static_cast<int>(start->op()->ValueOutputCount()) - 1;
|
||||||
|
|
||||||
// {inliner_inputs} counts JSFunction, Receiver, arguments, but not
|
// {inliner_inputs} counts JSFunction, receiver, arguments, but not
|
||||||
// context, effect, control.
|
// new target value, argument count, context, effect or control.
|
||||||
int inliner_inputs = call->op()->ValueInputCount();
|
int inliner_inputs = call->op()->ValueInputCount();
|
||||||
// Iterate over all uses of the start node.
|
// Iterate over all uses of the start node.
|
||||||
for (Edge edge : start->use_edges()) {
|
for (Edge edge : start->use_edges()) {
|
||||||
@ -157,10 +158,13 @@ Reduction JSInliner::InlineCall(Node* call, Node* context, Node* frame_state,
|
|||||||
case IrOpcode::kParameter: {
|
case IrOpcode::kParameter: {
|
||||||
int index = 1 + ParameterIndexOf(use->op());
|
int index = 1 + ParameterIndexOf(use->op());
|
||||||
DCHECK_LE(index, inlinee_context_index);
|
DCHECK_LE(index, inlinee_context_index);
|
||||||
if (index < inliner_inputs && index < inlinee_arity_index) {
|
if (index < inliner_inputs && index < inlinee_new_target_index) {
|
||||||
// There is an input from the call, and the index is a value
|
// There is an input from the call, and the index is a value
|
||||||
// projection but not the context, so rewire the input.
|
// projection but not the context, so rewire the input.
|
||||||
Replace(use, call->InputAt(index));
|
Replace(use, call->InputAt(index));
|
||||||
|
} else if (index == inlinee_new_target_index) {
|
||||||
|
// The projection is requesting the new target value.
|
||||||
|
Replace(use, new_target);
|
||||||
} else if (index == inlinee_arity_index) {
|
} else if (index == inlinee_arity_index) {
|
||||||
// The projection is requesting the number of arguments.
|
// The projection is requesting the number of arguments.
|
||||||
Replace(use, jsgraph_->Int32Constant(inliner_inputs - 2));
|
Replace(use, jsgraph_->Int32Constant(inliner_inputs - 2));
|
||||||
@ -409,6 +413,7 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
|
|||||||
Node* start = visitor.GetCopy(graph.start());
|
Node* start = visitor.GetCopy(graph.start());
|
||||||
Node* end = visitor.GetCopy(graph.end());
|
Node* end = visitor.GetCopy(graph.end());
|
||||||
Node* frame_state = call.frame_state_after();
|
Node* frame_state = call.frame_state_after();
|
||||||
|
Node* new_target = jsgraph_->UndefinedConstant();
|
||||||
|
|
||||||
// Insert nodes around the call that model the behavior required for a
|
// Insert nodes around the call that model the behavior required for a
|
||||||
// constructor dispatch and turn the constructor call into a regular call.
|
// constructor dispatch and turn the constructor call into a regular call.
|
||||||
@ -430,7 +435,8 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
|
|||||||
// Swizzle the inputs of the {JSCallConstruct} node to look like inputs to
|
// Swizzle the inputs of the {JSCallConstruct} node to look like inputs to
|
||||||
// any {JSCallFunction} node so that the rest of the inlining machinery
|
// any {JSCallFunction} node so that the rest of the inlining machinery
|
||||||
// behaves as if we were dealing with a regular function invocation.
|
// behaves as if we were dealing with a regular function invocation.
|
||||||
node->RemoveInput(call.formal_arguments() + 1); // Drop new.target.
|
new_target = call.new_target(); // Retrieve new target value input.
|
||||||
|
node->RemoveInput(call.formal_arguments() + 1); // Drop new target.
|
||||||
node->InsertInput(jsgraph_->graph()->zone(), 1, create);
|
node->InsertInput(jsgraph_->graph()->zone(), 1, create);
|
||||||
// Insert a check of the return value to determine whether the return value
|
// Insert a check of the return value to determine whether the return value
|
||||||
// or the implicit receiver should be selected as a result of the call.
|
// or the implicit receiver should be selected as a result of the call.
|
||||||
@ -474,16 +480,17 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert argument adaptor frame if required. The callees formal parameter
|
// Insert argument adaptor frame if required. The callees formal parameter
|
||||||
// count (i.e. value outputs of start node minus target, receiver, num args
|
// count (i.e. value outputs of start node minus target, receiver, new target,
|
||||||
// and context) have to match the number of arguments passed to the call.
|
// arguments count and context) have to match the number of arguments passed
|
||||||
DCHECK_EQ(parameter_count, start->op()->ValueOutputCount() - 4);
|
// to the call.
|
||||||
|
DCHECK_EQ(parameter_count, start->op()->ValueOutputCount() - 5);
|
||||||
if (call.formal_arguments() != parameter_count) {
|
if (call.formal_arguments() != parameter_count) {
|
||||||
frame_state = CreateArtificialFrameState(
|
frame_state = CreateArtificialFrameState(
|
||||||
node, frame_state, call.formal_arguments(),
|
node, frame_state, call.formal_arguments(),
|
||||||
FrameStateType::kArgumentsAdaptor, info.shared_info());
|
FrameStateType::kArgumentsAdaptor, info.shared_info());
|
||||||
}
|
}
|
||||||
|
|
||||||
return InlineCall(node, context, frame_state, start, end);
|
return InlineCall(node, new_target, context, frame_state, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
|
@ -45,8 +45,8 @@ class JSInliner final : public AdvancedReducer {
|
|||||||
FrameStateType frame_state_type,
|
FrameStateType frame_state_type,
|
||||||
Handle<SharedFunctionInfo> shared);
|
Handle<SharedFunctionInfo> shared);
|
||||||
|
|
||||||
Reduction InlineCall(Node* call, Node* context, Node* frame_state,
|
Reduction InlineCall(Node* call, Node* new_target, Node* context,
|
||||||
Node* start, Node* end);
|
Node* frame_state, Node* start, Node* end);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
|
@ -1820,9 +1820,11 @@ Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
|
|||||||
if (shared->internal_formal_parameter_count() == arity ||
|
if (shared->internal_formal_parameter_count() == arity ||
|
||||||
shared->internal_formal_parameter_count() ==
|
shared->internal_formal_parameter_count() ==
|
||||||
SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
|
SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
|
||||||
|
Node* new_target = jsgraph()->UndefinedConstant();
|
||||||
|
Node* argument_count = jsgraph()->Int32Constant(arity);
|
||||||
// Patch {node} to a direct call.
|
// Patch {node} to a direct call.
|
||||||
node->InsertInput(graph()->zone(), arity + 2,
|
node->InsertInput(graph()->zone(), arity + 2, new_target);
|
||||||
jsgraph()->Int32Constant(arity));
|
node->InsertInput(graph()->zone(), arity + 3, argument_count);
|
||||||
NodeProperties::ChangeOp(node,
|
NodeProperties::ChangeOp(node,
|
||||||
common()->Call(Linkage::GetJSCallDescriptor(
|
common()->Call(Linkage::GetJSCallDescriptor(
|
||||||
graph()->zone(), false, 1 + arity, flags)));
|
graph()->zone(), false, 1 + arity, flags)));
|
||||||
|
@ -339,9 +339,10 @@ CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
|
|||||||
CallDescriptor::Flags flags) {
|
CallDescriptor::Flags flags) {
|
||||||
const size_t return_count = 1;
|
const size_t return_count = 1;
|
||||||
const size_t context_count = 1;
|
const size_t context_count = 1;
|
||||||
|
const size_t new_target_count = 1;
|
||||||
const size_t num_args_count = 1;
|
const size_t num_args_count = 1;
|
||||||
const size_t parameter_count =
|
const size_t parameter_count =
|
||||||
js_parameter_count + num_args_count + context_count;
|
js_parameter_count + new_target_count + num_args_count + context_count;
|
||||||
|
|
||||||
LocationSignature::Builder locations(zone, return_count, parameter_count);
|
LocationSignature::Builder locations(zone, return_count, parameter_count);
|
||||||
MachineSignature::Builder types(zone, return_count, parameter_count);
|
MachineSignature::Builder types(zone, return_count, parameter_count);
|
||||||
@ -357,6 +358,10 @@ CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
|
|||||||
types.AddParam(kMachAnyTagged);
|
types.AddParam(kMachAnyTagged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add JavaScript call new target value.
|
||||||
|
locations.AddParam(regloc(kJavaScriptCallNewTargetRegister));
|
||||||
|
types.AddParam(kMachAnyTagged);
|
||||||
|
|
||||||
// Add JavaScript call argument count.
|
// Add JavaScript call argument count.
|
||||||
locations.AddParam(regloc(kJavaScriptCallArgCountRegister));
|
locations.AddParam(regloc(kJavaScriptCallArgCountRegister));
|
||||||
types.AddParam(kMachInt32);
|
types.AddParam(kMachInt32);
|
||||||
@ -508,8 +513,8 @@ LinkageLocation Linkage::GetOsrValueLocation(int index) const {
|
|||||||
if (index == kOsrContextSpillSlotIndex) {
|
if (index == kOsrContextSpillSlotIndex) {
|
||||||
// Context. Use the parameter location of the context spill slot.
|
// Context. Use the parameter location of the context spill slot.
|
||||||
// Parameter (arity + 2) is special for the context of the function frame.
|
// Parameter (arity + 2) is special for the context of the function frame.
|
||||||
int context_index =
|
// >> context_index = target + receiver + params + new_target + #args
|
||||||
1 + 1 + 1 + parameter_count; // target + receiver + params + #args
|
int context_index = 1 + 1 + parameter_count + 1 + 1;
|
||||||
return incoming_->GetInputLocation(context_index);
|
return incoming_->GetInputLocation(context_index);
|
||||||
} else if (index >= first_stack_slot) {
|
} else if (index >= first_stack_slot) {
|
||||||
// Local variable stored in this (callee) stack.
|
// Local variable stored in this (callee) stack.
|
||||||
|
@ -263,11 +263,11 @@ std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k);
|
|||||||
// Can be used to translate {arg_index} (i.e. index of the call node input) as
|
// Can be used to translate {arg_index} (i.e. index of the call node input) as
|
||||||
// well as {param_index} (i.e. as stored in parameter nodes) into an operator
|
// well as {param_index} (i.e. as stored in parameter nodes) into an operator
|
||||||
// representing the architecture-specific location. The following call node
|
// representing the architecture-specific location. The following call node
|
||||||
// layouts are supported (where {n} is the number value inputs):
|
// layouts are supported (where {n} is the number of value inputs):
|
||||||
//
|
//
|
||||||
// #0 #1 #2 #3 [...] #n
|
// #0 #1 #2 #3 [...] #n
|
||||||
// Call[CodeStub] code, arg 1, arg 2, arg 3, [...], context
|
// Call[CodeStub] code, arg 1, arg 2, arg 3, [...], context
|
||||||
// Call[JSFunction] function, rcvr, arg 1, arg 2, [...], #arg, context
|
// Call[JSFunction] function, rcvr, arg 1, arg 2, [...], new, #arg, context
|
||||||
// Call[Runtime] CEntryStub, arg 1, arg 2, arg 3, [...], fun, #arg, context
|
// Call[Runtime] CEntryStub, arg 1, arg 2, arg 3, [...], fun, #arg, context
|
||||||
class Linkage : public ZoneObject {
|
class Linkage : public ZoneObject {
|
||||||
public:
|
public:
|
||||||
@ -340,8 +340,23 @@ class Linkage : public ZoneObject {
|
|||||||
// Get the location where an incoming OSR value is stored.
|
// Get the location where an incoming OSR value is stored.
|
||||||
LinkageLocation GetOsrValueLocation(int index) const;
|
LinkageLocation GetOsrValueLocation(int index) const;
|
||||||
|
|
||||||
// A special parameter index for JSCalls that represents the closure.
|
// A special {Parameter} index for JSCalls that represents the new target.
|
||||||
static const int kJSFunctionCallClosureParamIndex = -1;
|
static int GetJSCallNewTargetParamIndex(int parameter_count) {
|
||||||
|
return parameter_count + 0; // Parameter (arity + 0) is special.
|
||||||
|
}
|
||||||
|
|
||||||
|
// A special {Parameter} index for JSCalls that represents the argument count.
|
||||||
|
static int GetJSCallArgCountParamIndex(int parameter_count) {
|
||||||
|
return parameter_count + 1; // Parameter (arity + 1) is special.
|
||||||
|
}
|
||||||
|
|
||||||
|
// A special {Parameter} index for JSCalls that represents the context.
|
||||||
|
static int GetJSCallContextParamIndex(int parameter_count) {
|
||||||
|
return parameter_count + 2; // Parameter (arity + 2) is special.
|
||||||
|
}
|
||||||
|
|
||||||
|
// A special {Parameter} index for JSCalls that represents the closure.
|
||||||
|
static const int kJSCallClosureParamIndex = -1;
|
||||||
|
|
||||||
// A special {OsrValue} index to indicate the context spill slot.
|
// A special {OsrValue} index to indicate the context spill slot.
|
||||||
static const int kOsrContextSpillSlotIndex = -1;
|
static const int kOsrContextSpillSlotIndex = -1;
|
||||||
|
@ -23,6 +23,7 @@ const Register kInterpreterRegisterFileRegister = {Register::kCode_edx};
|
|||||||
const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_ecx};
|
const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_ecx};
|
||||||
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_edi};
|
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_edi};
|
||||||
const Register kJavaScriptCallArgCountRegister = {Register::kCode_eax};
|
const Register kJavaScriptCallArgCountRegister = {Register::kCode_eax};
|
||||||
|
const Register kJavaScriptCallNewTargetRegister = {Register::kCode_edx};
|
||||||
const Register kRuntimeCallFunctionRegister = {Register::kCode_ebx};
|
const Register kRuntimeCallFunctionRegister = {Register::kCode_ebx};
|
||||||
const Register kRuntimeCallArgCountRegister = {Register::kCode_eax};
|
const Register kRuntimeCallArgCountRegister = {Register::kCode_eax};
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_t4};
|
|||||||
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_t5};
|
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_t5};
|
||||||
const Register kInterpreterDispatchTableRegister = {Register::kCode_t6};
|
const Register kInterpreterDispatchTableRegister = {Register::kCode_t6};
|
||||||
const Register kJavaScriptCallArgCountRegister = {Register::kCode_a0};
|
const Register kJavaScriptCallArgCountRegister = {Register::kCode_a0};
|
||||||
|
const Register kJavaScriptCallNewTargetRegister = {Register::kCode_a3};
|
||||||
const Register kRuntimeCallFunctionRegister = {Register::kCode_a1};
|
const Register kRuntimeCallFunctionRegister = {Register::kCode_a1};
|
||||||
const Register kRuntimeCallArgCountRegister = {Register::kCode_a0};
|
const Register kRuntimeCallArgCountRegister = {Register::kCode_a0};
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_t0};
|
|||||||
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_t1};
|
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_t1};
|
||||||
const Register kInterpreterDispatchTableRegister = {Register::kCode_t2};
|
const Register kInterpreterDispatchTableRegister = {Register::kCode_t2};
|
||||||
const Register kJavaScriptCallArgCountRegister = {Register::kCode_a0};
|
const Register kJavaScriptCallArgCountRegister = {Register::kCode_a0};
|
||||||
|
const Register kJavaScriptCallNewTargetRegister = {Register::kCode_a3};
|
||||||
const Register kRuntimeCallFunctionRegister = {Register::kCode_a1};
|
const Register kRuntimeCallFunctionRegister = {Register::kCode_a1};
|
||||||
const Register kRuntimeCallArgCountRegister = {Register::kCode_a0};
|
const Register kRuntimeCallArgCountRegister = {Register::kCode_a0};
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r15};
|
|||||||
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r16};
|
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r16};
|
||||||
const Register kInterpreterDispatchTableRegister = {Register::kCode_r17};
|
const Register kInterpreterDispatchTableRegister = {Register::kCode_r17};
|
||||||
const Register kJavaScriptCallArgCountRegister = {Register::kCode_r3};
|
const Register kJavaScriptCallArgCountRegister = {Register::kCode_r3};
|
||||||
|
const Register kJavaScriptCallNewTargetRegister = {Register::kCode_r6};
|
||||||
const Register kRuntimeCallFunctionRegister = {Register::kCode_r4};
|
const Register kRuntimeCallFunctionRegister = {Register::kCode_r4};
|
||||||
const Register kRuntimeCallArgCountRegister = {Register::kCode_r3};
|
const Register kRuntimeCallArgCountRegister = {Register::kCode_r3};
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r12};
|
|||||||
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r14};
|
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r14};
|
||||||
const Register kInterpreterDispatchTableRegister = {Register::kCode_r15};
|
const Register kInterpreterDispatchTableRegister = {Register::kCode_r15};
|
||||||
const Register kJavaScriptCallArgCountRegister = {Register::kCode_rax};
|
const Register kJavaScriptCallArgCountRegister = {Register::kCode_rax};
|
||||||
|
const Register kJavaScriptCallNewTargetRegister = {Register::kCode_rdx};
|
||||||
const Register kRuntimeCallFunctionRegister = {Register::kCode_rbx};
|
const Register kRuntimeCallFunctionRegister = {Register::kCode_rbx};
|
||||||
const Register kRuntimeCallArgCountRegister = {Register::kCode_rax};
|
const Register kRuntimeCallArgCountRegister = {Register::kCode_rax};
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ const Register kInterpreterRegisterFileRegister = {Register::kCode_edx};
|
|||||||
const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_ecx};
|
const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_ecx};
|
||||||
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_edi};
|
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_edi};
|
||||||
const Register kJavaScriptCallArgCountRegister = {Register::kCode_eax};
|
const Register kJavaScriptCallArgCountRegister = {Register::kCode_eax};
|
||||||
|
const Register kJavaScriptCallNewTargetRegister = {Register::kCode_edx};
|
||||||
const Register kRuntimeCallFunctionRegister = {Register::kCode_ebx};
|
const Register kRuntimeCallFunctionRegister = {Register::kCode_ebx};
|
||||||
const Register kRuntimeCallArgCountRegister = {Register::kCode_eax};
|
const Register kRuntimeCallArgCountRegister = {Register::kCode_eax};
|
||||||
|
|
||||||
|
@ -134,11 +134,11 @@ Matcher<Node*> BytecodeGraphBuilderTest::IsFeedbackVector(Node* effect,
|
|||||||
int offset = SharedFunctionInfo::kFeedbackVectorOffset - kHeapObjectTag;
|
int offset = SharedFunctionInfo::kFeedbackVectorOffset - kHeapObjectTag;
|
||||||
int offset1 = JSFunction::kSharedFunctionInfoOffset - kHeapObjectTag;
|
int offset1 = JSFunction::kSharedFunctionInfoOffset - kHeapObjectTag;
|
||||||
|
|
||||||
return IsLoad(kMachAnyTagged,
|
return IsLoad(
|
||||||
IsLoad(kMachAnyTagged,
|
kMachAnyTagged,
|
||||||
IsParameter(Linkage::kJSFunctionCallClosureParamIndex),
|
IsLoad(kMachAnyTagged, IsParameter(Linkage::kJSCallClosureParamIndex),
|
||||||
IsIntPtrConstant(offset1), effect, control),
|
IsIntPtrConstant(offset1), effect, control),
|
||||||
IsIntPtrConstant(offset), effect, control);
|
IsIntPtrConstant(offset), effect, control);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
|
|||||||
m.UndefinedConstant());
|
m.UndefinedConstant());
|
||||||
|
|
||||||
// Build the call.
|
// Build the call.
|
||||||
Node* args[] = {receiver, m.Int32Constant(1), context};
|
Node* args[] = {receiver, m.UndefinedConstant(), m.Int32Constant(1), context};
|
||||||
Node* call =
|
Node* call =
|
||||||
m.CallNWithFrameState(descriptor, function_node, args, state_node);
|
m.CallNWithFrameState(descriptor, function_node, args, state_node);
|
||||||
m.Return(call);
|
m.Return(call);
|
||||||
|
Loading…
Reference in New Issue
Block a user