// 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/debug/debug-frames.h"

#include "src/accessors.h"
#include "src/frames-inl.h"
#include "src/wasm/wasm-interpreter.h"
#include "src/wasm/wasm-objects-inl.h"

namespace v8 {
namespace internal {

FrameInspector::FrameInspector(StandardFrame* frame, int inlined_frame_index,
                               Isolate* isolate)
    : frame_(frame),
      isolate_(isolate) {
  // Extract the relevant information from the frame summary and discard it.
  FrameSummary summary = FrameSummary::Get(frame, inlined_frame_index);

  is_constructor_ = summary.is_constructor();
  source_position_ = summary.SourcePosition();
  function_name_ = summary.FunctionName();
  script_ = Handle<Script>::cast(summary.script());
  receiver_ = summary.receiver();

  if (summary.IsJavaScript()) {
    function_ = summary.AsJavaScript().function();
  }

  JavaScriptFrame* js_frame =
      frame->is_java_script() ? javascript_frame() : nullptr;
  DCHECK(js_frame || frame->is_wasm());
  has_adapted_arguments_ = js_frame && js_frame->has_adapted_arguments();
  is_optimized_ = frame_->is_optimized();
  is_interpreted_ = frame_->is_interpreted();

  // Calculate the deoptimized frame.
  if (is_optimized_) {
    DCHECK_NOT_NULL(js_frame);
    // TODO(turbofan): Deoptimization from AstGraphBuilder is not supported.
    if (js_frame->LookupCode()->is_turbofanned() &&
        !js_frame->function()->shared()->HasBytecodeArray()) {
      is_optimized_ = false;
      return;
    }

    deoptimized_frame_.reset(Deoptimizer::DebuggerInspectableFrame(
        js_frame, inlined_frame_index, isolate));
  } else if (frame_->is_wasm_interpreter_entry()) {
    wasm_interpreted_frame_ =
        summary.AsWasm().wasm_instance()->debug_info()->GetInterpretedFrame(
            frame_->fp(), inlined_frame_index);
    DCHECK(wasm_interpreted_frame_);
  }
}

FrameInspector::~FrameInspector() {
  // Destructor needs to be defined in the .cc file, because it instantiates
  // std::unique_ptr destructors but the types are not known in the header.
}

int FrameInspector::GetParametersCount() {
  if (is_optimized_) return deoptimized_frame_->parameters_count();
  if (wasm_interpreted_frame_)
    return wasm_interpreted_frame_->GetParameterCount();
  return frame_->ComputeParametersCount();
}

Handle<Object> FrameInspector::GetParameter(int index) {
  if (is_optimized_) return deoptimized_frame_->GetParameter(index);
  // TODO(clemensh): Handle wasm_interpreted_frame_.
  return handle(frame_->GetParameter(index), isolate_);
}

Handle<Object> FrameInspector::GetExpression(int index) {
  // TODO(turbofan): Deoptimization from AstGraphBuilder is not supported.
  if (frame_->is_java_script() &&
      javascript_frame()->LookupCode()->is_turbofanned() &&
      !javascript_frame()->function()->shared()->HasBytecodeArray()) {
    return isolate_->factory()->undefined_value();
  }
  return is_optimized_ ? deoptimized_frame_->GetExpression(index)
                       : handle(frame_->GetExpression(index), isolate_);
}

Handle<Object> FrameInspector::GetContext() {
  return deoptimized_frame_ ? deoptimized_frame_->GetContext()
                            : handle(frame_->context(), isolate_);
}

bool FrameInspector::IsWasm() { return frame_->is_wasm(); }

bool FrameInspector::IsJavaScript() { return frame_->is_java_script(); }

// To inspect all the provided arguments the frame might need to be
// replaced with the arguments frame.
void FrameInspector::SetArgumentsFrame(StandardFrame* frame) {
  DCHECK(has_adapted_arguments_);
  DCHECK(frame->is_arguments_adaptor());
  frame_ = frame;
  is_optimized_ = frame_->is_optimized();
  is_interpreted_ = frame_->is_interpreted();
  DCHECK(!is_optimized_);
}


// Create a plain JSObject which materializes the local scope for the specified
// frame.
void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
                                            Handle<ScopeInfo> scope_info,
                                            bool materialize_arguments_object) {
  HandleScope scope(isolate_);
  // First fill all parameters.
  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
    // Do not materialize the parameter if it is shadowed by a context local.
    // TODO(yangguo): check whether this is necessary, now that we materialize
    //                context locals as well.
    Handle<String> name(scope_info->ParameterName(i));
    if (ScopeInfo::VariableIsSynthetic(*name)) continue;
    if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;

    Handle<Object> value =
        i < GetParametersCount()
            ? GetParameter(i)
            : Handle<Object>::cast(isolate_->factory()->undefined_value());
    DCHECK(!value->IsTheHole(isolate_));

    JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
  }

