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

namespace v8 {
namespace internal {

FrameInspector::FrameInspector(JavaScriptFrame* frame,
                               int inlined_jsframe_index, Isolate* isolate)
    : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
  has_adapted_arguments_ = frame_->has_adapted_arguments();
  is_bottommost_ = inlined_jsframe_index == 0;
  is_optimized_ = frame_->is_optimized();
  is_interpreted_ = frame_->is_interpreted();
  // Calculate the deoptimized frame.
  if (frame->is_optimized()) {
    // TODO(turbofan): Revisit once we support deoptimization.
    if (frame->LookupCode()->is_turbofanned() &&
        frame->function()->shared()->asm_function() &&
        !FLAG_turbo_asm_deoptimization) {
      is_optimized_ = false;
      return;
    }

    deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
        frame, inlined_jsframe_index, isolate);
  }
}


FrameInspector::~FrameInspector() {
  // Get rid of the calculated deoptimized frame if any.
  if (deoptimized_frame_ != NULL) {
    Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_, isolate_);
  }
}


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

Handle<Object> FrameInspector::GetFunction() {
  return is_optimized_ ? deoptimized_frame_->GetFunction()
                       : handle(frame_->function(), isolate_);
}

Handle<Object> FrameInspector::GetParameter(int index) {
  return is_optimized_ ? deoptimized_frame_->GetParameter(index)
                       : handle(frame_->GetParameter(index), isolate_);
}

Handle<Object> FrameInspector::GetExpression(int index) {
  // TODO(turbofan): Revisit once we support deoptimization.
  if (frame_->LookupCode()->is_turbofanned() &&
      frame_->function()->shared()->asm_function() &&
      !FLAG_turbo_asm_deoptimization) {
    return isolate_->factory()->undefined_value();
  }
  return is_optimized_ ? deoptimized_frame_->GetExpression(index)
                       : handle(frame_->GetExpression(index), isolate_);
}


int FrameInspector::GetSourcePosition() {
  if (is_optimized_) {
    return deoptimized_frame_->GetSourcePosition();
  } else if (is_interpreted_) {
    InterpretedFrame* frame = reinterpret_cast<InterpretedFrame*>(frame_);
    BytecodeArray* bytecode_array = frame->GetBytecodeArray();
    return bytecode_array->SourcePosition(frame->GetBytecodeOffset());
  } else {
    Code* code = frame_->LookupCode();
    int offset = static_cast<int>(frame_->pc() - code->instruction_start());
    return code->SourcePosition(offset);
  }
}


bool FrameInspector::IsConstructor() {
  return is_optimized_ && !is_bottommost_
             ? deoptimized_frame_->HasConstructStub()
             : frame_->IsConstructor();
}

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


// To inspect all the provided arguments the frame might need to be
// replaced with the arguments frame.
void FrameInspector::SetArgumentsFrame(JavaScriptFrame* frame) {
  DCHECK(has_adapted_arguments_);
  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) {
  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());

    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()) value = isolate_->factory()->undefined_value();
    if (value->IsOptimizedOut()) value = isolate_->factory()->undefined_value();
    JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
  }
}


void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
                                            Handle<JSFunction> function) {
  Handle<SharedFunctionInfo> shared(function->shared());
  Handle<ScopeInfo> scope_info(shared->scope_info());
  MaterializeStackLocals(target, scope_info);
}


void FrameInspector::UpdateStackLocalsFromMaterializedObject(
    Handle<JSObject> target, Handle<ScopeInfo> scope_info) {
  if (is_optimized_) {
    // Optimized frames are not supported. Simply give up.
    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(!frame_->GetParameter(i)->IsTheHole());
    Handle<Object> value =
        Object::GetPropertyOrElement(target, name).ToHandleChecked();
    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()) 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, JavaScriptFrame* frame) {
  SaveContext* save = isolate->save_context();
  while (save != NULL && !save->IsBelowFrame(frame)) {
    save = save->prev();
  }
  DCHECK(save != NULL);
  return save;
}


int DebugFrameHelper::FindIndexedNonNativeFrame(JavaScriptFrameIterator* it,
                                                int index) {
  int count = -1;
  for (; !it->done(); it->Advance()) {
    List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
    it->frame()->Summarize(&frames);
    for (int i = frames.length() - 1; i >= 0; i--) {
      // Omit functions from native and extension scripts.
      if (!frames[i].function()->shared()->IsSubjectToDebugging()) continue;
      if (++count == index) return i;
    }
  }
  return -1;
}


}  // namespace internal
}  // namespace v8
