Home | History | Annotate | Download | only in debug
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/debug/debug-frames.h"
      6 
      7 #include "src/frames-inl.h"
      8 
      9 namespace v8 {
     10 namespace internal {
     11 
     12 FrameInspector::FrameInspector(JavaScriptFrame* frame,
     13                                int inlined_jsframe_index, Isolate* isolate)
     14     : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
     15   has_adapted_arguments_ = frame_->has_adapted_arguments();
     16   is_bottommost_ = inlined_jsframe_index == 0;
     17   is_optimized_ = frame_->is_optimized();
     18   // Calculate the deoptimized frame.
     19   if (frame->is_optimized()) {
     20     // TODO(turbofan): Revisit once we support deoptimization.
     21     if (frame->LookupCode()->is_turbofanned() &&
     22         frame->function()->shared()->asm_function() &&
     23         !FLAG_turbo_asm_deoptimization) {
     24       is_optimized_ = false;
     25       return;
     26     }
     27 
     28     deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
     29         frame, inlined_jsframe_index, isolate);
     30   }
     31 }
     32 
     33 
     34 FrameInspector::~FrameInspector() {
     35   // Get rid of the calculated deoptimized frame if any.
     36   if (deoptimized_frame_ != NULL) {
     37     Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_, isolate_);
     38   }
     39 }
     40 
     41 
     42 int FrameInspector::GetParametersCount() {
     43   return is_optimized_ ? deoptimized_frame_->parameters_count()
     44                        : frame_->ComputeParametersCount();
     45 }
     46 
     47 
     48 Object* FrameInspector::GetFunction() {
     49   return is_optimized_ ? deoptimized_frame_->GetFunction() : frame_->function();
     50 }
     51 
     52 
     53 Object* FrameInspector::GetParameter(int index) {
     54   return is_optimized_ ? deoptimized_frame_->GetParameter(index)
     55                        : frame_->GetParameter(index);
     56 }
     57 
     58 
     59 Object* FrameInspector::GetExpression(int index) {
     60   // TODO(turbofan): Revisit once we support deoptimization.
     61   if (frame_->LookupCode()->is_turbofanned() &&
     62       frame_->function()->shared()->asm_function() &&
     63       !FLAG_turbo_asm_deoptimization) {
     64     return isolate_->heap()->undefined_value();
     65   }
     66   return is_optimized_ ? deoptimized_frame_->GetExpression(index)
     67                        : frame_->GetExpression(index);
     68 }
     69 
     70 
     71 int FrameInspector::GetSourcePosition() {
     72   return is_optimized_ ? deoptimized_frame_->GetSourcePosition()
     73                        : frame_->LookupCode()->SourcePosition(frame_->pc());
     74 }
     75 
     76 
     77 bool FrameInspector::IsConstructor() {
     78   return is_optimized_ && !is_bottommost_
     79              ? deoptimized_frame_->HasConstructStub()
     80              : frame_->IsConstructor();
     81 }
     82 
     83 
     84 Object* FrameInspector::GetContext() {
     85   return is_optimized_ ? deoptimized_frame_->GetContext() : frame_->context();
     86 }
     87 
     88 
     89 // To inspect all the provided arguments the frame might need to be
     90 // replaced with the arguments frame.
     91 void FrameInspector::SetArgumentsFrame(JavaScriptFrame* frame) {
     92   DCHECK(has_adapted_arguments_);
     93   frame_ = frame;
     94   is_optimized_ = frame_->is_optimized();
     95   DCHECK(!is_optimized_);
     96 }
     97 
     98 
     99 // Create a plain JSObject which materializes the local scope for the specified
    100 // frame.
    101 void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
    102                                             Handle<ScopeInfo> scope_info) {
    103   HandleScope scope(isolate_);
    104   // First fill all parameters.
    105   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
    106     // Do not materialize the parameter if it is shadowed by a context local.
    107     // TODO(yangguo): check whether this is necessary, now that we materialize
    108     //                context locals as well.
    109     Handle<String> name(scope_info->ParameterName(i));
    110     if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
    111 
    112     Handle<Object> value(i < GetParametersCount()
    113                              ? GetParameter(i)
    114                              : isolate_->heap()->undefined_value(),
    115                          isolate_);
    116     DCHECK(!value->IsTheHole());
    117 
    118     JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
    119   }
    120 
    121   // Second fill all stack locals.
    122   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
    123     if (scope_info->LocalIsSynthetic(i)) continue;
    124     Handle<String> name(scope_info->StackLocalName(i));
    125     Handle<Object> value(GetExpression(scope_info->StackLocalIndex(i)),
    126                          isolate_);
    127     if (value->IsTheHole()) value = isolate_->factory()->undefined_value();
    128 
    129     JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
    130   }
    131 }
    132 
    133 
    134 void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
    135                                             Handle<JSFunction> function) {
    136   Handle<SharedFunctionInfo> shared(function->shared());
    137   Handle<ScopeInfo> scope_info(shared->scope_info());
    138   MaterializeStackLocals(target, scope_info);
    139 }
    140 
    141 
    142 void FrameInspector::UpdateStackLocalsFromMaterializedObject(
    143     Handle<JSObject> target, Handle<ScopeInfo> scope_info) {
    144   if (is_optimized_) {
    145     // Optimized frames are not supported. Simply give up.
    146     return;
    147   }
    148 
    149   HandleScope scope(isolate_);
    150 
    151   // Parameters.
    152   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
    153     // Shadowed parameters were not materialized.
    154     Handle<String> name(scope_info->ParameterName(i));
    155     if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
    156 
    157     DCHECK(!frame_->GetParameter(i)->IsTheHole());
    158     Handle<Object> value =
    159         Object::GetPropertyOrElement(target, name).ToHandleChecked();
    160     frame_->SetParameterValue(i, *value);
    161   }
    162 
    163   // Stack locals.
    164   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
    165     if (scope_info->LocalIsSynthetic(i)) continue;
    166     int index = scope_info->StackLocalIndex(i);
    167     if (frame_->GetExpression(index)->IsTheHole()) continue;
    168     Handle<Object> value =
    169         Object::GetPropertyOrElement(
    170             target, handle(scope_info->StackLocalName(i), isolate_))
    171             .ToHandleChecked();
    172     frame_->SetExpression(index, *value);
    173   }
    174 }
    175 
    176 
    177 bool FrameInspector::ParameterIsShadowedByContextLocal(
    178     Handle<ScopeInfo> info, Handle<String> parameter_name) {
    179   VariableMode mode;
    180   InitializationFlag init_flag;
    181   MaybeAssignedFlag maybe_assigned_flag;
    182   return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag,
    183                                      &maybe_assigned_flag) != -1;
    184 }
    185 
    186 
    187 SaveContext* DebugFrameHelper::FindSavedContextForFrame(
    188     Isolate* isolate, JavaScriptFrame* frame) {
    189   SaveContext* save = isolate->save_context();
    190   while (save != NULL && !save->IsBelowFrame(frame)) {
    191     save = save->prev();
    192   }
    193   DCHECK(save != NULL);
    194   return save;
    195 }
    196 
    197 
    198 int DebugFrameHelper::FindIndexedNonNativeFrame(JavaScriptFrameIterator* it,
    199                                                 int index) {
    200   int count = -1;
    201   for (; !it->done(); it->Advance()) {
    202     List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
    203     it->frame()->Summarize(&frames);
    204     for (int i = frames.length() - 1; i >= 0; i--) {
    205       // Omit functions from native and extension scripts.
    206       if (!frames[i].function()->shared()->IsSubjectToDebugging()) continue;
    207       if (++count == index) return i;
    208     }
    209   }
    210   return -1;
    211 }
    212 
    213 
    214 }  // namespace internal
    215 }  // namespace v8
    216