Commit b0ff71db authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Continue collecting CallIC feedback in optimized code.

Similar to Crankshaft use the CallIC to continue gathering feedback for
uninitialized call sites instead of inserting a soft deopt.

R=mvstanton@chromium.org

Review-Url: https://codereview.chromium.org/2597173002
Cr-Commit-Position: refs/heads/master@{#41927}
parent da328981
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "src/compiler/js-call-reducer.h" #include "src/compiler/js-call-reducer.h"
#include "src/code-factory.h"
#include "src/code-stubs.h" #include "src/code-stubs.h"
#include "src/compiler/js-graph.h" #include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h" #include "src/compiler/linkage.h"
...@@ -485,26 +486,37 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { ...@@ -485,26 +486,37 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
return NoChange(); return NoChange();
} }
// Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
// Extract feedback from the {node} using the CallICNexus. // Extract feedback from the {node} using the CallICNexus.
if (!p.feedback().IsValid()) return NoChange(); if (!p.feedback().IsValid()) return NoChange();
CallICNexus nexus(p.feedback().vector(), p.feedback().slot()); CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
if (nexus.IsUninitialized() && (flags() & kBailoutOnUninitialized)) { if (nexus.IsUninitialized()) {
Node* frame_state = NodeProperties::FindFrameStateBefore(node); // TODO(turbofan): Tail-calling to a CallIC stub is not supported.
Node* deoptimize = graph()->NewNode( if (p.tail_call_mode() == TailCallMode::kAllow) return NoChange();
common()->Deoptimize(
DeoptimizeKind::kSoft, // Insert a CallIC here to collect feedback for uninitialized calls.
DeoptimizeReason::kInsufficientTypeFeedbackForCall), int const arg_count = static_cast<int>(p.arity() - 2);
frame_state, effect, control); Callable callable =
// TODO(bmeurer): This should be on the AdvancedReducer somehow. CodeFactory::CallICInOptimizedCode(isolate(), p.convert_mode());
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
Revisit(graph()->end()); CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
node->TrimInputCount(0); isolate(), graph()->zone(), callable.descriptor(), arg_count + 1,
NodeProperties::ChangeOp(node, common()->Dead()); flags);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
Node* stub_arity = jsgraph()->Constant(arg_count);
Node* slot_index =
jsgraph()->Constant(TypeFeedbackVector::GetIndex(p.feedback().slot()));
Node* feedback_vector = jsgraph()->HeapConstant(p.feedback().vector());
node->InsertInput(graph()->zone(), 0, stub_code);
node->InsertInput(graph()->zone(), 2, stub_arity);
node->InsertInput(graph()->zone(), 3, slot_index);
node->InsertInput(graph()->zone(), 4, feedback_vector);
NodeProperties::ChangeOp(node, common()->Call(desc));
return Changed(node); return Changed(node);
} }
// Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
Handle<Object> feedback(nexus.GetFeedback(), isolate()); Handle<Object> feedback(nexus.GetFeedback(), isolate());
if (feedback->IsAllocationSite()) { if (feedback->IsAllocationSite()) {
// Retrieve the Array function from the {node}. // Retrieve the Array function from the {node}.
......
...@@ -25,8 +25,7 @@ class JSCallReducer final : public AdvancedReducer { ...@@ -25,8 +25,7 @@ class JSCallReducer final : public AdvancedReducer {
// Flags that control the mode of operation. // Flags that control the mode of operation.
enum Flag { enum Flag {
kNoFlags = 0u, kNoFlags = 0u,
kBailoutOnUninitialized = 1u << 0, kDeoptimizationEnabled = 1u << 0,
kDeoptimizationEnabled = 1u << 1
}; };
typedef base::Flags<Flag> Flags; typedef base::Flags<Flag> Flags;
......
...@@ -763,9 +763,6 @@ struct InliningPhase { ...@@ -763,9 +763,6 @@ struct InliningPhase {
CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
data->common(), data->machine()); data->common(), data->machine());
JSCallReducer::Flags call_reducer_flags = JSCallReducer::kNoFlags; JSCallReducer::Flags call_reducer_flags = JSCallReducer::kNoFlags;
if (data->info()->is_bailout_on_uninitialized()) {
call_reducer_flags |= JSCallReducer::kBailoutOnUninitialized;
}
if (data->info()->is_deoptimization_enabled()) { if (data->info()->is_deoptimization_enabled()) {
call_reducer_flags |= JSCallReducer::kDeoptimizationEnabled; call_reducer_flags |= JSCallReducer::kDeoptimizationEnabled;
} }
......
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