Commit 9b12ec9a authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Call ArgumentsAccessStub to materialize arguments.

This lowers JSCreateArgument nodes to call the ArgumentsAccessStub for
help with materializing arguments objects when possible. Along the way
this changes the calling convention of said stub to take parameters in
registers instead of on the stack.

R=mvstanton@chromium.org

Review URL: https://codereview.chromium.org/1348773002

Cr-Commit-Position: refs/heads/master@{#30919}
parent 347fa906
This diff is collapsed.
......@@ -60,6 +60,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return r1; }
const Register ArgumentsAccessReadDescriptor::parameter_count() { return r0; }
const Register ArgumentsAccessNewDescriptor::function() { return r1; }
const Register ArgumentsAccessNewDescriptor::parameter_count() { return r2; }
const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return r3; }
const Register ApiGetterDescriptor::function_address() { return r2; }
......
This diff is collapsed.
......@@ -60,6 +60,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return x1; }
const Register ArgumentsAccessReadDescriptor::parameter_count() { return x0; }
const Register ArgumentsAccessNewDescriptor::function() { return x1; }
const Register ArgumentsAccessNewDescriptor::parameter_count() { return x2; }
const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return x3; }
const Register ApiGetterDescriptor::function_address() { return x2; }
......
......@@ -235,6 +235,17 @@ Callable CodeFactory::FastNewClosure(Isolate* isolate,
}
// static
Callable CodeFactory::ArgumentsAccess(Isolate* isolate,
bool is_unmapped_arguments,
bool has_duplicate_parameters) {
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
is_unmapped_arguments, has_duplicate_parameters);
ArgumentsAccessStub stub(isolate, type);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::AllocateHeapNumber(Isolate* isolate) {
AllocateHeapNumberStub stub(isolate);
......
......@@ -88,6 +88,9 @@ class CodeFactory final {
static Callable FastNewClosure(Isolate* isolate, LanguageMode language_mode,
FunctionKind kind);
static Callable ArgumentsAccess(Isolate* isolate, bool is_unmapped_arguments,
bool has_duplicate_parameters);
static Callable AllocateHeapNumber(Isolate* isolate);
static Callable CallFunction(Isolate* isolate, int argc,
......
......@@ -1899,8 +1899,19 @@ class ArgumentsAccessStub: public PlatformCodeStub {
CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
if (type() == READ_ELEMENT) {
return ArgumentsAccessReadDescriptor(isolate());
} else {
return ArgumentsAccessNewDescriptor(isolate());
}
}
static Type ComputeType(bool is_unmapped, bool has_duplicate_parameters) {
if (is_unmapped) {
return Type::NEW_STRICT;
} else if (has_duplicate_parameters) {
return Type::NEW_SLOPPY_SLOW;
} else {
return Type::NEW_SLOPPY_FAST;
}
return ContextOnlyDescriptor(isolate());
}
private:
......
......@@ -1098,6 +1098,45 @@ Reduction JSTypedLowering::ReduceJSLoadDynamicContext(Node* node) {
}
Reduction JSTypedLowering::ReduceJSCreateArguments(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode());
CreateArgumentsParameters const& p = CreateArgumentsParametersOf(node->op());
Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
// Use the ArgumentsAccessStub for materializing both mapped and unmapped
// arguments object, but only for non-inlined (i.e. outermost) frames.
if (p.type() != CreateArgumentsParameters::kRestArray &&
outer_state->opcode() != IrOpcode::kFrameState) {
Handle<SharedFunctionInfo> shared;
Isolate* isolate = jsgraph()->isolate();
if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
bool unmapped = p.type() == CreateArgumentsParameters::kUnmappedArguments;
Callable callable = CodeFactory::ArgumentsAccess(
isolate, unmapped, shared->has_duplicate_parameters());
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate, graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState);
const Operator* new_op = common()->Call(desc);
int parameter_count = state_info.parameter_count() - 1;
int parameter_offset = parameter_count * kPointerSize;
int offset = StandardFrameConstants::kCallerSPOffset + parameter_offset;
Node* stub_code = jsgraph()->HeapConstant(callable.code());
Node* parameter_pointer = graph()->NewNode(
machine()->IntAdd(), graph()->NewNode(machine()->LoadFramePointer()),
jsgraph()->IntPtrConstant(offset));
node->InsertInput(graph()->zone(), 0, stub_code);
node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(parameter_count));
node->InsertInput(graph()->zone(), 3, parameter_pointer);
NodeProperties::ChangeOp(node, new_op);
return Changed(node);
}
return NoChange();
}
Reduction JSTypedLowering::ReduceJSCreateClosure(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
......@@ -1652,6 +1691,8 @@ Reduction JSTypedLowering::Reduce(Node* node) {
return ReduceJSLoadDynamicGlobal(node);
case IrOpcode::kJSLoadDynamicContext:
return ReduceJSLoadDynamicContext(node);
case IrOpcode::kJSCreateArguments:
return ReduceJSCreateArguments(node);
case IrOpcode::kJSCreateClosure:
return ReduceJSCreateClosure(node);
case IrOpcode::kJSCreateLiteralArray:
......
......@@ -57,6 +57,7 @@ class JSTypedLowering final : public AdvancedReducer {
Reduction ReduceJSToNumber(Node* node);
Reduction ReduceJSToStringInput(Node* input);
Reduction ReduceJSToString(Node* node);
Reduction ReduceJSCreateArguments(Node* node);
Reduction ReduceJSCreateClosure(Node* node);
Reduction ReduceJSCreateLiteralArray(Node* node);
Reduction ReduceJSCreateLiteralObject(Node* node);
......
......@@ -281,32 +281,26 @@ void FullCodeGenerator::Generate() {
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
DCHECK(r1.is(ArgumentsAccessNewDescriptor::function()));
if (!function_in_register_r1) {
// Load this again, if it's used by the local context below.
__ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
} else {
__ mov(r3, r1);
__ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
__ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset + offset));
__ mov(r1, Operand(Smi::FromInt(num_parameters)));
__ Push(r3, r2, r1);
__ mov(ArgumentsAccessNewDescriptor::parameter_count(),
Operand(Smi::FromInt(num_parameters)));
__ add(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
Operand(StandardFrameConstants::kCallerSPOffset + offset));
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::Type type;
if (is_strict(language_mode()) || !has_simple_parameters()) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (literal()->has_duplicate_parameters()) {
type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
} else {
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
// function, parameter pointer, parameter count.
// The stub will rewrite parameter pointer and parameter count if the
// previous stack frame was an arguments adapter frame.
bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
......
......@@ -289,31 +289,26 @@ void FullCodeGenerator::Generate() {
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
DCHECK(x1.is(ArgumentsAccessNewDescriptor::function()));
if (!function_in_register_x1) {
// Load this again, if it's used by the local context below.
__ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
} else {
__ Mov(x3, x1);
__ Ldr(x1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
__ Add(x2, fp, StandardFrameConstants::kCallerSPOffset + offset);
__ Mov(x1, Smi::FromInt(num_parameters));
__ Push(x3, x2, x1);
__ Mov(ArgumentsAccessNewDescriptor::parameter_count(),
Smi::FromInt(num_parameters));
__ Add(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
StandardFrameConstants::kCallerSPOffset + offset);
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::Type type;
if (is_strict(language_mode()) || !has_simple_parameters()) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (literal()->has_duplicate_parameters()) {
type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
} else {
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
// function, parameter pointer, parameter count.
// The stub will rewrite parameter pointer and parameter count if the
// previous stack frame was an arguments adapter frame.
bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
......
......@@ -283,31 +283,25 @@ void FullCodeGenerator::Generate() {
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
if (function_in_register) {
__ push(edi);
} else {
__ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
DCHECK(edi.is(ArgumentsAccessNewDescriptor::function()));
if (!function_in_register) {
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
__ lea(edx,
__ mov(ArgumentsAccessNewDescriptor::parameter_count(),
Immediate(Smi::FromInt(num_parameters)));
__ lea(ArgumentsAccessNewDescriptor::parameter_pointer(),
Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
__ push(edx);
__ push(Immediate(Smi::FromInt(num_parameters)));
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::Type type;
if (is_strict(language_mode()) || !has_simple_parameters()) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (literal()->has_duplicate_parameters()) {
type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
} else {
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
// Arguments to ArgumentsAccessStub:
// function, parameter pointer, parameter count.
// The stub will rewrite parameter pointer and parameter count if the
// previous stack frame was an arguments adapter frame.
bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
......
......@@ -299,32 +299,26 @@ void FullCodeGenerator::Generate() {
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
if (!function_in_register_a1) {
// Load this again, if it's used by the local context below.
__ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
} else {
__ mov(a3, a1);
__ lw(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
__ Addu(a2, fp,
Operand(StandardFrameConstants::kCallerSPOffset + offset));
__ li(a1, Operand(Smi::FromInt(num_parameters)));
__ Push(a3, a2, a1);
__ li(ArgumentsAccessNewDescriptor::parameter_count(),
Operand(Smi::FromInt(num_parameters)));
__ Addu(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
Operand(StandardFrameConstants::kCallerSPOffset + offset));
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiever and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::Type type;
if (is_strict(language_mode()) || !has_simple_parameters()) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (literal()->has_duplicate_parameters()) {
type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
} else {
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
// function, parameter pointer, parameter count.
// The stub will rewrite parameter pointer and parameter count if the
// previous stack frame was an arguments adapter frame.
bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
......
......@@ -295,32 +295,26 @@ void FullCodeGenerator::Generate() {
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
if (!function_in_register_a1) {
// Load this again, if it's used by the local context below.
__ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
} else {
__ mov(a3, a1);
__ ld(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
__ Daddu(a2, fp,
Operand(StandardFrameConstants::kCallerSPOffset + offset));
__ li(a1, Operand(Smi::FromInt(num_parameters)));
__ Push(a3, a2, a1);
__ li(ArgumentsAccessNewDescriptor::parameter_count(),
Operand(Smi::FromInt(num_parameters)));
__ Daddu(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
Operand(StandardFrameConstants::kCallerSPOffset + offset));
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiever and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::Type type;
if (is_strict(language_mode()) || !has_simple_parameters()) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (literal()->has_duplicate_parameters()) {
type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
} else {
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
// function, parameter pointer, parameter count.
// The stub will rewrite parameter pointer and parameter count if the
// previous stack frame was an arguments adapter frame.
bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
......
......@@ -281,31 +281,25 @@ void FullCodeGenerator::Generate() {
// Arguments object must be allocated after the context object, in
// case the "arguments" or ".arguments" variables are in the context.
Comment cmnt(masm_, "[ Allocate arguments object");
if (function_in_register) {
__ Push(rdi);
} else {
__ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function()));
if (!function_in_register) {
__ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
}
// The receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
__ leap(rdx,
Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
__ Push(rdx);
__ Push(Smi::FromInt(num_parameters));
__ Move(ArgumentsAccessNewDescriptor::parameter_count(),
Smi::FromInt(num_parameters));
__ leap(ArgumentsAccessNewDescriptor::parameter_pointer(),
Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::Type type;
if (is_strict(language_mode()) || !has_simple_parameters()) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (literal()->has_duplicate_parameters()) {
type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
} else {
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
// function, parameter pointer, parameter count.
// The stub will rewrite parameter pointer and parameter count if the
// previous stack frame was an arguments adapter frame.
bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
......
This diff is collapsed.
......@@ -65,6 +65,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return edx; }
const Register ArgumentsAccessReadDescriptor::parameter_count() { return eax; }
const Register ArgumentsAccessNewDescriptor::function() { return edi; }
const Register ArgumentsAccessNewDescriptor::parameter_count() { return ecx; }
const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return edx; }
const Register ApiGetterDescriptor::function_address() { return edx; }
......
......@@ -310,6 +310,26 @@ void ArgumentsAccessReadDescriptor::InitializePlatformSpecific(
}
Type::FunctionType*
ArgumentsAccessNewDescriptor::BuildCallInterfaceDescriptorFunctionType(
Isolate* isolate, int paramater_count) {
Zone* zone = isolate->interface_descriptor_zone();
Type::FunctionType* function =
Type::FunctionType::New(AnyTagged(zone), Type::Undefined(), 3, zone);
function->InitParameter(0, AnyTagged(zone));
function->InitParameter(1, SmiType(zone));
function->InitParameter(2, ExternalPointer(zone));
return function;
}
void ArgumentsAccessNewDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {function(), parameter_count(), parameter_pointer()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ContextOnlyDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
data->InitializePlatformSpecific(0, nullptr);
......
......@@ -61,6 +61,7 @@ class PlatformInterfaceDescriptor;
V(ApiAccessor) \
V(ApiGetter) \
V(ArgumentsAccessRead) \
V(ArgumentsAccessNew) \
V(StoreArrayLiteralElement) \
V(LoadGlobalViaContext) \
V(StoreGlobalViaContext) \
......@@ -638,6 +639,17 @@ class ArgumentsAccessReadDescriptor : public CallInterfaceDescriptor {
};
class ArgumentsAccessNewDescriptor : public CallInterfaceDescriptor {
public:
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArgumentsAccessNewDescriptor,
CallInterfaceDescriptor)
static const Register function();
static const Register parameter_count();
static const Register parameter_pointer();
};
class StoreArrayLiteralElementDescriptor : public CallInterfaceDescriptor {
public:
DECLARE_DESCRIPTOR(StoreArrayLiteralElementDescriptor,
......
This diff is collapsed.
......@@ -58,6 +58,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return a1; }
const Register ArgumentsAccessReadDescriptor::parameter_count() { return a0; }
const Register ArgumentsAccessNewDescriptor::function() { return a1; }
const Register ArgumentsAccessNewDescriptor::parameter_count() { return a2; }
const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return a3; }
const Register ApiGetterDescriptor::function_address() { return a2; }
......
This diff is collapsed.
......@@ -58,6 +58,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return a1; }
const Register ArgumentsAccessReadDescriptor::parameter_count() { return a0; }
const Register ArgumentsAccessNewDescriptor::function() { return a1; }
const Register ArgumentsAccessNewDescriptor::parameter_count() { return a2; }
const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return a3; }
const Register ApiGetterDescriptor::function_address() { return a2; }
......
This diff is collapsed.
......@@ -58,6 +58,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return rdx; }
const Register ArgumentsAccessReadDescriptor::parameter_count() { return rax; }
const Register ArgumentsAccessNewDescriptor::function() { return rdi; }
const Register ArgumentsAccessNewDescriptor::parameter_count() { return rcx; }
const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return rdx; }
const Register ApiGetterDescriptor::function_address() { return r8; }
......
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