Commit 87eedbc1 authored by Stephan Herhut's avatar Stephan Herhut Committed by Commit Bot

[profiling] Fix BasicBlockProfiler implementation

Data object for tick collection are now created in a thread save way
and the block ids for counters use the same numbers as the printed
schedule.

Change-Id: I7a35088cb2fcd94a81067b16ad12b01d380fefa5
Reviewed-on: https://chromium-review.googlesource.com/1152923
Commit-Queue: Stephan Herhut <herhut@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55124}
parent 7cc1d19b
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "src/basic-block-profiler.h" #include "src/basic-block-profiler.h"
#include <algorithm>
#include <numeric>
#include <sstream> #include <sstream>
#include "src/base/lazy-instance.h" #include "src/base/lazy-instance.h"
...@@ -21,8 +23,9 @@ BasicBlockProfiler* BasicBlockProfiler::Get() { ...@@ -21,8 +23,9 @@ BasicBlockProfiler* BasicBlockProfiler::Get() {
} }
BasicBlockProfiler::Data::Data(size_t n_blocks) BasicBlockProfiler::Data::Data(size_t n_blocks)
: n_blocks_(n_blocks), block_ids_(n_blocks_), counts_(n_blocks_, 0) {} : n_blocks_(n_blocks),
block_rpo_numbers_(n_blocks_),
counts_(n_blocks_, 0) {}
BasicBlockProfiler::Data::~Data() {} BasicBlockProfiler::Data::~Data() {}
...@@ -31,31 +34,31 @@ static void InsertIntoString(std::ostringstream* os, std::string* string) { ...@@ -31,31 +34,31 @@ static void InsertIntoString(std::ostringstream* os, std::string* string) {
string->insert(0, os->str()); string->insert(0, os->str());
} }
static void InsertIntoString(const char* data, std::string* string) {
string->insert(0, data);
}
void BasicBlockProfiler::Data::SetCode(std::ostringstream* os) { void BasicBlockProfiler::Data::SetCode(std::ostringstream* os) {
InsertIntoString(os, &code_); InsertIntoString(os, &code_);
} }
void BasicBlockProfiler::Data::SetFunctionName(std::unique_ptr<char[]> name) {
void BasicBlockProfiler::Data::SetFunctionName(std::ostringstream* os) { InsertIntoString(name.get(), &function_name_);
InsertIntoString(os, &function_name_);
} }
void BasicBlockProfiler::Data::SetSchedule(std::ostringstream* os) { void BasicBlockProfiler::Data::SetSchedule(std::ostringstream* os) {
InsertIntoString(os, &schedule_); InsertIntoString(os, &schedule_);
} }
void BasicBlockProfiler::Data::SetBlockRpoNumber(size_t offset,
void BasicBlockProfiler::Data::SetBlockId(size_t offset, size_t block_id) { int32_t block_rpo) {
DCHECK(offset < n_blocks_); DCHECK(offset < n_blocks_);
block_ids_[offset] = block_id; block_rpo_numbers_[offset] = block_rpo;
} }
intptr_t BasicBlockProfiler::Data::GetCounterAddress(size_t offset) {
uint32_t* BasicBlockProfiler::Data::GetCounterAddress(size_t offset) {
DCHECK(offset < n_blocks_); DCHECK(offset < n_blocks_);
return &counts_[offset]; return reinterpret_cast<intptr_t>(&(counts_[offset]));
} }
...@@ -70,6 +73,7 @@ BasicBlockProfiler::BasicBlockProfiler() {} ...@@ -70,6 +73,7 @@ BasicBlockProfiler::BasicBlockProfiler() {}
BasicBlockProfiler::Data* BasicBlockProfiler::NewData(size_t n_blocks) { BasicBlockProfiler::Data* BasicBlockProfiler::NewData(size_t n_blocks) {
base::LockGuard<base::Mutex> lock(&data_list_mutex_);
Data* data = new Data(n_blocks); Data* data = new Data(n_blocks);
data_list_.push_back(data); data_list_.push_back(data);
return data; return data;
...@@ -102,17 +106,33 @@ std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler& p) { ...@@ -102,17 +106,33 @@ std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler& p) {
std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler::Data& d) { std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler::Data& d) {
int block_count_sum = std::accumulate(d.counts_.begin(), d.counts_.end(), 0);
if (block_count_sum == 0) return os;
const char* name = "unknown function"; const char* name = "unknown function";
if (!d.function_name_.empty()) { if (!d.function_name_.empty()) {
name = d.function_name_.c_str(); name = d.function_name_.c_str();
} }
if (!d.schedule_.empty()) { if (!d.schedule_.empty()) {
os << "schedule for " << name << std::endl; os << "schedule for " << name << " (B0 entered " << d.counts_[0]
<< " times)" << std::endl;
os << d.schedule_.c_str() << std::endl; os << d.schedule_.c_str() << std::endl;
} }
os << "block counts for " << name << ":" << std::endl; os << "block counts for " << name << ":" << std::endl;
std::vector<std::pair<int32_t, uint32_t>> pairs;
pairs.reserve(d.n_blocks_);
for (size_t i = 0; i < d.n_blocks_; ++i) { for (size_t i = 0; i < d.n_blocks_; ++i) {
os << "block " << d.block_ids_[i] << " : " << d.counts_[i] << std::endl; pairs.push_back(std::make_pair(d.block_rpo_numbers_[i], d.counts_[i]));
}
std::sort(pairs.begin(), pairs.end(),
[=](std::pair<int32_t, uint32_t> left,
std::pair<int32_t, uint32_t> right) {
if (right.second == left.second)
return left.first < right.first;
return right.second < left.second;
});
for (auto it : pairs) {
if (it.second == 0) break;
os << "block B" << it.first << " : " << it.second << std::endl;
} }
os << std::endl; os << std::endl;
if (!d.code_.empty()) { if (!d.code_.empty()) {
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <vector> #include <vector>
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/base/platform/mutex.h"
#include "src/globals.h" #include "src/globals.h"
namespace v8 { namespace v8 {
...@@ -24,10 +25,10 @@ class BasicBlockProfiler { ...@@ -24,10 +25,10 @@ class BasicBlockProfiler {
const uint32_t* counts() const { return &counts_[0]; } const uint32_t* counts() const { return &counts_[0]; }
void SetCode(std::ostringstream* os); void SetCode(std::ostringstream* os);
void SetFunctionName(std::ostringstream* os); void SetFunctionName(std::unique_ptr<char[]> name);
void SetSchedule(std::ostringstream* os); void SetSchedule(std::ostringstream* os);
void SetBlockId(size_t offset, size_t block_id); void SetBlockRpoNumber(size_t offset, int32_t block_rpo);
uint32_t* GetCounterAddress(size_t offset); intptr_t GetCounterAddress(size_t offset);
private: private:
friend class BasicBlockProfiler; friend class BasicBlockProfiler;
...@@ -40,7 +41,7 @@ class BasicBlockProfiler { ...@@ -40,7 +41,7 @@ class BasicBlockProfiler {
void ResetCounts(); void ResetCounts();
const size_t n_blocks_; const size_t n_blocks_;
std::vector<size_t> block_ids_; std::vector<int32_t> block_rpo_numbers_;
std::vector<uint32_t> counts_; std::vector<uint32_t> counts_;
std::string function_name_; std::string function_name_;
std::string schedule_; std::string schedule_;
...@@ -64,6 +65,7 @@ class BasicBlockProfiler { ...@@ -64,6 +65,7 @@ class BasicBlockProfiler {
std::ostream& os, const BasicBlockProfiler& s); std::ostream& os, const BasicBlockProfiler& s);
DataList data_list_; DataList data_list_;
base::Mutex data_list_mutex_;
DISALLOW_COPY_AND_ASSIGN(BasicBlockProfiler); DISALLOW_COPY_AND_ASSIGN(BasicBlockProfiler);
}; };
......
...@@ -40,26 +40,23 @@ static NodeVector::iterator FindInsertionPoint(BasicBlock* block) { ...@@ -40,26 +40,23 @@ static NodeVector::iterator FindInsertionPoint(BasicBlock* block) {
// TODO(dcarney): need to mark code as non-serializable. // TODO(dcarney): need to mark code as non-serializable.
static const Operator* PointerConstant(CommonOperatorBuilder* common, static const Operator* PointerConstant(CommonOperatorBuilder* common,
void* ptr) { intptr_t ptr) {
return kPointerSize == 8 return kPointerSize == 8 ? common->Int64Constant(ptr)
? common->Int64Constant(reinterpret_cast<intptr_t>(ptr)) : common->Int32Constant(static_cast<int32_t>(ptr));
: common->Int32Constant(
static_cast<int32_t>(reinterpret_cast<intptr_t>(ptr)));
} }
BasicBlockProfiler::Data* BasicBlockInstrumentor::Instrument( BasicBlockProfiler::Data* BasicBlockInstrumentor::Instrument(
OptimizedCompilationInfo* info, Graph* graph, Schedule* schedule, OptimizedCompilationInfo* info, Graph* graph, Schedule* schedule,
Isolate* isolate) { Isolate* isolate) {
// Basic block profiling disables concurrent compilation, so handle deref is
// fine.
AllowHandleDereference allow_handle_dereference;
// Skip the exit block in profiles, since the register allocator can't handle // Skip the exit block in profiles, since the register allocator can't handle
// it and entry into it means falling off the end of the function anyway. // it and entry into it means falling off the end of the function anyway.
size_t n_blocks = static_cast<size_t>(schedule->RpoBlockCount()) - 1; size_t n_blocks = static_cast<size_t>(schedule->RpoBlockCount()) - 1;
BasicBlockProfiler::Data* data = BasicBlockProfiler::Get()->NewData(n_blocks); BasicBlockProfiler::Data* data = BasicBlockProfiler::Get()->NewData(n_blocks);
// Set the function name. // Set the function name.
if (info->has_shared_info()) { data->SetFunctionName(info->GetDebugName());
std::ostringstream os;
info->shared_info()->Name()->PrintUC16(os);
data->SetFunctionName(&os);
}
// Capture the schedule string before instrumentation. // Capture the schedule string before instrumentation.
{ {
std::ostringstream os; std::ostringstream os;
...@@ -76,7 +73,7 @@ BasicBlockProfiler::Data* BasicBlockInstrumentor::Instrument( ...@@ -76,7 +73,7 @@ BasicBlockProfiler::Data* BasicBlockInstrumentor::Instrument(
for (BasicBlockVector::iterator it = blocks->begin(); block_number < n_blocks; for (BasicBlockVector::iterator it = blocks->begin(); block_number < n_blocks;
++it, ++block_number) { ++it, ++block_number) {
BasicBlock* block = (*it); BasicBlock* block = (*it);
data->SetBlockId(block_number, block->id().ToSize()); data->SetBlockRpoNumber(block_number, block->rpo_number());
// TODO(dcarney): wire effect and control deps for load and store. // TODO(dcarney): wire effect and control deps for load and store.
// Construct increment operation. // Construct increment operation.
Node* base = graph->NewNode( Node* base = graph->NewNode(
......
...@@ -3010,7 +3010,7 @@ bool Isolate::Init(StartupDeserializer* des) { ...@@ -3010,7 +3010,7 @@ bool Isolate::Init(StartupDeserializer* des) {
set_event_logger(Logger::DefaultEventLoggerSentinel); set_event_logger(Logger::DefaultEventLoggerSentinel);
} }
if (FLAG_trace_turbo || FLAG_trace_turbo_graph) { if (FLAG_trace_turbo || FLAG_trace_turbo_graph || FLAG_turbo_profiling) {
PrintF("Concurrent recompilation has been disabled for tracing.\n"); PrintF("Concurrent recompilation has been disabled for tracing.\n");
} else if (OptimizingCompileDispatcher::Enabled()) { } else if (OptimizingCompileDispatcher::Enabled()) {
optimizing_compile_dispatcher_ = new OptimizingCompileDispatcher(this); optimizing_compile_dispatcher_ = new OptimizingCompileDispatcher(this);
......
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