Commit 2301473a authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Slighly improve JSCreateArguments lowering.

Make JSCreateArguments eliminatable, and remove the need for frame
states on JSCreateArguments nodes being lowered to (optimized) stub
calls. Only the runtime fallback needs a frame state, because in that
case we need to ask the deoptimizer for arguments to inlined functions.

R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/1965013005
Cr-Commit-Position: refs/heads/master@{#36154}
parent 39f083f5
......@@ -280,6 +280,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
CreateArgumentsType type = CreateArgumentsTypeOf(node->op());
Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
Node* const control = graph()->start();
FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
// Use the ArgumentsAccessStub for materializing both mapped and unmapped
......@@ -293,38 +294,41 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
shared_info->has_duplicate_parameters()) {
return NoChange();
}
// TODO(bmeurer): Actually we don't need a frame state here.
Callable callable = CodeFactory::FastNewSloppyArguments(isolate());
Operator::Properties properties = node->op()->properties();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState);
CallDescriptor::kNoFlags, properties);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(graph()->zone(), 0, stub_code);
node->RemoveInput(3); // Remove the frame state.
NodeProperties::ChangeOp(node, new_op);
return Changed(node);
}
case CreateArgumentsType::kUnmappedArguments: {
// TODO(bmeurer): Actually we don't need a frame state here.
Callable callable = CodeFactory::FastNewStrictArguments(isolate());
Operator::Properties properties = node->op()->properties();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState);
CallDescriptor::kNoFlags, properties);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(graph()->zone(), 0, stub_code);
node->RemoveInput(3); // Remove the frame state.
NodeProperties::ChangeOp(node, new_op);
return Changed(node);
}
case CreateArgumentsType::kRestParameter: {
// TODO(bmeurer): Actually we don't need a frame state here.
Callable callable = CodeFactory::FastNewRestParameter(isolate());
Operator::Properties properties = node->op()->properties();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState);
CallDescriptor::kNoFlags, properties);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(graph()->zone(), 0, stub_code);
node->RemoveInput(3); // Remove the frame state.
NodeProperties::ChangeOp(node, new_op);
return Changed(node);
}
......@@ -337,7 +341,6 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
Handle<SharedFunctionInfo> shared;
if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
Node* const callee = NodeProperties::GetValueInput(node, 0);
Node* const control = NodeProperties::GetControlInput(node);
Node* const context = NodeProperties::GetContextInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
// TODO(mstarzinger): Duplicate parameters are not handled yet.
......@@ -378,7 +381,6 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
} else if (type == CreateArgumentsType::kUnmappedArguments) {
// Use inline allocation for all unmapped arguments objects within inlined
// (i.e. non-outermost) frames, independent of the object size.
Node* const control = NodeProperties::GetControlInput(node);
Node* const context = NodeProperties::GetContextInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
// Choose the correct frame state and frame state info depending on
......@@ -416,7 +418,6 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
int start_index = shared->internal_formal_parameter_count();
// Use inline allocation for all unmapped arguments objects within inlined
// (i.e. non-outermost) frames, independent of the object size.
Node* const control = NodeProperties::GetControlInput(node);
Node* const context = NodeProperties::GetContextInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
// Choose the correct frame state and frame state info depending on
......
......@@ -707,11 +707,11 @@ const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) {
const Operator* JSOperatorBuilder::CreateArguments(CreateArgumentsType type) {
return new (zone()) Operator1<CreateArgumentsType>( // --
IrOpcode::kJSCreateArguments, Operator::kNoThrow, // opcode
"JSCreateArguments", // name
1, 1, 1, 1, 1, 0, // counts
type); // parameter
return new (zone()) Operator1<CreateArgumentsType>( // --
IrOpcode::kJSCreateArguments, Operator::kEliminatable, // opcode
"JSCreateArguments", // name
1, 1, 0, 1, 1, 0, // counts
type); // parameter
}
......
......@@ -1164,7 +1164,8 @@ void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) const {
DisallowHeapAllocation no_gc;
int deopt_index = Safepoint::kNoDeoptimizationIndex;
DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
DCHECK(data != nullptr && deopt_index != Safepoint::kNoDeoptimizationIndex);
DCHECK_NOT_NULL(data);
DCHECK_NE(Safepoint::kNoDeoptimizationIndex, deopt_index);
FixedArray* const literal_array = data->LiteralArray();
TranslationIterator it(data->TranslationByteArray(),
......
......@@ -580,12 +580,6 @@ RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
Object** parameters = reinterpret_cast<Object**>(args[1]);
CONVERT_SMI_ARG_CHECKED(argument_count, 2);
#ifdef DEBUG
// This runtime function does not materialize the correct arguments when the
// caller has been inlined, better make sure we are not hitting that case.
JavaScriptFrameIterator it(isolate);
DCHECK(!it.frame()->HasInlinedFrames());
#endif // DEBUG
ParameterArguments argument_getter(parameters);
return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
}
......
......@@ -80,95 +80,56 @@ TEST_F(JSCreateLoweringTest, JSCreate) {
// -----------------------------------------------------------------------------
// JSCreateArguments
TEST_F(JSCreateLoweringTest, JSCreateArgumentsViaStub) {
Node* const closure = Parameter(Type::Any());
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Node* const control = graph()->start();
Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
Node* const frame_state = FrameState(shared, graph()->start());
Reduction r = Reduce(graph()->NewNode(
javascript()->CreateArguments(CreateArgumentsType::kUnmappedArguments),
closure, context, frame_state, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsCall(_, IsHeapConstant(
CodeFactory::FastNewStrictArguments(isolate()).code()),
closure, context, frame_state, effect, control));
}
TEST_F(JSCreateLoweringTest, JSCreateArgumentsRestParameterViaStub) {
Node* const closure = Parameter(Type::Any());
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Node* const control = graph()->start();
Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
Node* const frame_state = FrameState(shared, graph()->start());
Reduction r = Reduce(graph()->NewNode(
javascript()->CreateArguments(CreateArgumentsType::kRestParameter),
closure, context, frame_state, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsCall(_, IsHeapConstant(
CodeFactory::FastNewRestParameter(isolate()).code()),
closure, context, frame_state, effect, control));
}
TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedMapped) {
Node* const closure = Parameter(Type::Any());
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Node* const control = graph()->start();
Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
Node* const frame_state_outer = FrameState(shared, graph()->start());
Node* const frame_state_inner = FrameState(shared, frame_state_outer);
Reduction r = Reduce(graph()->NewNode(
javascript()->CreateArguments(CreateArgumentsType::kMappedArguments),
closure, context, frame_state_inner, effect, control));
closure, context, frame_state_inner, effect));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFinishRegion(
IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize),
_, control),
_));
EXPECT_THAT(
r.replacement(),
IsFinishRegion(
IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize), _, _),
_));
}
TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedUnmapped) {
Node* const closure = Parameter(Type::Any());
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Node* const control = graph()->start();
Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
Node* const frame_state_outer = FrameState(shared, graph()->start());
Node* const frame_state_inner = FrameState(shared, frame_state_outer);
Reduction r = Reduce(graph()->NewNode(
javascript()->CreateArguments(CreateArgumentsType::kUnmappedArguments),
closure, context, frame_state_inner, effect, control));
closure, context, frame_state_inner, effect));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFinishRegion(
IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize),
_, control),
_));
EXPECT_THAT(
r.replacement(),
IsFinishRegion(
IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize), _, _),
_));
}
TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedRestArray) {
Node* const closure = Parameter(Type::Any());
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Node* const control = graph()->start();
Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
Node* const frame_state_outer = FrameState(shared, graph()->start());
Node* const frame_state_inner = FrameState(shared, frame_state_outer);
Reduction r = Reduce(graph()->NewNode(
javascript()->CreateArguments(CreateArgumentsType::kRestParameter),
closure, context, frame_state_inner, effect, control));
closure, context, frame_state_inner, effect));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFinishRegion(
IsAllocate(IsNumberConstant(JSArray::kSize), _, control), _));
EXPECT_THAT(
r.replacement(),
IsFinishRegion(IsAllocate(IsNumberConstant(JSArray::kSize), _, _), _));
}
// -----------------------------------------------------------------------------
......
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