// Copyright 2015 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/interpreter/interpreter.h"

#include <fstream>
#include <memory>

#include "builtins-generated/bytecodes-builtins-list.h"
#include "src/ast/prettyprinter.h"
#include "src/codegen/compiler.h"
#include "src/codegen/unoptimized-compilation-info.h"
#include "src/init/bootstrapper.h"
#include "src/init/setup-isolate.h"
#include "src/interpreter/bytecode-generator.h"
#include "src/interpreter/bytecodes.h"
#include "src/logging/counters-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/shared-function-info.h"
#include "src/objects/slots.h"
#include "src/objects/visitors.h"
#include "src/parsing/parse-info.h"
#include "src/snapshot/snapshot.h"
#include "src/utils/ostreams.h"

namespace v8 {
namespace internal {
namespace interpreter {

class InterpreterCompilationJob final : public UnoptimizedCompilationJob {
 public:
  InterpreterCompilationJob(
      ParseInfo* parse_info, FunctionLiteral* literal,
      AccountingAllocator* allocator,
      std::vector<FunctionLiteral*>* eager_inner_literals);

 protected:
  Status ExecuteJobImpl() final;
  Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
                         Isolate* isolate) final;

 private:
  BytecodeGenerator* generator() { return &generator_; }

  Zone zone_;
  UnoptimizedCompilationInfo compilation_info_;
  BytecodeGenerator generator_;

