Commit 2cccb464 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Improve --trace-turbo-inlining and TRACE_BROKER_MISSING

- Eliminate unconditional heap reads in tracing code.
- Change operator<< on ObjectRef to additionally print
  the Brief() output when the broker is disabled.
- Print line number in TRACE_BROKER_MISSING and make
  some messages more consistent.
- Make PrintCandidates output clearer.
- Be more consistent about dereferencing optionals.

Bug: v8:7790, chromium:990478
Change-Id: I2917529d5138a0d63ad476d3f8fee6a963767b23
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1758311
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63242}
parent 4b1af9fc
...@@ -3247,8 +3247,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -3247,8 +3247,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
if (target_ref.IsJSFunction()) { if (target_ref.IsJSFunction()) {
JSFunctionRef function = target_ref.AsJSFunction(); JSFunctionRef function = target_ref.AsJSFunction();
if (FLAG_concurrent_inlining && !function.serialized()) { if (FLAG_concurrent_inlining && !function.serialized()) {
TRACE_BROKER_MISSING(broker(), TRACE_BROKER_MISSING(broker(), "data for function " << function);
"function, not serialized: " << function);
return NoChange(); return NoChange();
} }
...@@ -3261,8 +3260,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -3261,8 +3260,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
} else if (target_ref.IsJSBoundFunction()) { } else if (target_ref.IsJSBoundFunction()) {
JSBoundFunctionRef function = target_ref.AsJSBoundFunction(); JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
if (FLAG_concurrent_inlining && !function.serialized()) { if (FLAG_concurrent_inlining && !function.serialized()) {
TRACE_BROKER_MISSING(broker(), TRACE_BROKER_MISSING(broker(), "data for function " << function);
"function, not serialized: " << function);
return NoChange(); return NoChange();
} }
......
...@@ -4460,7 +4460,13 @@ void ElementAccessFeedback::AddGroup(TransitionGroup&& group) { ...@@ -4460,7 +4460,13 @@ void ElementAccessFeedback::AddGroup(TransitionGroup&& group) {
} }
std::ostream& operator<<(std::ostream& os, const ObjectRef& ref) { std::ostream& operator<<(std::ostream& os, const ObjectRef& ref) {
return os << ref.data(); if (ref.broker()->mode() == JSHeapBroker::kDisabled) {
// If the broker is disabled we cannot be in a background thread so it's
// safe to read the heap.
return os << ref.data() << " {" << ref.object() << "}";
} else {
return os << ref.data();
}
} }
base::Optional<NameRef> JSHeapBroker::GetNameFeedback( base::Optional<NameRef> JSHeapBroker::GetNameFeedback(
......
...@@ -56,10 +56,11 @@ struct FeedbackSource { ...@@ -56,10 +56,11 @@ struct FeedbackSource {
broker->Trace() << x << '\n'; \ broker->Trace() << x << '\n'; \
} while (false) } while (false)
#define TRACE_BROKER_MISSING(broker, x) \ #define TRACE_BROKER_MISSING(broker, x) \
do { \ do { \
if (broker->tracing_enabled()) \ if (broker->tracing_enabled()) \
broker->Trace() << __FUNCTION__ << ": missing " << x << '\n'; \ broker->Trace() << __FUNCTION__ << " (line " << __LINE__ \
<< "): missing " << x << std::endl; \
} while (false) } while (false)
struct PropertyAccessTarget { struct PropertyAccessTarget {
......
...@@ -114,8 +114,8 @@ Reduction JSInliningHeuristic::Reduce(Node* node) { ...@@ -114,8 +114,8 @@ Reduction JSInliningHeuristic::Reduce(Node* node) {
Handle<SharedFunctionInfo> frame_shared_info; Handle<SharedFunctionInfo> frame_shared_info;
for (int i = 0; i < candidate.num_functions; ++i) { for (int i = 0; i < candidate.num_functions; ++i) {
if (!candidate.bytecode[i].has_value()) { if (!candidate.bytecode[i].has_value()) {
// We're already missing critical data which wouldn't allow us to // Can't inline without bytecode.
// continue the inlining checks. Log a warning and continue. // TODO(neis): Should this even be a broker message?
if (candidate.functions[i].has_value()) { if (candidate.functions[i].has_value()) {
TRACE_BROKER(broker(), TRACE_BROKER(broker(),
"Missing bytecode array trying to inline JSFunction " "Missing bytecode array trying to inline JSFunction "
...@@ -205,6 +205,8 @@ Reduction JSInliningHeuristic::Reduce(Node* node) { ...@@ -205,6 +205,8 @@ Reduction JSInliningHeuristic::Reduce(Node* node) {
} }
void JSInliningHeuristic::Finalize() { void JSInliningHeuristic::Finalize() {
DisallowHeapAccessIf no_heap_acess(FLAG_concurrent_inlining);
if (candidates_.empty()) return; // Nothing to do without candidates. if (candidates_.empty()) return; // Nothing to do without candidates.
if (FLAG_trace_turbo_inlining) PrintCandidates(); if (FLAG_trace_turbo_inlining) PrintCandidates();
...@@ -730,22 +732,22 @@ bool JSInliningHeuristic::CandidateCompare::operator()( ...@@ -730,22 +732,22 @@ bool JSInliningHeuristic::CandidateCompare::operator()(
void JSInliningHeuristic::PrintCandidates() { void JSInliningHeuristic::PrintCandidates() {
StdoutStream os; StdoutStream os;
os << "Candidates for inlining (size=" << candidates_.size() << "):\n"; os << candidates_.size() << " candidate(s) for inlining:" << std::endl;
for (const Candidate& candidate : candidates_) { for (const Candidate& candidate : candidates_) {
os << " #" << candidate.node->id() << ":" os << "- candidate: " << candidate.node->op()->mnemonic() << " node #"
<< candidate.node->op()->mnemonic() << candidate.node->id() << " with frequency " << candidate.frequency
<< ", frequency: " << candidate.frequency << std::endl; << ", " << candidate.num_functions << " target(s):" << std::endl;
for (int i = 0; i < candidate.num_functions; ++i) { for (int i = 0; i < candidate.num_functions; ++i) {
SharedFunctionInfoRef shared = candidate.functions[i].has_value()
? candidate.functions[i]->shared()
: candidate.shared_info.value();
os << " - target: " << shared;
if (candidate.bytecode[i].has_value()) { if (candidate.bytecode[i].has_value()) {
PrintF(" - size:%d,", candidate.bytecode[i].value().length()); os << ", bytecode size: " << candidate.bytecode[i]->length();
} else { } else {
PrintF(" - no bytecode,"); os << ", no bytecode";
} }
SharedFunctionInfoRef shared = os << std::endl;
candidate.functions[i].has_value()
? candidate.functions[i].value().shared()
: candidate.shared_info.value();
PrintF(" name: %s\n", shared.object()->DebugName().ToCString().get());
} }
} }
} }
......
...@@ -373,13 +373,14 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -373,13 +373,14 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
// Determine the call target. // Determine the call target.
base::Optional<SharedFunctionInfoRef> shared_info(DetermineCallTarget(node)); base::Optional<SharedFunctionInfoRef> shared_info(DetermineCallTarget(node));
if (!shared_info.has_value()) return NoChange(); if (!shared_info.has_value()) return NoChange();
DCHECK(shared_info->IsInlineable()); DCHECK(shared_info->IsInlineable());
SharedFunctionInfoRef outer_shared_info(broker(), info_->shared_info());
// Constructor must be constructable. // Constructor must be constructable.
if (node->opcode() == IrOpcode::kJSConstruct && if (node->opcode() == IrOpcode::kJSConstruct &&
!IsConstructable(shared_info->kind())) { !IsConstructable(shared_info->kind())) {
TRACE("Not inlining " << *shared_info << " into " << info_->shared_info() TRACE("Not inlining " << *shared_info << " into " << outer_shared_info
<< " because constructor is not constructable."); << " because constructor is not constructable.");
return NoChange(); return NoChange();
} }
...@@ -388,7 +389,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -388,7 +389,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
// See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ). // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
if (node->opcode() == IrOpcode::kJSCall && if (node->opcode() == IrOpcode::kJSCall &&
IsClassConstructor(shared_info->kind())) { IsClassConstructor(shared_info->kind())) {
TRACE("Not inlining " << *shared_info << " into " << info_->shared_info() TRACE("Not inlining " << *shared_info << " into " << outer_shared_info
<< " because callee is a class constructor."); << " because callee is a class constructor.");
return NoChange(); return NoChange();
} }
...@@ -402,7 +403,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -402,7 +403,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
nesting_level++; nesting_level++;
if (nesting_level > kMaxDepthForInlining) { if (nesting_level > kMaxDepthForInlining) {
TRACE("Not inlining " TRACE("Not inlining "
<< *shared_info << " into " << info_->shared_info() << *shared_info << " into " << outer_shared_info
<< " because call has exceeded the maximum depth for function " << " because call has exceeded the maximum depth for function "
"inlining."); "inlining.");
return NoChange(); return NoChange();
...@@ -417,14 +418,14 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -417,14 +418,14 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
// passing the IsInlineable check, The broker holds a reference to the // passing the IsInlineable check, The broker holds a reference to the
// bytecode array, which prevents it from getting flushed. // bytecode array, which prevents it from getting flushed.
// Therefore, the following check should always hold true. // Therefore, the following check should always hold true.
CHECK(shared_info.value().is_compiled()); CHECK(shared_info->is_compiled());
if (!FLAG_concurrent_inlining && info_->is_source_positions_enabled()) { if (!FLAG_concurrent_inlining && info_->is_source_positions_enabled()) {
SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate(), SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate(),
shared_info->object()); shared_info->object());
} }
TRACE("Inlining " << *shared_info << " into " << info_->shared_info() TRACE("Inlining " << *shared_info << " into " << outer_shared_info
<< ((exception_target != nullptr) ? " (inside try-block)" << ((exception_target != nullptr) ? " (inside try-block)"
: "")); : ""));
// Determine the targets feedback vector and its context. // Determine the targets feedback vector and its context.
...@@ -432,7 +433,8 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -432,7 +433,8 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
FeedbackVectorRef feedback_vector = DetermineCallContext(node, &context); FeedbackVectorRef feedback_vector = DetermineCallContext(node, &context);
if (FLAG_concurrent_inlining && if (FLAG_concurrent_inlining &&
!shared_info.value().IsSerializedForCompilation(feedback_vector)) { !shared_info->IsSerializedForCompilation(feedback_vector)) {
// TODO(neis): Should this be a broker message?
TRACE("Missed opportunity to inline a function (" TRACE("Missed opportunity to inline a function ("
<< *shared_info << " with " << feedback_vector << ")"); << *shared_info << " with " << feedback_vector << ")");
return NoChange(); return NoChange();
...@@ -442,12 +444,12 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -442,12 +444,12 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
// After this point, we've made a decision to inline this function. // After this point, we've made a decision to inline this function.
// We shall not bailout from inlining if we got here. // We shall not bailout from inlining if we got here.
BytecodeArrayRef bytecode_array = shared_info.value().GetBytecodeArray(); BytecodeArrayRef bytecode_array = shared_info->GetBytecodeArray();
// Remember that we inlined this function. // Remember that we inlined this function.
int inlining_id = info_->AddInlinedFunction( int inlining_id =
shared_info.value().object(), bytecode_array.object(), info_->AddInlinedFunction(shared_info->object(), bytecode_array.object(),
source_positions_->GetSourcePosition(node)); source_positions_->GetSourcePosition(node));
// Create the subgraph for the inlinee. // Create the subgraph for the inlinee.
Node* start; Node* start;
...@@ -473,11 +475,11 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -473,11 +475,11 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
AllowCodeDependencyChange allow_code_dep_change; AllowCodeDependencyChange allow_code_dep_change;
CallFrequency frequency = call.frequency(); CallFrequency frequency = call.frequency();
Handle<NativeContext> native_context(info_->native_context(), isolate()); Handle<NativeContext> native_context(info_->native_context(), isolate());
BuildGraphFromBytecode( BuildGraphFromBytecode(broker(), zone(), bytecode_array.object(),
broker(), zone(), bytecode_array.object(), shared_info->object(), feedback_vector.object(),
shared_info.value().object(), feedback_vector.object(), BailoutId::None(), jsgraph(), frequency,
BailoutId::None(), jsgraph(), frequency, source_positions_, source_positions_, native_context, inlining_id,
native_context, inlining_id, flags, &info_->tick_counter()); flags, &info_->tick_counter());
} }
// Extract the inlinee start/end nodes. // Extract the inlinee start/end nodes.
...@@ -525,13 +527,13 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -525,13 +527,13 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
// where execution continues at {construct_stub_create_deopt_pc_offset}). // where execution continues at {construct_stub_create_deopt_pc_offset}).
Node* receiver = jsgraph()->TheHoleConstant(); // Implicit receiver. Node* receiver = jsgraph()->TheHoleConstant(); // Implicit receiver.
Node* context = NodeProperties::GetContextInput(node); Node* context = NodeProperties::GetContextInput(node);
if (NeedsImplicitReceiver(shared_info.value())) { if (NeedsImplicitReceiver(*shared_info)) {
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node); Node* control = NodeProperties::GetControlInput(node);
Node* frame_state_inside = CreateArtificialFrameState( Node* frame_state_inside = CreateArtificialFrameState(
node, frame_state, call.formal_arguments(), node, frame_state, call.formal_arguments(),
BailoutId::ConstructStubCreate(), FrameStateType::kConstructStub, BailoutId::ConstructStubCreate(), FrameStateType::kConstructStub,
shared_info.value(), context); *shared_info, context);
Node* create = Node* create =
graph()->NewNode(javascript()->Create(), call.target(), new_target, graph()->NewNode(javascript()->Create(), call.target(), new_target,
context, frame_state_inside, effect, control); context, frame_state_inside, effect, control);
...@@ -586,7 +588,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -586,7 +588,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
frame_state = CreateArtificialFrameState( frame_state = CreateArtificialFrameState(
node, frame_state, call.formal_arguments(), node, frame_state, call.formal_arguments(),
BailoutId::ConstructStubInvoke(), FrameStateType::kConstructStub, BailoutId::ConstructStubInvoke(), FrameStateType::kConstructStub,
shared_info.value(), context); *shared_info, context);
} }
// Insert a JSConvertReceiver node for sloppy callees. Note that the context // Insert a JSConvertReceiver node for sloppy callees. Note that the context
...@@ -615,7 +617,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -615,7 +617,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
if (call.formal_arguments() != parameter_count) { if (call.formal_arguments() != parameter_count) {
frame_state = CreateArtificialFrameState( frame_state = CreateArtificialFrameState(
node, frame_state, call.formal_arguments(), BailoutId::None(), node, frame_state, call.formal_arguments(), BailoutId::None(),
FrameStateType::kArgumentsAdaptor, shared_info.value()); FrameStateType::kArgumentsAdaptor, *shared_info);
} }
return InlineCall(node, new_target, context, frame_state, start, end, return InlineCall(node, new_target, context, frame_state, start, end,
......
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