LCOV - code coverage report
Current view: top level - src/compiler - basic-block-instrumentor.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 32 32 100.0 %
Date: 2019-04-17 Functions: 3 3 100.0 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/basic-block-instrumentor.h"
       6             : 
       7             : #include <sstream>
       8             : 
       9             : #include "src/compiler/common-operator.h"
      10             : #include "src/compiler/graph.h"
      11             : #include "src/compiler/machine-operator.h"
      12             : #include "src/compiler/node.h"
      13             : #include "src/compiler/operator-properties.h"
      14             : #include "src/compiler/schedule.h"
      15             : #include "src/objects-inl.h"
      16             : #include "src/optimized-compilation-info.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : namespace compiler {
      21             : 
      22             : // Find the first place to insert new nodes in a block that's already been
      23             : // scheduled that won't upset the register allocator.
      24          48 : static NodeVector::iterator FindInsertionPoint(BasicBlock* block) {
      25             :   NodeVector::iterator i = block->begin();
      26          76 :   for (; i != block->end(); ++i) {
      27          44 :     const Operator* op = (*i)->op();
      28          44 :     if (OperatorProperties::IsBasicBlockBegin(op)) continue;
      29             :     switch (op->opcode()) {
      30             :       case IrOpcode::kParameter:
      31             :       case IrOpcode::kPhi:
      32             :       case IrOpcode::kEffectPhi:
      33             :         continue;
      34             :     }
      35             :     break;
      36             :   }
      37          48 :   return i;
      38             : }
      39             : 
      40             : 
      41             : // TODO(dcarney): need to mark code as non-serializable.
      42             : static const Operator* PointerConstant(CommonOperatorBuilder* common,
      43             :                                        intptr_t ptr) {
      44             :   return kSystemPointerSize == 8
      45             :              ? common->Int64Constant(ptr)
      46          48 :              : common->Int32Constant(static_cast<int32_t>(ptr));
      47             : }
      48             : 
      49           8 : BasicBlockProfiler::Data* BasicBlockInstrumentor::Instrument(
      50             :     OptimizedCompilationInfo* info, Graph* graph, Schedule* schedule,
      51             :     Isolate* isolate) {
      52             :   // Basic block profiling disables concurrent compilation, so handle deref is
      53             :   // fine.
      54             :   AllowHandleDereference allow_handle_dereference;
      55             :   // Skip the exit block in profiles, since the register allocator can't handle
      56             :   // it and entry into it means falling off the end of the function anyway.
      57           8 :   size_t n_blocks = static_cast<size_t>(schedule->RpoBlockCount()) - 1;
      58           8 :   BasicBlockProfiler::Data* data = BasicBlockProfiler::Get()->NewData(n_blocks);
      59             :   // Set the function name.
      60          16 :   data->SetFunctionName(info->GetDebugName());
      61             :   // Capture the schedule string before instrumentation.
      62             :   {
      63          16 :     std::ostringstream os;
      64           8 :     os << *schedule;
      65           8 :     data->SetSchedule(&os);
      66             :   }
      67             :   // Add the increment instructions to the start of every block.
      68           8 :   CommonOperatorBuilder common(graph->zone());
      69           8 :   Node* zero = graph->NewNode(common.Int32Constant(0));
      70           8 :   Node* one = graph->NewNode(common.Int32Constant(1));
      71           8 :   MachineOperatorBuilder machine(graph->zone());
      72             :   BasicBlockVector* blocks = schedule->rpo_order();
      73             :   size_t block_number = 0;
      74         104 :   for (BasicBlockVector::iterator it = blocks->begin(); block_number < n_blocks;
      75             :        ++it, ++block_number) {
      76          48 :     BasicBlock* block = (*it);
      77          48 :     data->SetBlockRpoNumber(block_number, block->rpo_number());
      78             :     // TODO(dcarney): wire effect and control deps for load and store.
      79             :     // Construct increment operation.
      80          48 :     Node* base = graph->NewNode(
      81             :         PointerConstant(&common, data->GetCounterAddress(block_number)));
      82          48 :     Node* load = graph->NewNode(machine.Load(MachineType::Uint32()), base, zero,
      83             :                                 graph->start(), graph->start());
      84          48 :     Node* inc = graph->NewNode(machine.Int32Add(), load, one);
      85             :     Node* store =
      86          96 :         graph->NewNode(machine.Store(StoreRepresentation(
      87             :                            MachineRepresentation::kWord32, kNoWriteBarrier)),
      88             :                        base, zero, inc, graph->start(), graph->start());
      89             :     // Insert the new nodes.
      90             :     static const int kArraySize = 6;
      91          48 :     Node* to_insert[kArraySize] = {zero, one, base, load, inc, store};
      92          48 :     int insertion_start = block_number == 0 ? 0 : 2;
      93          48 :     NodeVector::iterator insertion_point = FindInsertionPoint(block);
      94          48 :     block->InsertNodes(insertion_point, &to_insert[insertion_start],
      95             :                        &to_insert[kArraySize]);
      96             :     // Tell the scheduler about the new nodes.
      97         464 :     for (int i = insertion_start; i < kArraySize; ++i) {
      98         208 :       schedule->SetBlockForNode(block, to_insert[i]);
      99             :     }
     100             :   }
     101           8 :   return data;
     102             : }
     103             : 
     104             : }  // namespace compiler
     105             : }  // namespace internal
     106      121996 : }  // namespace v8

Generated by: LCOV version 1.10