Files
sdk/runtime/vm/compiler/compiler_timings.h
Alexander Aprelev 6123e0effb [vm/inlining] Set try-index for inlined function after decision is made.
Delay setting try-index for callee flow graph until the decision to inline is made.
This avoids confusing situation when running optimization passes on callee, where InsideTryBlock reports that the instruction is in try block, but there is no try block in the flow graph.

TEST=ci

Change-Id: Ia9dfa8b53dda9ca259dc73d810e7a4344971b904
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/399320
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
2024-12-06 16:23:09 +00:00

164 lines
6.5 KiB
C++

// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_COMPILER_COMPILER_TIMINGS_H_
#define RUNTIME_VM_COMPILER_COMPILER_TIMINGS_H_
#include <memory>
#include "platform/allocation.h"
#include "vm/compiler/compiler_pass.h"
#include "vm/thread.h"
#include "vm/timer.h"
#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif // defined(DART_PRECOMPILED_RUNTIME)
#define PRECOMPILER_TIMERS_LIST(V) \
V(CompileAll) \
V(Iterate) \
V(CompileFunction) \
V(AddCalleesOf) \
V(CheckForNewDynamicFunctions) \
V(CollectCallbackFields) \
V(PrecompileConstructors) \
V(AttachOptimizedTypeTestingStub) \
V(TraceForRetainedFunctions) \
V(FinalizeDispatchTable) \
V(ReplaceFunctionStaticCallEntries) \
V(Drop) \
V(Obfuscate) \
V(Dedup) \
V(SymbolsCompact)
#define INLINING_TIMERS_LIST(V) \
V(CollectGraphInfo) \
V(PopulateWithICData) \
V(FindCallSites) \
V(SetInliningIdAndTryIndex) \
V(MakeInliningDecision) \
V(CheckForPragma) \
V(InlineCall) \
V(InlineRecognizedMethod) \
V(DiscoverBlocks) \
V(BuildDecisionGraph) \
V(PrepareGraphs)
// Note: COMPILER_PASS_LIST must be the first element of the list below because
// we expect that pass ids are the same as ids of corresponding timers.
#define COMPILER_TIMERS_LIST(V) \
COMPILER_PASS_LIST(V) \
PRECOMPILER_TIMERS_LIST(V) \
INLINING_TIMERS_LIST(V) \
V(BuildGraph) \
V(EmitCode) \
V(FinalizeCode)
namespace dart {
// |CompilerTimings| provides a way to track time taken by various compiler
// passes via a fixed number of timers (specified in |COMPILER_TIMERS_LIST|).
//
// It supports arbitrary nesting of timers e.g. if |DiscoverBlocks| is invoked
// within two different compiler passes like |IfConvert| and |BranchSimplify|
// then |CompilerTimings| will separate these two invocations and measure each
// separately.
class CompilerTimings : public MallocAllocated {
private:
#define INC(Name) +1
static constexpr intptr_t kNumTimers = 0 COMPILER_TIMERS_LIST(INC);
#undef INC
struct Timers : public MallocAllocated {
Timer timers_[kNumTimers];
std::unique_ptr<Timers> nested_[kNumTimers];
};
public:
enum TimerId {
#define DECLARE_TIMER_ID(Name) k##Name,
COMPILER_TIMERS_LIST(DECLARE_TIMER_ID)
#undef DECLARE_TIMER_ID
};
// Timing scope which starts and stop the timer with the given |id|.
class Scope : public StackResource {
public:
Scope(Thread* thread, TimerId id)
: StackResource(thread), stats_(thread->compiler_timings()) {
if (stats_ != nullptr) {
outer_nested_ = stats_->nested_;
if (*outer_nested_ == nullptr) {
// Created array of nested timers if we don't have one yet.
*outer_nested_ = std::make_unique<Timers>();
}
timer_ = &(*outer_nested_)->timers_[id];
stats_->nested_ = &(*outer_nested_)->nested_[id];
timer_->Start();
}
}
~Scope() {
if (stats_ != nullptr) {
timer_->Stop();
stats_->nested_ = outer_nested_;
}
}
private:
CompilerTimings* const stats_;
Timer* timer_;
std::unique_ptr<Timers>* outer_nested_;
};
CompilerTimings() { total_.Start(); }
void RecordInliningStatsByOutcome(bool success, const Timer& timer) {
if (success) {
try_inlining_success_.AddTotal(timer);
} else {
try_inlining_failure_.AddTotal(timer);
}
}
void Print();
private:
void PrintTimers(Zone* zone,
const std::unique_ptr<CompilerTimings::Timers>& timers,
const Timer& total,
intptr_t level);
Timer total_;
std::unique_ptr<Timers> root_ = std::make_unique<Timers>();
// Timers nested under the currently running timer(s).
std::unique_ptr<Timers>* nested_ = &root_;
Timer try_inlining_success_;
Timer try_inlining_failure_;
};
#define TIMER_SCOPE_NAME2(counter) timer_scope_##counter
#define TIMER_SCOPE_NAME(counter) TIMER_SCOPE_NAME2(counter)
#define COMPILER_TIMINGS_TIMER_SCOPE(thread, timer_id) \
CompilerTimings::Scope TIMER_SCOPE_NAME(__COUNTER__)( \
thread, CompilerTimings::k##timer_id)
#define COMPILER_TIMINGS_PASS_TIMER_SCOPE(thread, pass_id) \
CompilerTimings::Scope TIMER_SCOPE_NAME(__COUNTER__)( \
thread, static_cast<CompilerTimings::TimerId>(pass_id))
#define PRECOMPILER_TIMER_SCOPE(precompiler, timer_id) \
CompilerTimings::Scope TIMER_SCOPE_NAME(__COUNTER__)( \
(precompiler) -> thread(), CompilerTimings::k##timer_id)
} // namespace dart
#endif // RUNTIME_VM_COMPILER_COMPILER_TIMINGS_H_