// 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 <sstream>

#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(BasicBlock* block) {
  NodeVector::iterator i = block->begin();
  for (; i != block->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()) {
    std::ostringstream os;
    String::cast(info->shared_info()->name())->PrintUC16(os);
    data->SetFunctionName(&os);
  }
  // Capture the schedule string before instrumentation.
  {
    std::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(graph->zone());
  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().ToSize());
    // 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::iterator insertion_point = FindInsertionPoint(block);
    block->InsertNodes(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
