// Copyright 2016 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/codegen/optimized-compilation-info.h"

#include "src/api/api.h"
#include "src/codegen/source-position.h"
#include "src/debug/debug.h"
#include "src/execution/isolate.h"
#include "src/objects/objects-inl.h"
#include "src/objects/shared-function-info.h"
#include "src/tracing/trace-event.h"
#include "src/tracing/traced-value.h"
#include "src/wasm/function-compiler.h"

namespace v8 {
namespace internal {

OptimizedCompilationInfo::OptimizedCompilationInfo(
    Zone* zone, Isolate* isolate, Handle<SharedFunctionInfo> shared,
    Handle<JSFunction> closure)
    : OptimizedCompilationInfo(Code::OPTIMIZED_FUNCTION, zone) {
  DCHECK(shared->is_compiled());
  bytecode_array_ = handle(shared->GetBytecodeArray(), isolate);
  shared_info_ = shared;
  closure_ = closure;
  optimization_id_ = isolate->NextOptimizationId();

  // Collect source positions for optimized code when profiling or if debugger
  // is active, to be able to get more precise source positions at the price of
  // more memory consumption.
  if (isolate->NeedsDetailedOptimizedCodeLineInfo()) {
    MarkAsSourcePositionsEnabled();
  }

  SetTracingFlags(shared->PassesFilter(FLAG_trace_turbo_filter));
}

OptimizedCompilationInfo::OptimizedCompilationInfo(
    Vector<const char> debug_name, Zone* zone, Code::Kind code_kind)
    : OptimizedCompilationInfo(code_kind, zone) {
  debug_name_ = debug_name;

  SetTracingFlags(
      PassesFilter(debug_name, CStrVector(FLAG_trace_turbo_filter)));
}

OptimizedCompilationInfo::OptimizedCompilationInfo(Code::Kind code_kind,
                                                   Zone* zone)
    : code_kind_(code_kind), zone_(zone) {
  ConfigureFlags();
}

void OptimizedCompilationInfo::ConfigureFlags() {
  if (FLAG_untrusted_code_mitigations) SetFlag(kUntrustedCodeMitigations);

  switch (code_kind_) {
    case Code::OPTIMIZED_FUNCTION:
      SetFlag(kCalledWithCodeStartRegister);
      SetFlag(kSwitchJumpTableEnabled);
      if (FLAG_function_context_specialization) {
        MarkAsFunctionContextSpecializing();
      }
      if (FLAG_turbo_splitting) {
        MarkAsSplittingEnabled();
      }
      if (FLAG_untrusted_code_mitigations) {
        MarkAsPoisoningRegisterArguments();
      }
      if (FLAG_analyze_environment_liveness) {
        // TODO(yangguo): Disable this in case of debugging for crbug.com/826613
        MarkAsAnalyzeEnvironmentLiveness();
      }
      break;
    case Code::BYTECODE_HANDLER:
      SetFlag(kCalledWithCodeStartRegister);
      if (FLAG_turbo_splitting) {
        MarkAsSplittingEnabled();
      }
      break;
    case Code::BUILTIN:
    case Code::STUB:
      if (FLAG_turbo_splitting) {
        MarkAsSplittingEnabled();
      }
#if ENABLE_GDB_JIT_INTERFACE && DEBUG
      MarkAsSourcePositionsEnabled();
#endif  // ENABLE_GDB_JIT_INTERFACE && DEBUG
      break;
    case Code::WASM_FUNCTION:
    case Code::WASM_TO_CAPI_FUNCTION:
      SetFlag(kSwitchJumpTableEnabled);
      break;
    default:
      break;
  }

  if (FLAG_turbo_control_flow_aware_allocation) {
    MarkAsTurboControlFlowAwareAllocation();
  } else {
    MarkAsTurboPreprocessRanges();
  }
}

OptimizedCompilationInfo::~OptimizedCompilationInfo() {
  if (GetFlag(kDisableFutureOptimization) && has_shared_info()) {
    shared_info()->DisableOptimization(bailout_reason());
  }
}

void OptimizedCompilationInfo::set_deferred_handles(
    std::shared_ptr<DeferredHandles> deferred_handles) {
  DCHECK_NULL(deferred_handles_);
  deferred_handles_.swap(deferred_handles);
}

void OptimizedCompilationInfo::set_deferred_handles(
    DeferredHandles* deferred_handles) {
  DCHECK_NULL(deferred_handles_);
  deferred_handles_.reset(deferred_handles);
}

void OptimizedCompilationInfo::ReopenHandlesInNewHandleScope(Isolate* isolate) {
  if (!shared_info_.is_null()) {
    shared_info_ = Handle<SharedFunctionInfo>(*shared_info_, isolate);
  }
  if (!bytecode_array_.is_null()) {
    bytecode_array_ = Handle<BytecodeArray>(*bytecode_array_, isolate);
  }
  if (!closure_.is_null()) {
    closure_ = Handle<JSFunction>(*closure_, isolate);
  }
}

void OptimizedCompilationInfo::AbortOptimization(BailoutReason reason) {
  DCHECK_NE(reason, BailoutReason::kNoReason);
  if (bailout_reason_ == BailoutReason::kNoReason) {
    TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                         "V8.AbortOptimization", TRACE_EVENT_SCOPE_THREAD,
                         "reason", GetBailoutReason(reason), "function",
                         shared_info()->TraceIDRef());
    bailout_reason_ = reason;
  }
  SetFlag(kDisableFutureOptimization);
}

void OptimizedCompilationInfo::RetryOptimization(BailoutReason reason) {
  DCHECK_NE(reason, BailoutReason::kNoReason);
  if (GetFlag(kDisableFutureOptimization)) return;
  TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                       "V8.RetryOptimization", TRACE_EVENT_SCOPE_THREAD,
                       "reason", GetBailoutReason(reason), "function",
                       shared_info()->TraceIDRef());
  bailout_reason_ = reason;
}

