LCOV - code coverage report
Current view: top level - src/compiler - basic-block-instrumentor.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 32 35 91.4 %
Date: 2017-04-26 Functions: 2 2 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/compilation-info.h"
      10             : #include "src/compiler/common-operator.h"
      11             : #include "src/compiler/graph.h"
      12             : #include "src/compiler/machine-operator.h"
      13             : #include "src/compiler/node.h"
      14             : #include "src/compiler/operator-properties.h"
      15             : #include "src/compiler/schedule.h"
      16             : #include "src/objects-inl.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          56 : static NodeVector::iterator FindInsertionPoint(BasicBlock* block) {
      25             :   NodeVector::iterator i = block->begin();
      26         133 :   for (; i != block->end(); ++i) {
      27          98 :     const Operator* op = (*i)->op();
      28          49 :     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          56 :   return i;
      38             : }
      39             : 
      40             : 
      41             : // TODO(dcarney): need to mark code as non-serializable.
      42             : static const Operator* PointerConstant(CommonOperatorBuilder* common,
      43             :                                        void* ptr) {
      44             :   return kPointerSize == 8
      45             :              ? common->Int64Constant(reinterpret_cast<intptr_t>(ptr))
      46             :              : common->Int32Constant(
      47          56 :                    static_cast<int32_t>(reinterpret_cast<intptr_t>(ptr)));
      48             : }
      49             : 
      50             : 
      51          14 : BasicBlockProfiler::Data* BasicBlockInstrumentor::Instrument(
      52         154 :     CompilationInfo* info, Graph* graph, Schedule* schedule) {
      53             :   // Skip the exit block in profiles, since the register allocator can't handle
      54             :   // it and entry into it means falling off the end of the function anyway.
      55          14 :   size_t n_blocks = static_cast<size_t>(schedule->RpoBlockCount()) - 1;
      56             :   BasicBlockProfiler::Data* data =
      57          14 :       info->isolate()->GetOrCreateBasicBlockProfiler()->NewData(n_blocks);
      58             :   // Set the function name.
      59          14 :   if (info->has_shared_info() && info->shared_info()->name()->IsString()) {
      60           0 :     std::ostringstream os;
      61           0 :     String::cast(info->shared_info()->name())->PrintUC16(os);
      62           0 :     data->SetFunctionName(&os);
      63             :   }
      64             :   // Capture the schedule string before instrumentation.
      65             :   {
      66          14 :     std::ostringstream os;
      67          14 :     os << *schedule;
      68          14 :     data->SetSchedule(&os);
      69             :   }
      70             :   // Add the increment instructions to the start of every block.
      71          14 :   CommonOperatorBuilder common(graph->zone());
      72          14 :   Node* zero = graph->NewNode(common.Int32Constant(0));
      73          14 :   Node* one = graph->NewNode(common.Int32Constant(1));
      74          14 :   MachineOperatorBuilder machine(graph->zone());
      75             :   BasicBlockVector* blocks = schedule->rpo_order();
      76             :   size_t block_number = 0;
      77          70 :   for (BasicBlockVector::iterator it = blocks->begin(); block_number < n_blocks;
      78             :        ++it, ++block_number) {
      79          56 :     BasicBlock* block = (*it);
      80          56 :     data->SetBlockId(block_number, block->id().ToSize());
      81             :     // TODO(dcarney): wire effect and control deps for load and store.
      82             :     // Construct increment operation.
      83             :     Node* base = graph->NewNode(
      84          56 :         PointerConstant(&common, data->GetCounterAddress(block_number)));
      85             :     Node* load = graph->NewNode(machine.Load(MachineType::Uint32()), base, zero,
      86          56 :                                 graph->start(), graph->start());
      87          56 :     Node* inc = graph->NewNode(machine.Int32Add(), load, one);
      88             :     Node* store =
      89             :         graph->NewNode(machine.Store(StoreRepresentation(
      90             :                            MachineRepresentation::kWord32, kNoWriteBarrier)),
      91         112 :                        base, zero, inc, graph->start(), graph->start());
      92             :     // Insert the new nodes.
      93             :     static const int kArraySize = 6;
      94          56 :     Node* to_insert[kArraySize] = {zero, one, base, load, inc, store};
      95          56 :     int insertion_start = block_number == 0 ? 0 : 2;
      96          56 :     NodeVector::iterator insertion_point = FindInsertionPoint(block);
      97             :     block->InsertNodes(insertion_point, &to_insert[insertion_start],
      98          56 :                        &to_insert[kArraySize]);
      99             :     // Tell the scheduler about the new nodes.
     100         308 :     for (int i = insertion_start; i < kArraySize; ++i) {
     101         252 :       schedule->SetBlockForNode(block, to_insert[i]);
     102             :     }
     103             :   }
     104          14 :   return data;
     105             : }
     106             : 
     107             : }  // namespace compiler
     108             : }  // namespace internal
     109             : }  // namespace v8

Generated by: LCOV version 1.10