[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}
This commit is contained in:
parent
39f083f59a
commit
2301473a88
@ -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), _, _), _));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user