  DISALLOW_COPY_AND_ASSIGN(InterpreterCompilationJob);
};

Interpreter::Interpreter(Isolate* isolate)
    : isolate_(isolate),
      interpreter_entry_trampoline_instruction_start_(kNullAddress) {
  memset(dispatch_table_, 0, sizeof(dispatch_table_));

  if (FLAG_trace_ignition_dispatches) {
    static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1;
    bytecode_dispatch_counters_table_.reset(
        new uintptr_t[kBytecodeCount * kBytecodeCount]);
    memset(bytecode_dispatch_counters_table_.get(), 0,
           sizeof(uintptr_t) * kBytecodeCount * kBytecodeCount);
  }
}

namespace {

int BuiltinIndexFromBytecode(Bytecode bytecode, OperandScale operand_scale) {
  int index = BytecodeOperands::OperandScaleAsIndex(operand_scale) *
                  kNumberOfBytecodeHandlers +
              static_cast<int>(bytecode);
  int offset = kBytecodeToBuiltinsMapping[index];
  return offset >= 0 ? Builtins::kFirstBytecodeHandler + offset
                     : Builtins::kIllegalHandler;
}

}  // namespace

Code Interpreter::GetBytecodeHandler(Bytecode bytecode,
                                     OperandScale operand_scale) {
  int builtin_index = BuiltinIndexFromBytecode(bytecode, operand_scale);
  Builtins* builtins = isolate_->builtins();
  return builtins->builtin(builtin_index);
}

void Interpreter::SetBytecodeHandler(Bytecode bytecode,
                                     OperandScale operand_scale, Code handler) {
  DCHECK(handler.kind() == Code::BYTECODE_HANDLER);
  size_t index = GetDispatchTableIndex(bytecode, operand_scale);
  dispatch_table_[index] = handler.InstructionStart();
}

// static
size_t Interpreter::GetDispatchTableIndex(Bytecode bytecode,
                                          OperandScale operand_scale) {
  static const size_t kEntriesPerOperandScale = 1u << kBitsPerByte;
  size_t index = static_cast<size_t>(bytecode);
  return index + BytecodeOperands::OperandScaleAsIndex(operand_scale) *
                     kEntriesPerOperandScale;
}

void Interpreter::IterateDispatchTable(RootVisitor* v) {
  if (FLAG_embedded_builtins && !isolate_->serializer_enabled() &&
      isolate_->embedded_blob() != nullptr) {
// If builtins are embedded (and we're not generating a snapshot), then
// every bytecode handler will be off-heap, so there's no point iterating
// over them.
#ifdef DEBUG
    for (int i = 0; i < kDispatchTableSize; i++) {
      Address code_entry = dispatch_table_[i];
      CHECK(code_entry == kNullAddress ||
            InstructionStream::PcIsOffHeap(isolate_, code_entry));
    }
#endif  // DEBUG
    return;
  }

  for (int i = 0; i < kDispatchTableSize; i++) {
    Address code_entry = dispatch_table_[i];
    // Skip over off-heap bytecode handlers since they will never move.
    if (InstructionStream::PcIsOffHeap(isolate_, code_entry)) continue;

    // TODO(jkummerow): Would it hurt to simply do:
    // if (code_entry == kNullAddress) continue;
    Code code;
    if (code_entry != kNullAddress) {
      code = Code::GetCodeFromTargetAddress(code_entry);
    }
    Code old_code = code;
    v->VisitRootPointer(Root::kDispatchTable, nullptr, FullObjectSlot(&code));
    if (code != old_code) {
      dispatch_table_[i] = code.entry();
    }
  }
}

int Interpreter::InterruptBudget() {
  return FLAG_interrupt_budget;
}

namespace {

void MaybePrintAst(ParseInfo* parse_info,
                   UnoptimizedCompilationInfo* compilation_info) {
  if (!FLAG_print_ast) return;

  StdoutStream os;
  std::unique_ptr<char[]> name = compilation_info->literal()->GetDebugName();
  os << "[generating bytecode for function: " << name.get() << "]" << std::endl;
#ifdef DEBUG
  os << "--- AST ---" << std::endl
     << AstPrinter(parse_info->stack_limit())
            .PrintProgram(compilation_info->literal())
     << std::endl;
#endif  // DEBUG
}

bool ShouldPrintBytecode(Handle<SharedFunctionInfo> shared) {
  if (!FLAG_print_bytecode) return false;

  // Checks whether function passed the filter.
  if (shared->is_toplevel()) {
    Vector<const char> filter = CStrVector(FLAG_print_bytecode_filter);
    return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*');
  } else {
    return shared->PassesFilter(FLAG_print_bytecode_filter);
  }
}

}  // namespace

InterpreterCompilationJob::InterpreterCompilationJob(
    ParseInfo* parse_info, FunctionLiteral* literal,
    AccountingAllocator* allocator,
    std::vector<FunctionLiteral*>* eager_inner_literals)
    : UnoptimizedCompilationJob(parse_info->stack_limit(), parse_info,
                                &compilation_info_),
      zone_(allocator, ZONE_NAME),
      compilation_info_(&zone_, parse_info, literal),
      generator_(&compilation_info_, parse_info->ast_string_constants(),
                 eager_inner_literals) {}

InterpreterCompilationJob::Status InterpreterCompilationJob::ExecuteJobImpl() {
  RuntimeCallTimerScope runtimeTimerScope(
      parse_info()->runtime_call_stats(),
      parse_info()->on_background_thread()
          ? RuntimeCallCounterId::kCompileBackgroundIgnition
          : RuntimeCallCounterId::kCompileIgnition);
  // TODO(lpy): add support for background compilation RCS trace.
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileIgnition");

  // Print AST if flag is enabled. Note, if compiling on a background thread
  // then ASTs from different functions may be intersperse when printed.
  MaybePrintAst(parse_info(), compilation_info());

  generator()->GenerateBytecode(stack_limit());

  if (generator()->HasStackOverflow()) {
    return FAILED;
  }
  return SUCCEEDED;
}

InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl(
    Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
  RuntimeCallTimerScope runtimeTimerScope(
      parse_info()->runtime_call_stats(),
      RuntimeCallCounterId::kCompileIgnitionFinalization);
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.CompileIgnitionFinalization");

  Handle<BytecodeArray> bytecodes =
      generator()->FinalizeBytecode(isolate, parse_info()->script());
  if (generator()->HasStackOverflow()) {
    return FAILED;
  }

  if (ShouldPrintBytecode(shared_info)) {
    StdoutStream os;
    std::unique_ptr<char[]> name =
        compilation_info()->literal()->GetDebugName();
    os << "[generated bytecode for function: " << name.get() << "]"
       << std::endl;
    bytecodes->Disassemble(os);
    os << std::flush;
  }

  compilation_info()->SetBytecodeArray(bytecodes);
  return SUCCEEDED;
}

std::unique_ptr<UnoptimizedCompilationJob> Interpreter::NewCompilationJob(
    ParseInfo* parse_info, FunctionLiteral* literal,
    AccountingAllocator* allocator,
    std::vector<FunctionLiteral*>* eager_inner_literals) {
  return base::make_unique<InterpreterCompilationJob>(
      parse_info, literal, allocator, eager_inner_literals);
}

void Interpreter::ForEachBytecode(
    const std::function<void(Bytecode, OperandScale)>& f) {
  constexpr OperandScale kOperandScales[] = {
#define VALUE(Name, _) OperandScale::k##Name,
      OPERAND_SCALE_LIST(VALUE)
#undef VALUE
  };

  for (OperandScale operand_scale : kOperandScales) {
    for (int i = 0; i < Bytecodes::kBytecodeCount; i++) {
      f(Bytecodes::FromByte(i), operand_scale);
    }
  }
}

void Interpreter::Initialize() {
  Builtins* builtins = isolate_->builtins();

  // Set the interpreter entry trampoline entry point now that builtins are
  // initialized.
  Handle<Code> code = BUILTIN_CODE(isolate_, InterpreterEntryTrampoline);
  DCHECK(builtins->is_initialized());
  DCHECK(code->is_off_heap_trampoline() ||
         isolate_->heap()->IsImmovable(*code));
  interpreter_entry_trampoline_instruction_start_ = code->InstructionStart();

  // Initialize the dispatch table.
  Code illegal = builtins->builtin(Builtins::kIllegalHandler);
  int builtin_id = Builtins::kFirstBytecodeHandler;
  ForEachBytecode([=, &builtin_id](Bytecode bytecode,
                                   OperandScale operand_scale) {
    Code handler = illegal;
    if (Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) {
#ifdef DEBUG
      std::string builtin_name(Builtins::name(builtin_id));
      std::string expected_name =
          Bytecodes::ToString(bytecode, operand_scale, "") + "Handler";
      DCHECK_EQ(expected_name, builtin_name);
#endif
      handler = builtins->builtin(builtin_id++);
    }
    SetBytecodeHandler(bytecode, operand_scale, handler);
  });
  DCHECK(builtin_id == Builtins::builtin_count);
  DCHECK(IsDispatchTableInitialized());
}

bool Interpreter::IsDispatchTableInitialized() const {
  return dispatch_table_[0] != kNullAddress;
}

const char* Interpreter::LookupNameOfBytecodeHandler(const Code code) {
  if (code.kind() == Code::BYTECODE_HANDLER) {
    return Builtins::name(code.builtin_index());
  }
  return nullptr;
}

uintptr_t Interpreter::GetDispatchCounter(Bytecode from, Bytecode to) const {
  int from_index = Bytecodes::ToByte(from);
  int to_index = Bytecodes::ToByte(to);
  return bytecode_dispatch_counters_table_[from_index * kNumberOfBytecodes +
                                           to_index];
}

Local<v8::Object> Interpreter::GetDispatchCountersObject() {
  v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(isolate_);
  Local<v8::Context> context = isolate->GetCurrentContext();

  Local<v8::Object> counters_map = v8::Object::New(isolate);

  // Output is a JSON-encoded object of objects.
  //
  // The keys on the top level object are source bytecodes,
  // and corresponding value are objects. Keys on these last are the
  // destinations of the dispatch and the value associated is a counter for
  // the correspondent source-destination dispatch chain.
  //
  // Only non-zero counters are written to file, but an entry in the top-level
  // object is always present, even if the value is empty because all counters
  // for that source are zero.

  for (int from_index = 0; from_index < kNumberOfBytecodes; ++from_index) {
    Bytecode from_bytecode = Bytecodes::FromByte(from_index);
    Local<v8::Object> counters_row = v8::Object::New(isolate);

    for (int to_index = 0; to_index < kNumberOfBytecodes; ++to_index) {
      Bytecode to_bytecode = Bytecodes::FromByte(to_index);
      uintptr_t counter = GetDispatchCounter(from_bytecode, to_bytecode);

      if (counter > 0) {
        std::string to_name = Bytecodes::ToString(to_bytecode);
        Local<v8::String> to_name_object =
            v8::String::NewFromUtf8(isolate, to_name.c_str(),
                                    NewStringType::kNormal)
                .ToLocalChecked();
        Local<v8::Number> counter_object = v8::Number::New(isolate, counter);
        CHECK(counters_row
                  ->DefineOwnProperty(context, to_name_object, counter_object)
                  .IsJust());
      }
    }

    std::string from_name = Bytecodes::ToString(from_bytecode);
    Local<v8::String> from_name_object =
        v8::String::NewFromUtf8(isolate, from_name.c_str(),
                                NewStringType::kNormal)
            .ToLocalChecked();

    CHECK(
        counters_map->DefineOwnProperty(context, from_name_object, counters_row)
            .IsJust());
  }

  return counters_map;
}

}  // namespace interpreter
}  // namespace internal
}  // namespace v8
