[turbofan] basic block profiler
authordcarney@chromium.org <dcarney@chromium.org>
Mon, 29 Sep 2014 07:29:14 +0000 (07:29 +0000)
committerdcarney@chromium.org <dcarney@chromium.org>
Mon, 29 Sep 2014 07:29:14 +0000 (07:29 +0000)
R=titzer@chromium.org, mstarzinger@chromium.org

BUG=

Review URL: https://codereview.chromium.org/593563005

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24263 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

14 files changed:
BUILD.gn
src/basic-block-profiler.cc [new file with mode: 0644]
src/basic-block-profiler.h [new file with mode: 0644]
src/compiler/basic-block-instrumentor.cc [new file with mode: 0644]
src/compiler/basic-block-instrumentor.h [new file with mode: 0644]
src/compiler/pipeline.cc
src/compiler/schedule.h
src/d8.cc
src/flag-definitions.h
src/isolate.cc
src/isolate.h
test/cctest/cctest.gyp
test/cctest/compiler/test-basic-block-profiler.cc [new file with mode: 0644]
tools/gyp/v8.gyp

index 75aa523..8ee3a95 100644 (file)
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -440,6 +440,8 @@ source_set("v8_base") {
     "src/background-parsing-task.h",
     "src/bailout-reason.cc",
     "src/bailout-reason.h",
+    "src/basic-block-profiler.cc",
+    "src/basic-block-profiler.h",
     "src/bignum-dtoa.cc",
     "src/bignum-dtoa.h",
     "src/bignum.cc",
@@ -471,6 +473,8 @@ source_set("v8_base") {
     "src/compiler/access-builder.h",
     "src/compiler/ast-graph-builder.cc",
     "src/compiler/ast-graph-builder.h",
+    "src/compiler/basic-block-instrumentor.cc",
+    "src/compiler/basic-block-instrumentor.h",
     "src/compiler/change-lowering.cc",
     "src/compiler/change-lowering.h",
     "src/compiler/code-generator-impl.h",
diff --git a/src/basic-block-profiler.cc b/src/basic-block-profiler.cc
new file mode 100644 (file)
index 0000000..ef68ac6
--- /dev/null
@@ -0,0 +1,112 @@
+// 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/basic-block-profiler.h"
+
+namespace v8 {
+namespace internal {
+
+BasicBlockProfiler::Data::Data(size_t n_blocks)
+    : n_blocks_(n_blocks), block_ids_(n_blocks_, -1), counts_(n_blocks_, 0) {}
+
+
+BasicBlockProfiler::Data::~Data() {}
+
+
+static void InsertIntoString(OStringStream* os, std::string* string) {
+  string->insert(string->begin(), os->c_str(), &os->c_str()[os->size()]);
+}
+
+
+void BasicBlockProfiler::Data::SetCode(OStringStream* os) {
+  InsertIntoString(os, &code_);
+}
+
+
+void BasicBlockProfiler::Data::SetFunctionName(OStringStream* os) {
+  InsertIntoString(os, &function_name_);
+}
+
+
+void BasicBlockProfiler::Data::SetSchedule(OStringStream* os) {
+  InsertIntoString(os, &schedule_);
+}
+
+
+void BasicBlockProfiler::Data::SetBlockId(size_t offset, int block_id) {
+  DCHECK(offset < n_blocks_);
+  block_ids_[offset] = block_id;
+}
+
+
+uint32_t* BasicBlockProfiler::Data::GetCounterAddress(size_t offset) {
+  DCHECK(offset < n_blocks_);
+  return &counts_[offset];
+}
+
+
+void BasicBlockProfiler::Data::ResetCounts() {
+  for (size_t i = 0; i < n_blocks_; ++i) {
+    counts_[i] = 0;
+  }
+}
+
+
+BasicBlockProfiler::BasicBlockProfiler() {}
+
+
+BasicBlockProfiler::Data* BasicBlockProfiler::NewData(size_t n_blocks) {
+  Data* data = new Data(n_blocks);
+  data_list_.push_back(data);
+  return data;
+}
+
+
+BasicBlockProfiler::~BasicBlockProfiler() {
+  for (DataList::iterator i = data_list_.begin(); i != data_list_.end(); ++i) {
+    delete (*i);
+  }
+}
+
+
+void BasicBlockProfiler::ResetCounts() {
+  for (DataList::iterator i = data_list_.begin(); i != data_list_.end(); ++i) {
+    (*i)->ResetCounts();
+  }
+}
+
+
+OStream& operator<<(OStream& os, const BasicBlockProfiler& p) {
+  os << "---- Start Profiling Data ----" << endl;
+  typedef BasicBlockProfiler::DataList::const_iterator iterator;
+  for (iterator i = p.data_list_.begin(); i != p.data_list_.end(); ++i) {
+    os << **i;
+  }
+  os << "---- End Profiling Data ----" << endl;
+  return os;
+}
+
+
+OStream& operator<<(OStream& os, const BasicBlockProfiler::Data& d) {
+  const char* name = "unknown function";
+  if (!d.function_name_.empty()) {
+    name = d.function_name_.c_str();
+  }
+  if (!d.schedule_.empty()) {
+    os << "schedule for " << name << endl;
+    os << d.schedule_.c_str() << endl;
+  }
+  os << "block counts for " << name << ":" << endl;
+  for (size_t i = 0; i < d.n_blocks_; ++i) {
+    os << "block " << d.block_ids_[i] << " : " << d.counts_[i] << endl;
+  }
+  os << endl;
+  if (!d.code_.empty()) {
+    os << d.code_.c_str() << endl;
+  }
+  return os;
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/basic-block-profiler.h b/src/basic-block-profiler.h
new file mode 100644 (file)
index 0000000..e625cd2
--- /dev/null
@@ -0,0 +1,73 @@
+// 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.
+
+#ifndef V8_BASIC_BLOCK_PROFILER_H_
+#define V8_BASIC_BLOCK_PROFILER_H_
+
+#include <list>
+
+#include "src/v8.h"
+
+namespace v8 {
+namespace internal {
+
+class Schedule;
+class Graph;
+
+class BasicBlockProfiler {
+ public:
+  class Data {
+   public:
+    size_t n_blocks() const { return n_blocks_; }
+    const uint32_t* counts() const { return &counts_[0]; }
+
+    void SetCode(OStringStream* os);
+    void SetFunctionName(OStringStream* os);
+    void SetSchedule(OStringStream* os);
+    void SetBlockId(size_t offset, int block_id);
+    uint32_t* GetCounterAddress(size_t offset);
+
+   private:
+    friend class BasicBlockProfiler;
+    friend OStream& operator<<(OStream& os, const BasicBlockProfiler::Data& s);
+
+    explicit Data(size_t n_blocks);
+    ~Data();
+
+    void ResetCounts();
+
+    const size_t n_blocks_;
+    std::vector<int> block_ids_;
+    std::vector<uint32_t> counts_;
+    std::string function_name_;
+    std::string schedule_;
+    std::string code_;
+    DISALLOW_COPY_AND_ASSIGN(Data);
+  };
+
+  typedef std::list<Data*> DataList;
+
+  BasicBlockProfiler();
+  ~BasicBlockProfiler();
+
+  Data* NewData(size_t n_blocks);
+  void ResetCounts();
+
+  const DataList* data_list() { return &data_list_; }
+
+ private:
+  friend OStream& operator<<(OStream& os, const BasicBlockProfiler& s);
+
+  DataList data_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(BasicBlockProfiler);
+};
+
+OStream& operator<<(OStream& os, const BasicBlockProfiler& s);
+OStream& operator<<(OStream& os, const BasicBlockProfiler::Data& s);
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_BASIC_BLOCK_PROFILER_H_
diff --git a/src/compiler/basic-block-instrumentor.cc b/src/compiler/basic-block-instrumentor.cc
new file mode 100644 (file)
index 0000000..119a44b
--- /dev/null
@@ -0,0 +1,103 @@
+// 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-instrumentor.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"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// Find the first place to insert new nodes in a block that's already been
+// scheduled that won't upset the register allocator.
+static NodeVector::iterator FindInsertionPoint(NodeVector* nodes) {
+  NodeVector::iterator i = nodes->begin();
+  for (; i != nodes->end(); ++i) {
+    const Operator* op = (*i)->op();
+    if (OperatorProperties::IsBasicBlockBegin(op)) continue;
+    switch (op->opcode()) {
+      case IrOpcode::kParameter:
+      case IrOpcode::kPhi:
+      case IrOpcode::kEffectPhi:
+        continue;
+    }
+    break;
+  }
+  return i;
+}
+
+
+// TODO(dcarney): need to mark code as non-serializable.
+static const Operator* PointerConstant(CommonOperatorBuilder* common,
+                                       void* ptr) {
+  return kPointerSize == 8
+             ? common->Int64Constant(reinterpret_cast<intptr_t>(ptr))
+             : common->Int32Constant(
+                   static_cast<int32_t>(reinterpret_cast<intptr_t>(ptr)));
+}
+
+
+BasicBlockProfiler::Data* BasicBlockInstrumentor::Instrument(
+    CompilationInfo* info, Graph* graph, Schedule* schedule) {
+  // 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.
+  size_t n_blocks = static_cast<size_t>(schedule->RpoBlockCount()) - 1;
+  BasicBlockProfiler::Data* data =
+      info->isolate()->GetOrCreateBasicBlockProfiler()->NewData(n_blocks);
+  // Set the function name.
+  if (!info->shared_info().is_null() &&
+      info->shared_info()->name()->IsString()) {
+    OStringStream os;
+    String::cast(info->shared_info()->name())->PrintUC16(os);
+    data->SetFunctionName(&os);
+  }
+  // Capture the schedule string before instrumentation.
+  {
+    OStringStream os;
+    os << *schedule;
+    data->SetSchedule(&os);
+  }
+  // Add the increment instructions to the start of every block.
+  CommonOperatorBuilder common(graph->zone());
+  Node* zero = graph->NewNode(common.Int32Constant(0));
+  Node* one = graph->NewNode(common.Int32Constant(1));
+  MachineOperatorBuilder machine;
+  BasicBlockVector* blocks = schedule->rpo_order();
+  size_t block_number = 0;
+  for (BasicBlockVector::iterator it = blocks->begin(); block_number < n_blocks;
+       ++it, ++block_number) {
+    BasicBlock* block = (*it);
+    data->SetBlockId(block_number, block->id());
+    // TODO(dcarney): wire effect and control deps for load and store.
+    // Construct increment operation.
+    Node* base = graph->NewNode(
+        PointerConstant(&common, data->GetCounterAddress(block_number)));
+    Node* load = graph->NewNode(machine.Load(kMachUint32), base, zero);
+    Node* inc = graph->NewNode(machine.Int32Add(), load, one);
+    Node* store = graph->NewNode(
+        machine.Store(StoreRepresentation(kMachUint32, kNoWriteBarrier)), base,
+        zero, inc);
+    // Insert the new nodes.
+    static const int kArraySize = 6;
+    Node* to_insert[kArraySize] = {zero, one, base, load, inc, store};
+    int insertion_start = block_number == 0 ? 0 : 2;
+    NodeVector* nodes = &block->nodes_;
+    NodeVector::iterator insertion_point = FindInsertionPoint(nodes);
+    nodes->insert(insertion_point, &to_insert[insertion_start],
+                  &to_insert[kArraySize]);
+    // Tell the scheduler about the new nodes.
+    for (int i = insertion_start; i < kArraySize; ++i) {
+      schedule->SetBlockForNode(block, to_insert[i]);
+    }
+  }
+  return data;
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/src/compiler/basic-block-instrumentor.h b/src/compiler/basic-block-instrumentor.h
new file mode 100644 (file)
index 0000000..7edac0d
--- /dev/null
@@ -0,0 +1,32 @@
+// 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.
+
+#ifndef V8_COMPILER_BASIC_BLOCK_INSTRUMENTOR_H_
+#define V8_COMPILER_BASIC_BLOCK_INSTRUMENTOR_H_
+
+#include "src/v8.h"
+
+#include "src/basic-block-profiler.h"
+
+namespace v8 {
+namespace internal {
+
+class CompilationInfo;
+
+namespace compiler {
+
+class Graph;
+class Schedule;
+
+class BasicBlockInstrumentor : public AllStatic {
+ public:
+  static BasicBlockProfiler::Data* Instrument(CompilationInfo* info,
+                                              Graph* graph, Schedule* schedule);
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif
index 87a5370..333382a 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "src/base/platform/elapsed-timer.h"
 #include "src/compiler/ast-graph-builder.h"
+#include "src/compiler/basic-block-instrumentor.h"
 #include "src/compiler/change-lowering.h"
 #include "src/compiler/code-generator.h"
 #include "src/compiler/graph-replay.h"
@@ -315,6 +316,8 @@ Handle<Code> Pipeline::GenerateCode() {
     VerifyAndPrintGraph(&graph, "Lowered generic");
   }
 
+  source_positions.RemoveDecorator();
+
   Handle<Code> code = Handle<Code>::null();
   {
     // Compute a schedule.
@@ -381,6 +384,11 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, Graph* graph,
   DCHECK_NOT_NULL(schedule);
   CHECK(SupportedBackend());
 
+  BasicBlockProfiler::Data* profiler_data = NULL;
+  if (FLAG_turbo_profiling) {
+    profiler_data = BasicBlockInstrumentor::Instrument(info_, graph, schedule);
+  }
+
   InstructionSequence sequence(linkage, graph, schedule);
 
   // Select and schedule instructions covering the scheduled graph.
@@ -417,7 +425,15 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, Graph* graph,
 
   // Generate native sequence.
   CodeGenerator generator(&sequence);
-  return generator.GenerateCode();
+  Handle<Code> code = generator.GenerateCode();
+  if (profiler_data != NULL) {
+#if ENABLE_DISASSEMBLER
+    OStringStream os;
+    code->Disassemble(NULL, os);
+    profiler_data->SetCode(&os);
+#endif
+  }
+  return code;
 }
 
 
index 0ea499c..0094d57 100644 (file)
@@ -22,6 +22,7 @@ namespace internal {
 namespace compiler {
 
 class BasicBlock;
+class BasicBlockInstrumentor;
 class Graph;
 class ConstructScheduleData;
 class CodeGenerator;  // Because of a namespace bug in clang.
@@ -279,6 +280,7 @@ class Schedule : public GenericGraph<BasicBlock> {
 
  private:
   friend class ScheduleVisualizer;
+  friend class BasicBlockInstrumentor;
 
   void SetControlInput(BasicBlock* block, Node* node) {
     block->control_input_ = node;
index 9db7744..d1929b0 100644 (file)
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -46,6 +46,7 @@
 #include "src/base/logging.h"
 #include "src/base/platform/platform.h"
 #include "src/base/sys-info.h"
+#include "src/basic-block-profiler.h"
 #include "src/d8-debug.h"
 #include "src/debug.h"
 #include "src/natives.h"
@@ -1700,6 +1701,14 @@ int Shell::Main(int argc, char* argv[]) {
       RunShell(isolate);
     }
   }
+#ifndef V8_SHARED
+  // Dump basic block profiling data.
+  if (i::BasicBlockProfiler* profiler =
+          reinterpret_cast<i::Isolate*>(isolate)->basic_block_profiler()) {
+    i::OFStream os(stdout);
+    os << *profiler;
+  }
+#endif  // !V8_SHARED
   isolate->Dispose();
   V8::Dispose();
   V8::ShutdownPlatform();
index 6c90912..672f2b6 100644 (file)
@@ -345,6 +345,7 @@ DEFINE_BOOL(turbo_deoptimization, false, "enable deoptimization in TurboFan")
 DEFINE_BOOL(turbo_inlining, false, "enable inlining in TurboFan")
 DEFINE_BOOL(trace_turbo_inlining, false, "trace TurboFan inlining")
 DEFINE_IMPLICATION(turbo_inlining, turbo_types)
+DEFINE_BOOL(turbo_profiling, false, "enable profiling in TurboFan")
 
 DEFINE_INT(typed_array_max_size_in_heap, 64,
            "threshold for in-heap typed array")
index c6a8b81..edc8326 100644 (file)
@@ -10,6 +10,7 @@
 #include "src/base/platform/platform.h"
 #include "src/base/sys-info.h"
 #include "src/base/utils/random-number-generator.h"
+#include "src/basic-block-profiler.h"
 #include "src/bootstrapper.h"
 #include "src/codegen.h"
 #include "src/compilation-cache.h"
@@ -1516,7 +1517,8 @@ Isolate::Isolate()
       num_sweeper_threads_(0),
       stress_deopt_count_(0),
       next_optimization_id_(0),
-      use_counter_callback_(NULL) {
+      use_counter_callback_(NULL),
+      basic_block_profiler_(NULL) {
   {
     base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
     CHECK(thread_data_table_);
@@ -1640,6 +1642,10 @@ void Isolate::Deinit() {
       delete runtime_profiler_;
       runtime_profiler_ = NULL;
     }
+
+    delete basic_block_profiler_;
+    basic_block_profiler_ = NULL;
+
     heap_.TearDown();
     logger_->TearDown();
 
@@ -2363,6 +2369,14 @@ void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) {
 }
 
 
+BasicBlockProfiler* Isolate::GetOrCreateBasicBlockProfiler() {
+  if (basic_block_profiler_ == NULL) {
+    basic_block_profiler_ = new BasicBlockProfiler();
+  }
+  return basic_block_profiler_;
+}
+
+
 bool StackLimitCheck::JsHasOverflowed() const {
   StackGuard* stack_guard = isolate_->stack_guard();
 #ifdef USE_SIMULATOR
index a92554e..9ea3074 100644 (file)
@@ -32,6 +32,7 @@ class RandomNumberGenerator;
 
 namespace internal {
 
+class BasicBlockProfiler;
 class Bootstrapper;
 class CallInterfaceDescriptorData;
 class CodeGenerator;
@@ -1107,6 +1108,9 @@ class Isolate {
   void SetUseCounterCallback(v8::Isolate::UseCounterCallback callback);
   void CountUsage(v8::Isolate::UseCounterFeature feature);
 
+  BasicBlockProfiler* GetOrCreateBasicBlockProfiler();
+  BasicBlockProfiler* basic_block_profiler() { return basic_block_profiler_; }
+
   static Isolate* NewForTesting() { return new Isolate(); }
 
  private:
@@ -1327,6 +1331,7 @@ class Isolate {
   List<CallCompletedCallback> call_completed_callbacks_;
 
   v8::Isolate::UseCounterCallback use_counter_callback_;
+  BasicBlockProfiler* basic_block_profiler_;
 
   friend class ExecutionAccess;
   friend class HandleScopeImplementer;
index 6a57763..f993d26 100644 (file)
@@ -53,6 +53,7 @@
         'compiler/graph-tester.h',
         'compiler/simplified-graph-builder.cc',
         'compiler/simplified-graph-builder.h',
+        'compiler/test-basic-block-profiler.cc',
         'compiler/test-branch-combine.cc',
         'compiler/test-changes-lowering.cc',
         'compiler/test-codegen-deopt.cc',
diff --git a/test/cctest/compiler/test-basic-block-profiler.cc b/test/cctest/compiler/test-basic-block-profiler.cc
new file mode 100644 (file)
index 0000000..703fc17
--- /dev/null
@@ -0,0 +1,114 @@
+// 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/v8.h"
+
+#include "src/basic-block-profiler.h"
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/codegen-tester.h"
+
+#if V8_TURBOFAN_TARGET
+
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+
+typedef RawMachineAssembler::Label MLabel;
+
+class BasicBlockProfilerTest : public RawMachineAssemblerTester<int32_t> {
+ public:
+  BasicBlockProfilerTest() : RawMachineAssemblerTester<int32_t>(kMachInt32) {
+    FLAG_turbo_profiling = true;
+  }
+
+  void ResetCounts() { isolate()->basic_block_profiler()->ResetCounts(); }
+
+  void Expect(size_t size, uint32_t* expected) {
+    CHECK_NE(NULL, isolate()->basic_block_profiler());
+    const BasicBlockProfiler::DataList* l =
+        isolate()->basic_block_profiler()->data_list();
+    CHECK_NE(0, static_cast<int>(l->size()));
+    const BasicBlockProfiler::Data* data = l->back();
+    CHECK_EQ(static_cast<int>(size), static_cast<int>(data->n_blocks()));
+    const uint32_t* counts = data->counts();
+    for (size_t i = 0; i < size; ++i) {
+      CHECK_EQ(static_cast<int>(expected[i]), static_cast<int>(counts[i]));
+    }
+  }
+};
+
+
+TEST(ProfileDiamond) {
+  BasicBlockProfilerTest m;
+
+  MLabel blocka, blockb, end;
+  m.Branch(m.Parameter(0), &blocka, &blockb);
+  m.Bind(&blocka);
+  m.Goto(&end);
+  m.Bind(&blockb);
+  m.Goto(&end);
+  m.Bind(&end);
+  m.Return(m.Int32Constant(0));
+
+  m.GenerateCode();
+  {
+    uint32_t expected[] = {0, 0, 0, 0};
+    m.Expect(arraysize(expected), expected);
+  }
+
+  m.Call(0);
+  {
+    uint32_t expected[] = {1, 1, 0, 1};
+    m.Expect(arraysize(expected), expected);
+  }
+
+  m.ResetCounts();
+
+  m.Call(1);
+  {
+    uint32_t expected[] = {1, 0, 1, 1};
+    m.Expect(arraysize(expected), expected);
+  }
+
+  m.Call(0);
+  {
+    uint32_t expected[] = {2, 1, 1, 2};
+    m.Expect(arraysize(expected), expected);
+  }
+}
+
+
+TEST(ProfileLoop) {
+  BasicBlockProfilerTest m;
+
+  MLabel header, body, end;
+  Node* one = m.Int32Constant(1);
+  m.Goto(&header);
+
+  m.Bind(&header);
+  Node* count = m.Phi(kMachInt32, m.Parameter(0), one);
+  m.Branch(count, &body, &end);
+
+  m.Bind(&body);
+  count->ReplaceInput(1, m.Int32Sub(count, one));
+  m.Goto(&header);
+
+  m.Bind(&end);
+  m.Return(one);
+
+  m.GenerateCode();
+  {
+    uint32_t expected[] = {0, 0, 0, 0};
+    m.Expect(arraysize(expected), expected);
+  }
+
+  uint32_t runs[] = {0, 1, 500, 10000};
+  for (size_t i = 0; i < arraysize(runs); i++) {
+    m.ResetCounts();
+    CHECK_EQ(1, m.Call(static_cast<int>(runs[i])));
+    uint32_t expected[] = {1, runs[i] + 1, runs[i], 1};
+    m.Expect(arraysize(expected), expected);
+  }
+}
+
+#endif  // V8_TURBOFAN_TARGET
index b088bfc..22a1564 100644 (file)
         '../../src/background-parsing-task.h',
         '../../src/bailout-reason.cc',
         '../../src/bailout-reason.h',
+        '../../src/basic-block-profiler.cc',
+        '../../src/basic-block-profiler.h',
         '../../src/bignum-dtoa.cc',
         '../../src/bignum-dtoa.h',
         '../../src/bignum.cc',
         '../../src/compiler/access-builder.h',
         '../../src/compiler/ast-graph-builder.cc',
         '../../src/compiler/ast-graph-builder.h',
+        '../../src/compiler/basic-block-instrumentor.cc',
+        '../../src/compiler/basic-block-instrumentor.h',
         '../../src/compiler/change-lowering.cc',
         '../../src/compiler/change-lowering.h',
         '../../src/compiler/code-generator-impl.h',