[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}
This commit is contained in:
bmeurer 2016-12-22 10:27:45 -08:00 committed by Commit bot
parent da328981ff
commit b0ff71dbe8
3 changed files with 28 additions and 20 deletions

View File

@ -4,6 +4,7 @@
#include "src/compiler/js-call-reducer.h"
#include "src/code-factory.h"
#include "src/code-stubs.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
@ -485,26 +486,37 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
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.
if (!p.feedback().IsValid()) return NoChange();
CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
if (nexus.IsUninitialized() && (flags() & kBailoutOnUninitialized)) {
Node* frame_state = NodeProperties::FindFrameStateBefore(node);
Node* deoptimize = graph()->NewNode(
common()->Deoptimize(
DeoptimizeKind::kSoft,
DeoptimizeReason::kInsufficientTypeFeedbackForCall),
frame_state, effect, control);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
Revisit(graph()->end());
node->TrimInputCount(0);
NodeProperties::ChangeOp(node, common()->Dead());
if (nexus.IsUninitialized()) {
// TODO(turbofan): Tail-calling to a CallIC stub is not supported.
if (p.tail_call_mode() == TailCallMode::kAllow) return NoChange();
// Insert a CallIC here to collect feedback for uninitialized calls.
int const arg_count = static_cast<int>(p.arity() - 2);
Callable callable =
CodeFactory::CallICInOptimizedCode(isolate(), p.convert_mode());
CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), arg_count + 1,
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);
}
// Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
Handle<Object> feedback(nexus.GetFeedback(), isolate());
if (feedback->IsAllocationSite()) {
// Retrieve the Array function from the {node}.

View File

@ -25,8 +25,7 @@ class JSCallReducer final : public AdvancedReducer {
// Flags that control the mode of operation.
enum Flag {
kNoFlags = 0u,
kBailoutOnUninitialized = 1u << 0,
kDeoptimizationEnabled = 1u << 1
kDeoptimizationEnabled = 1u << 0,
};
typedef base::Flags<Flag> Flags;

View File

@ -763,9 +763,6 @@ struct InliningPhase {
CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
data->common(), data->machine());
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()) {
call_reducer_flags |= JSCallReducer::kDeoptimizationEnabled;
}