Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Unified Diff: src/compiler/basic-block-profiler.cc

Issue 593563005: [turbofan] basic block profiler (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/compiler/basic-block-profiler.cc
diff --git a/src/compiler/basic-block-profiler.cc b/src/compiler/basic-block-profiler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7207c8d72785077fb9da810705f81832fdb16a0e
--- /dev/null
+++ b/src/compiler/basic-block-profiler.cc
@@ -0,0 +1,182 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/basic-block-profiler.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/graph.h"
+#include "src/compiler/machine-operator.h"
+#include "src/compiler/operator-properties-inl.h"
+#include "src/compiler/schedule.h"
+#include "src/global-handles.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+BasicBlockProfiler::Data::Data(int n_blocks, int* block_ids, uint32_t* counts,
titzer 2014/09/23 14:14:09 Can you make the constructor allocate the block_id
+ OStringStream* function_name,
+ OStringStream* schedule_stream)
+ : n_blocks_(n_blocks),
+ block_ids_(block_ids),
+ counts_(counts),
+ function_name_(function_name),
+ schedule_stream_(schedule_stream),
+ code_stream_(NULL) {}
+
+
+BasicBlockProfiler::Data::~Data() {
+ delete[] block_ids_;
+ delete[] counts_;
+ delete function_name_;
+ delete schedule_stream_;
+ delete code_stream_;
+}
+
+
+void BasicBlockProfiler::Data::SetCode(Handle<Code> code) {
+ DCHECK_EQ(NULL, code_stream_);
+#if ENABLE_DISASSEMBLER
+// TODO(dcarney): reenable this once code printing is fixed.
titzer 2014/09/23 14:14:09 What's broken with code printing?
+// code_stream_ = new OStringStream();
+// code->Disassemble(NULL, *code_stream_);
+#endif
+}
+
+
+void BasicBlockProfiler::Data::DumpProfilingData() {
titzer 2014/09/23 14:14:09 Can you use OFStream here? It seems to be the way
+ const char* name = "unknown function";
+ if (function_name_ != NULL) {
+ name = function_name_->c_str();
+ }
+ fprintf(stderr, "schedule for %s:\n", name);
+ if (schedule_stream_ != NULL) {
+ fprintf(stderr, "%s\n", schedule_stream_->c_str());
+ }
+ fprintf(stderr, "block counts for %s:\n", name);
+ for (int i = 0; i < n_blocks_; ++i) {
+ fprintf(stderr, "block %d : %u\n", block_ids_[i], counts_[i]);
+ }
+ fprintf(stderr, "\n");
+ if (code_stream_ != NULL) {
+ fprintf(stderr, "%s\n", code_stream_->c_str());
+ }
+}
+
+
+void BasicBlockProfiler::Data::ResetCounts() {
+ for (int i = 0; i < n_blocks_; ++i) {
+ counts_[i] = 0;
+ }
+}
+
+
+BasicBlockProfiler::BasicBlockProfiler() {}
+
+
+BasicBlockProfiler::~BasicBlockProfiler() {
+ DumpProfilingData();
+ TearDown();
+}
+
+
+void BasicBlockProfiler::TearDown() {
+ for (DataList::iterator i = data_list_.begin(); i != data_list_.end(); ++i) {
+ delete (*i);
+ }
+ data_list_.clear();
+}
+
+
+void BasicBlockProfiler::ResetCounts() {
+ for (DataList::iterator i = data_list_.begin(); i != data_list_.end(); ++i) {
+ (*i)->ResetCounts();
+ }
+}
+
+
+void BasicBlockProfiler::DumpProfilingData() {
+ fprintf(stderr, "---- Start Profiling Data ----\n");
+ for (DataList::iterator i = data_list_.begin(); i != data_list_.end(); ++i) {
+ (*i)->DumpProfilingData();
+ }
+ fprintf(stderr, "---- End Profiling Data ----\n");
+}
+
+
+BasicBlockProfiler::Data* BasicBlockProfiler::Profile(CompilationInfo* info,
+ Graph* graph,
+ Schedule* schedule) {
+ OStringStream* schedule_stream = new OStringStream();
+ (*schedule_stream) << *schedule;
+ int n_blocks = schedule->RpoBlockCount();
+ // Create a backing store for the count data.
+ uint32_t* counts = new uint32_t[n_blocks];
+ for (int i = 0; i < n_blocks; ++i) {
+ counts[i] = 0;
+ }
+ // Add the increment instructions to the start of every block.
+ CommonOperatorBuilder common(graph->zone());
+ intptr_t base_address = reinterpret_cast<intptr_t>(counts);
+ // TODO(dcarney): need to mark code as non-serializable.
+ const Operator* base_op =
+ kPointerSize == 8 ? common.Int64Constant(base_address)
+ : common.Int32Constant(static_cast<int>(base_address));
+ Node* base = graph->NewNode(base_op);
+ Node* one = graph->NewNode(common.Int32Constant(1));
+ MachineOperatorBuilder machine;
+ StoreRepresentation representation(kMachUint32, kNoWriteBarrier);
+ const Operator* load_op = machine.Load(kMachUint32);
+ const Operator* store_op = machine.Store(representation);
+ const Operator* add_op = machine.Int32Add();
+ BasicBlockVector* blocks = schedule->rpo_order();
+ int block_number = 0;
+ int* block_ids = new int[n_blocks];
+ for (BasicBlockVector::iterator it = blocks->begin(); it != blocks->end();
+ ++it, ++block_number) {
+ BasicBlock* block = (*it);
+ block_ids[block_number] = block->id();
titzer 2014/09/23 14:14:09 Pull the body of this loop out into its own functi
+ // Construct increment operation.
+ int index_value = sizeof(counts[0]) * block_number;
+ Node* index = graph->NewNode(common.Int32Constant(index_value));
+ // TODO(dcarney): wire effect and control deps for load and store.
+ Node* load = graph->NewNode(load_op, base, index);
+ Node* inc = graph->NewNode(add_op, load, one);
+ Node* store = graph->NewNode(store_op, base, index, inc);
+ // skip parameters and phis when inserting.
+ NodeVector& nodes = block->nodes_;
+ NodeVector::iterator j = nodes.begin();
+ for (; j != nodes.end(); ++j) {
+ const Operator* op = (*j)->op();
+ if (OperatorProperties::IsBasicBlockBegin(op)) continue;
+ switch (op->opcode()) {
+ case IrOpcode::kParameter:
+ case IrOpcode::kPhi:
+ case IrOpcode::kEffectPhi:
+ continue;
+ }
+ break;
+ }
+ static const int kArraySize = 6;
+ Node* to_insert[kArraySize] = {base, one, index, load, inc, store};
+ int insertion_start = block_number == 0 ? 0 : 2;
+ nodes.insert(j, &to_insert[insertion_start], &to_insert[kArraySize]);
+ for (int j = insertion_start; j < kArraySize; ++j) {
+ schedule->SetBlockForNode(block, to_insert[j]);
+ }
+ }
+ OStringStream* function_name = NULL;
+ if (!info->shared_info().is_null() &&
+ info->shared_info()->name()->IsString()) {
+ function_name = new OStringStream();
+ String::cast(info->shared_info()->name())->PrintUC16(*function_name);
+ }
+ Data* data =
+ new Data(n_blocks, block_ids, counts, function_name, schedule_stream);
+ data_list_.push_back(data);
+ return data;
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8

Powered by Google App Engine
This is Rietveld 408576698