  // Second fill all stack locals.
  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
    Handle<String> name(scope_info->StackLocalName(i));
    if (ScopeInfo::VariableIsSynthetic(*name)) continue;
    Handle<Object> value = GetExpression(scope_info->StackLocalIndex(i));
    // TODO(yangguo): We convert optimized out values to {undefined} when they
    // are passed to the debugger. Eventually we should handle them somehow.
    if (value->IsTheHole(isolate_)) {
      value = isolate_->factory()->undefined_value();
    }
    if (value->IsOptimizedOut(isolate_)) {
      if (materialize_arguments_object) {
        Handle<String> arguments_str = isolate_->factory()->arguments_string();
        if (String::Equals(name, arguments_str)) continue;
      }
      value = isolate_->factory()->undefined_value();
    }
    JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
  }
}

void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
                                            Handle<JSFunction> function,
                                            bool materialize_arguments_object) {
  // Do not materialize the arguments object for eval or top-level code.
  if (function->shared()->is_toplevel()) materialize_arguments_object = false;

  Handle<SharedFunctionInfo> shared(function->shared());
  Handle<ScopeInfo> scope_info(shared->scope_info());
  MaterializeStackLocals(target, scope_info, materialize_arguments_object);

  // Third materialize the arguments object.
  if (materialize_arguments_object) {
    // Skip if "arguments" is already taken and wasn't optimized out (which
    // causes {MaterializeStackLocals} above to skip the local variable).
    Handle<String> arguments_str = isolate_->factory()->arguments_string();
    Maybe<bool> maybe = JSReceiver::HasOwnProperty(target, arguments_str);
    DCHECK(maybe.IsJust());
    if (maybe.FromJust()) return;

    // FunctionGetArguments can't throw an exception.
    Handle<JSObject> arguments = Accessors::FunctionGetArguments(function);
    JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments,
                                             NONE)
        .Check();
  }
}


void FrameInspector::UpdateStackLocalsFromMaterializedObject(
    Handle<JSObject> target, Handle<ScopeInfo> scope_info) {
  // Optimized frames and wasm frames are not supported. Simply give up.
  if (is_optimized_ || frame_->is_wasm()) return;

  HandleScope scope(isolate_);

  // Parameters.
  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
    // Shadowed parameters were not materialized.
    Handle<String> name(scope_info->ParameterName(i));
    if (ScopeInfo::VariableIsSynthetic(*name)) continue;
    if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;

    DCHECK(!javascript_frame()->GetParameter(i)->IsTheHole(isolate_));
    Handle<Object> value =
        Object::GetPropertyOrElement(target, name).ToHandleChecked();
    javascript_frame()->SetParameterValue(i, *value);
  }

  // Stack locals.
  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
    Handle<String> name(scope_info->StackLocalName(i));
    if (ScopeInfo::VariableIsSynthetic(*name)) continue;
    int index = scope_info->StackLocalIndex(i);
    if (frame_->GetExpression(index)->IsTheHole(isolate_)) continue;
    Handle<Object> value =
        Object::GetPropertyOrElement(target, name).ToHandleChecked();
    frame_->SetExpression(index, *value);
  }
}


bool FrameInspector::ParameterIsShadowedByContextLocal(
    Handle<ScopeInfo> info, Handle<String> parameter_name) {
  VariableMode mode;
  InitializationFlag init_flag;
  MaybeAssignedFlag maybe_assigned_flag;
  return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag,
                                     &maybe_assigned_flag) != -1;
}

SaveContext* DebugFrameHelper::FindSavedContextForFrame(Isolate* isolate,
                                                        StandardFrame* frame) {
  SaveContext* save = isolate->save_context();
  while (save != NULL && !save->IsBelowFrame(frame)) {
    save = save->prev();
  }
  DCHECK(save != NULL);
  return save;
}

int DebugFrameHelper::FindIndexedNonNativeFrame(StackTraceFrameIterator* it,
                                                int index) {
  int count = -1;
  for (; !it->done(); it->Advance()) {
    std::vector<FrameSummary> frames;
    frames.reserve(FLAG_max_inlining_levels + 1);
    it->frame()->Summarize(&frames);
    for (size_t i = frames.size(); i != 0; i--) {
      // Omit functions from native and extension scripts.
      if (!frames[i - 1].is_subject_to_debugging()) continue;
      if (++count == index) return static_cast<int>(i) - 1;
    }
  }
  return -1;
}


}  // namespace internal
}  // namespace v8
