Commit 864b07e9 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Remove eager frame state from call nodes.

This removes the frame state input representing the before-state from
nodes having the {JSCallFunction} or {JSCallConstruct} operator. These
frame states can by now be found via checkpoints in the graph.

R=bmeurer@chromium.org
BUG=v8:5021

Review-Url: https://codereview.chromium.org/2025573003
Cr-Commit-Position: refs/heads/master@{#36669}
parent 5a3a6daf
......@@ -71,7 +71,6 @@ Reduction JSCallReducer::ReduceArrayConstructor(Node* node) {
size_t const arity = p.arity() - 2;
NodeProperties::ReplaceValueInput(node, target, 0);
NodeProperties::ReplaceValueInput(node, target, 1);
NodeProperties::RemoveFrameStateInput(node, 1);
// TODO(bmeurer): We might need to propagate the tail call mode to
// the JSCreateArray operator, because an Array call in tail call
// position must always properly consume the parent stack frame.
......@@ -89,7 +88,6 @@ Reduction JSCallReducer::ReduceNumberConstructor(Node* node) {
DCHECK_LE(2u, p.arity());
Node* value = (p.arity() == 2) ? jsgraph()->ZeroConstant()
: NodeProperties::GetValueInput(node, 2);
NodeProperties::RemoveFrameStateInput(node, 1);
NodeProperties::ReplaceValueInputs(node, value);
NodeProperties::ChangeOp(node, javascript()->ToNumber());
return Changed(node);
......@@ -220,9 +218,9 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
Node* target = NodeProperties::GetValueInput(node, 0);
Node* context = NodeProperties::GetContextInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
Node* control = NodeProperties::GetControlInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* frame_state = NodeProperties::FindFrameStateBefore(node);
// Try to specialize JSCallFunction {node}s with constant {target}s.
HeapObjectMatcher m(target);
......@@ -233,7 +231,6 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
// Raise a TypeError if the {target} is a "classConstructor".
if (IsClassConstructor(shared->kind())) {
NodeProperties::RemoveFrameStateInput(node, 0);
NodeProperties::ReplaceValueInputs(node, target);
NodeProperties::ChangeOp(
node, javascript()->CallRuntime(
......@@ -370,9 +367,9 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
Node* target = NodeProperties::GetValueInput(node, 0);
Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
Node* context = NodeProperties::GetContextInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* frame_state = NodeProperties::FindFrameStateBefore(node);
// Try to specialize JSCallConstruct {node}s with constant {target}s.
HeapObjectMatcher m(target);
......@@ -382,11 +379,6 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
// Raise a TypeError if the {target} is not a constructor.
if (!function->IsConstructor()) {
// Drop the lazy bailout location and use the eager bailout point for
// the runtime function (actually as lazy bailout point). It doesn't
// really matter which bailout location we use since we never really
// go back after throwing the exception.
NodeProperties::RemoveFrameStateInput(node, 0);
NodeProperties::ReplaceValueInputs(node, target);
NodeProperties::ChangeOp(
node, javascript()->CallRuntime(Runtime::kThrowCalledNonCallable));
......@@ -406,7 +398,6 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
}
// Turn the {node} into a {JSCreateArray} call.
NodeProperties::RemoveFrameStateInput(node, 1);
for (int i = arity; i > 0; --i) {
NodeProperties::ReplaceValueInput(
node, NodeProperties::GetValueInput(node, i), i + 1);
......@@ -460,7 +451,6 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
// Turn the {node} into a {JSCreateArray} call.
NodeProperties::ReplaceEffectInput(node, effect);
NodeProperties::ReplaceControlInput(node, control);
NodeProperties::RemoveFrameStateInput(node, 1);
for (int i = arity; i > 0; --i) {
NodeProperties::ReplaceValueInput(
node, NodeProperties::GetValueInput(node, i), i + 1);
......
......@@ -55,12 +55,8 @@ class JSCallAccessor {
return call_->InputAt(formal_arguments() + 1);
}
Node* frame_state_before() {
return NodeProperties::GetFrameStateInput(call_, 1);
}
Node* frame_state_after() {
// Both, {JSCallFunction} and {JSCallConstruct}, have frame state after.
Node* frame_state() {
// Both, {JSCallFunction} and {JSCallConstruct}, have frame state.
return NodeProperties::GetFrameStateInput(call_, 0);
}
......@@ -334,7 +330,7 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
// TODO(turbofan): TranslatedState::GetAdaptedArguments() currently relies on
// not inlining recursive functions. We might want to relax that at some
// point.
for (Node* frame_state = call.frame_state_after();
for (Node* frame_state = call.frame_state();
frame_state->opcode() == IrOpcode::kFrameState;
frame_state = frame_state->InputAt(kFrameStateOuterStateInput)) {
FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
......@@ -419,7 +415,7 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
end = graph()->end();
}
Node* frame_state = call.frame_state_after();
Node* frame_state = call.frame_state();
Node* new_target = jsgraph_->UndefinedConstant();
// Inline {JSCallConstruct} requires some additional magic.
......@@ -430,11 +426,12 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
// Note that the context has to be the callers context (input to call node).
Node* receiver = jsgraph_->UndefinedConstant(); // Implicit receiver.
if (NeedsImplicitReceiver(shared_info)) {
Node* frame_state_before = NodeProperties::FindFrameStateBefore(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* context = NodeProperties::GetContextInput(node);
Node* create = jsgraph_->graph()->NewNode(
jsgraph_->javascript()->Create(), call.target(), call.new_target(),
context, call.frame_state_before(), effect);
context, frame_state_before, effect);
NodeProperties::ReplaceEffectInput(node, create);
// Insert a check of the return value to determine whether the return
// value
......@@ -481,10 +478,11 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
if (node->opcode() == IrOpcode::kJSCallFunction &&
is_sloppy(parse_info.language_mode()) && !shared_info->native()) {
const CallFunctionParameters& p = CallFunctionParametersOf(node->op());
Node* frame_state_before = NodeProperties::FindFrameStateBefore(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* convert = jsgraph_->graph()->NewNode(
jsgraph_->javascript()->ConvertReceiver(p.convert_mode()),
call.receiver(), context, call.frame_state_before(), effect, start);
call.receiver(), context, frame_state_before, effect, start);
NodeProperties::ReplaceValueInput(node, convert, 1);
NodeProperties::ReplaceEffectInput(node, convert);
}
......
......@@ -1388,9 +1388,6 @@ Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) {
Handle<JSFunction>::cast(target_type->AsConstant()->Value());
Handle<SharedFunctionInfo> shared(function->shared(), isolate());
// Remove the eager bailout frame state.
NodeProperties::RemoveFrameStateInput(node, 1);
// Patch {node} to an indirect call via the {function}s construct stub.
Callable callable(handle(shared->construct_stub(), isolate()),
ConstructStubDescriptor(isolate()));
......@@ -1410,9 +1407,6 @@ Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) {
// Check if {target} is a JSFunction.
if (target_type->Is(Type::Function())) {
// Remove the eager bailout frame state.
NodeProperties::RemoveFrameStateInput(node, 1);
// Patch {node} to an indirect call via the ConstructFunction builtin.
Callable callable = CodeFactory::ConstructFunction(isolate());
node->RemoveInput(arity + 1);
......@@ -1441,9 +1435,9 @@ Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
Type* target_type = NodeProperties::GetType(target);
Node* receiver = NodeProperties::GetValueInput(node, 1);
Type* receiver_type = NodeProperties::GetType(receiver);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* frame_state = NodeProperties::FindFrameStateBefore(node);
// Try to infer receiver {convert_mode} from {receiver} type.
if (receiver_type->Is(Type::NullOrUndefined())) {
......@@ -1481,9 +1475,6 @@ Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
// Update the effect dependency for the {node}.
NodeProperties::ReplaceEffectInput(node, effect);
// Remove the eager bailout frame state.
NodeProperties::RemoveFrameStateInput(node, 1);
// Compute flags for the call.
CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
if (p.tail_call_mode() == TailCallMode::kAllow) {
......@@ -1521,9 +1512,6 @@ Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
// Check if {target} is a JSFunction.
if (target_type->Is(Type::Function())) {
// Remove the eager bailout frame state.
NodeProperties::RemoveFrameStateInput(node, 1);
// Compute flags for the call.
CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
if (p.tail_call_mode() == TailCallMode::kAllow) {
......
......@@ -164,6 +164,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
case Runtime::kTraceEnter:
case Runtime::kTraceExit:
return 0;
case Runtime::kInlineCall:
case Runtime::kInlineGetPrototype:
case Runtime::kInlineNewObject:
case Runtime::kInlineRegExpConstructResult:
......@@ -179,7 +180,6 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
case Runtime::kInlineToPrimitive_String:
case Runtime::kInlineToString:
return 1;
case Runtime::kInlineCall:
case Runtime::kInlineDeoptimizeNow:
case Runtime::kInlineThrowNotDateError:
return 2;
......
......@@ -179,13 +179,6 @@ void NodeProperties::ReplaceFrameStateInput(Node* node, int index,
}
// static
void NodeProperties::RemoveFrameStateInput(Node* node, int index) {
DCHECK_LT(index, OperatorProperties::GetFrameStateInputCount(node->op()));
node->RemoveInput(FirstFrameStateIndex(node) + index);
}
// static
void NodeProperties::RemoveNonValueInputs(Node* node) {
node->TrimInputCount(node->op()->ValueInputCount());
......@@ -242,6 +235,17 @@ void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
}
// static
Node* NodeProperties::FindFrameStateBefore(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
while (effect->opcode() != IrOpcode::kCheckpoint) {
DCHECK_EQ(1, effect->op()->EffectInputCount());
effect = NodeProperties::GetEffectInput(effect);
}
Node* frame_state = GetFrameStateInput(effect, 0);
return frame_state;
}
// static
Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
for (auto use : node->uses()) {
......
......@@ -84,7 +84,6 @@ class NodeProperties final {
static void ReplaceControlInput(Node* node, Node* control, int index = 0);
static void ReplaceEffectInput(Node* node, Node* effect, int index = 0);
static void ReplaceFrameStateInput(Node* node, int index, Node* frame_state);
static void RemoveFrameStateInput(Node* node, int index);
static void RemoveNonValueInputs(Node* node);
static void RemoveValueInputs(Node* node);
......@@ -109,6 +108,11 @@ class NodeProperties final {
// ---------------------------------------------------------------------------
// Miscellaneous utilities.
// Find the last frame state that is effect-wise before the given node. This
// assumes a linear effect-chain up to a {CheckPoint} node in the graph.
static Node* FindFrameStateBefore(Node* node);
// Collect the output-value projection for the given output index.
static Node* FindProjection(Node* node, size_t projection_index);
// Collect the branch-related projections from a node, such as IfTrue,
......
......@@ -35,12 +35,6 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
case IrOpcode::kJSStrictNotEqual:
return 0;
// We record the frame state immediately before and immediately after every
// construct/function call.
case IrOpcode::kJSCallConstruct:
case IrOpcode::kJSCallFunction:
return 2;
// Compare operations
case IrOpcode::kJSEqual:
case IrOpcode::kJSNotEqual:
......@@ -66,6 +60,10 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
case IrOpcode::kJSToObject:
case IrOpcode::kJSToString:
// Call operations
case IrOpcode::kJSCallConstruct:
case IrOpcode::kJSCallFunction:
// Misc operations
case IrOpcode::kJSConvertReceiver:
case IrOpcode::kJSForInNext:
......
......@@ -99,7 +99,7 @@ TEST_F(JSBuiltinReducerTest, MathMax0) {
Node* frame_state = graph()->start();
Node* call = graph()->NewNode(javascript()->CallFunction(2), function,
UndefinedConstant(), context, frame_state,
frame_state, effect, control);
effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
......@@ -118,7 +118,7 @@ TEST_F(JSBuiltinReducerTest, MathMax1) {
Node* p0 = Parameter(t0, 0);
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
UndefinedConstant(), p0, context, frame_state,
frame_state, effect, control);
effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
......@@ -140,7 +140,7 @@ TEST_F(JSBuiltinReducerTest, MathMax2) {
Node* p1 = Parameter(t1, 1);
Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
UndefinedConstant(), p0, p1, context,
frame_state, frame_state, effect, control);
frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
......@@ -168,7 +168,7 @@ TEST_F(JSBuiltinReducerTest, MathImul) {
Node* p1 = Parameter(t1, 1);
Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
UndefinedConstant(), p0, p1, context,
frame_state, frame_state, effect, control);
frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
......@@ -194,7 +194,7 @@ TEST_F(JSBuiltinReducerTest, MathFround) {
Node* p0 = Parameter(t0, 0);
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
UndefinedConstant(), p0, context, frame_state,
frame_state, effect, control);
effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
......
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