std::unique_ptr<char[]> OptimizedCompilationInfo::GetDebugName() const {
  if (!shared_info().is_null()) {
    return shared_info()->DebugName().ToCString();
  }
  Vector<const char> name_vec = debug_name_;
  if (name_vec.empty()) name_vec = ArrayVector("unknown");
  std::unique_ptr<char[]> name(new char[name_vec.length() + 1]);
  memcpy(name.get(), name_vec.begin(), name_vec.length());
  name[name_vec.length()] = '\0';
  return name;
}

StackFrame::Type OptimizedCompilationInfo::GetOutputStackFrameType() const {
  switch (code_kind()) {
    case Code::STUB:
    case Code::BYTECODE_HANDLER:
    case Code::BUILTIN:
      return StackFrame::STUB;
    case Code::WASM_FUNCTION:
      return StackFrame::WASM_COMPILED;
    case Code::WASM_TO_CAPI_FUNCTION:
      return StackFrame::WASM_EXIT;
    case Code::JS_TO_WASM_FUNCTION:
      return StackFrame::JS_TO_WASM;
    case Code::WASM_TO_JS_FUNCTION:
      return StackFrame::WASM_TO_JS;
    case Code::WASM_INTERPRETER_ENTRY:
      return StackFrame::WASM_INTERPRETER_ENTRY;
    case Code::C_WASM_ENTRY:
      return StackFrame::C_WASM_ENTRY;
    default:
      UNIMPLEMENTED();
      return StackFrame::NONE;
  }
}

void OptimizedCompilationInfo::SetWasmCompilationResult(
    std::unique_ptr<wasm::WasmCompilationResult> wasm_compilation_result) {
  wasm_compilation_result_ = std::move(wasm_compilation_result);
}

std::unique_ptr<wasm::WasmCompilationResult>
OptimizedCompilationInfo::ReleaseWasmCompilationResult() {
  return std::move(wasm_compilation_result_);
}

bool OptimizedCompilationInfo::has_context() const {
  return !closure().is_null();
}

Context OptimizedCompilationInfo::context() const {
  DCHECK(has_context());
  return closure()->context();
}

bool OptimizedCompilationInfo::has_native_context() const {
  return !closure().is_null() && !closure()->native_context().is_null();
}

NativeContext OptimizedCompilationInfo::native_context() const {
  DCHECK(has_native_context());
  return closure()->native_context();
}

bool OptimizedCompilationInfo::has_global_object() const {
  return has_native_context();
}

JSGlobalObject OptimizedCompilationInfo::global_object() const {
  DCHECK(has_global_object());
  return native_context().global_object();
}

int OptimizedCompilationInfo::AddInlinedFunction(
    Handle<SharedFunctionInfo> inlined_function,
    Handle<BytecodeArray> inlined_bytecode, SourcePosition pos) {
  int id = static_cast<int>(inlined_functions_.size());
  inlined_functions_.push_back(
      InlinedFunctionHolder(inlined_function, inlined_bytecode, pos));
  return id;
}

void OptimizedCompilationInfo::SetTracingFlags(bool passes_filter) {
  if (!passes_filter) return;
  if (FLAG_trace_turbo) SetFlag(kTraceTurboJson);
  if (FLAG_trace_turbo_graph) SetFlag(kTraceTurboGraph);
  if (FLAG_trace_turbo_scheduled) SetFlag(kTraceTurboScheduled);
  if (FLAG_trace_turbo_alloc) SetFlag(kTraceTurboAllocation);
  if (FLAG_trace_heap_broker) SetFlag(kTraceHeapBroker);
}

OptimizedCompilationInfo::InlinedFunctionHolder::InlinedFunctionHolder(
    Handle<SharedFunctionInfo> inlined_shared_info,
    Handle<BytecodeArray> inlined_bytecode, SourcePosition pos)
    : shared_info(inlined_shared_info), bytecode_array(inlined_bytecode) {
  position.position = pos;
  // initialized when generating the deoptimization literals
  position.inlined_function_id = DeoptimizationData::kNotInlinedIndex;
}

std::unique_ptr<v8::tracing::TracedValue>
OptimizedCompilationInfo::ToTracedValue() {
  auto value = v8::tracing::TracedValue::Create();
  value->SetBoolean("osr", is_osr());
  value->SetBoolean("functionContextSpecialized",
                    is_function_context_specializing());
  if (has_shared_info()) {
    value->SetValue("function", shared_info()->TraceIDRef());
  }
  if (bailout_reason() != BailoutReason::kNoReason) {
    value->SetString("bailoutReason", GetBailoutReason(bailout_reason()));
    value->SetBoolean("disableFutureOptimization",
                      is_disable_future_optimization());
  } else {
    value->SetInteger("optimizationId", optimization_id());
    value->BeginArray("inlinedFunctions");
    for (auto const& inlined_function : inlined_functions()) {
      value->BeginDictionary();
      value->SetValue("function", inlined_function.shared_info->TraceIDRef());
      // TODO(bmeurer): Also include the source position from the
      // {inlined_function} here as dedicated "sourcePosition" field.
      value->EndDictionary();
    }
    value->EndArray();
  }
  return value;
}

}  // namespace internal
}  // namespace v8
