LCOV - code coverage report
Current view: top level - src/debug - debug-frames.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 106 110 96.4 %
Date: 2017-10-20 Functions: 14 15 93.3 %

          Line data    Source code
       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/accessors.h"
       8             : #include "src/frames-inl.h"
       9             : #include "src/wasm/wasm-interpreter.h"
      10             : #include "src/wasm/wasm-objects-inl.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15      194044 : FrameInspector::FrameInspector(StandardFrame* frame, int inlined_frame_index,
      16             :                                Isolate* isolate)
      17             :     : frame_(frame),
      18      388088 :       isolate_(isolate) {
      19             :   // Extract the relevant information from the frame summary and discard it.
      20      194044 :   FrameSummary summary = FrameSummary::Get(frame, inlined_frame_index);
      21             : 
      22      194044 :   is_constructor_ = summary.is_constructor();
      23      194044 :   source_position_ = summary.SourcePosition();
      24      194044 :   function_name_ = summary.FunctionName();
      25      194044 :   script_ = Handle<Script>::cast(summary.script());
      26      194044 :   receiver_ = summary.receiver();
      27             : 
      28      194044 :   if (summary.IsJavaScript()) {
      29      193648 :     function_ = summary.AsJavaScript().function();
      30             :   }
      31             : 
      32             :   JavaScriptFrame* js_frame =
      33      194044 :       frame->is_java_script() ? javascript_frame() : nullptr;
      34             :   DCHECK(js_frame || frame->is_wasm());
      35      387692 :   has_adapted_arguments_ = js_frame && js_frame->has_adapted_arguments();
      36      388373 :   is_optimized_ = frame_->is_optimized();
      37      388088 :   is_interpreted_ = frame_->is_interpreted();
      38             : 
      39             :   // Calculate the deoptimized frame.
      40      194044 :   if (is_optimized_) {
      41             :     DCHECK_NOT_NULL(js_frame);
      42             :     // TODO(turbofan): Deoptimization from AstGraphBuilder is not supported.
      43      104565 :     if (js_frame->LookupCode()->is_turbofanned() &&
      44       69710 :         !js_frame->function()->shared()->HasBytecodeArray()) {
      45           0 :       is_optimized_ = false;
      46      194044 :       return;
      47             :     }
      48             : 
      49             :     deoptimized_frame_.reset(Deoptimizer::DebuggerInspectableFrame(
      50       34855 :         js_frame, inlined_frame_index, isolate));
      51      318378 :   } else if (frame_->is_wasm_interpreter_entry()) {
      52         855 :     wasm_interpreted_frame_ =
      53             :         summary.AsWasm().wasm_instance()->debug_info()->GetInterpretedFrame(
      54             :             frame_->fp(), inlined_frame_index);
      55             :     DCHECK(wasm_interpreted_frame_);
      56      194044 :   }
      57             : }
      58             : 
      59      194044 : FrameInspector::~FrameInspector() {
      60             :   // Destructor needs to be defined in the .cc file, because it instantiates
      61             :   // std::unique_ptr destructors but the types are not known in the header.
      62      194044 : }
      63             : 
      64       64429 : int FrameInspector::GetParametersCount() {
      65       86926 :   if (is_optimized_) return deoptimized_frame_->parameters_count();
      66       41932 :   if (wasm_interpreted_frame_)
      67           0 :     return wasm_interpreted_frame_->GetParameterCount();
      68       41932 :   return frame_->ComputeParametersCount();
      69             : }
      70             : 
      71       33132 : Handle<Object> FrameInspector::GetParameter(int index) {
      72       33132 :   if (is_optimized_) return deoptimized_frame_->GetParameter(index);
      73             :   // TODO(clemensh): Handle wasm_interpreted_frame_.
      74       21903 :   return handle(frame_->GetParameter(index), isolate_);
      75             : }
      76             : 
      77     3339307 : Handle<Object> FrameInspector::GetExpression(int index) {
      78             :   // TODO(turbofan): Deoptimization from AstGraphBuilder is not supported.
      79    10017921 :   if (frame_->is_java_script() &&
      80     6696055 :       javascript_frame()->LookupCode()->is_turbofanned() &&
      81       34882 :       !javascript_frame()->function()->shared()->HasBytecodeArray()) {
      82           0 :     return isolate_->factory()->undefined_value();
      83             :   }
      84             :   return is_optimized_ ? deoptimized_frame_->GetExpression(index)
      85     6661173 :                        : handle(frame_->GetExpression(index), isolate_);
      86             : }
      87             : 
      88      497392 : Handle<Object> FrameInspector::GetContext() {
      89             :   return deoptimized_frame_ ? deoptimized_frame_->GetContext()
      90      994784 :                             : handle(frame_->context(), isolate_);
      91             : }
      92             : 
      93      310594 : bool FrameInspector::IsWasm() { return frame_->is_wasm(); }
      94             : 
      95      125078 : bool FrameInspector::IsJavaScript() { return frame_->is_java_script(); }
      96             : 
      97             : // To inspect all the provided arguments the frame might need to be
      98             : // replaced with the arguments frame.
      99         180 : void FrameInspector::SetArgumentsFrame(StandardFrame* frame) {
     100             :   DCHECK(has_adapted_arguments_);
     101             :   DCHECK(frame->is_arguments_adaptor());
     102         180 :   frame_ = frame;
     103         360 :   is_optimized_ = frame_->is_optimized();
     104         360 :   is_interpreted_ = frame_->is_interpreted();
     105             :   DCHECK(!is_optimized_);
     106         180 : }
     107             : 
     108             : 
     109             : // Create a plain JSObject which materializes the local scope for the specified
     110             : // frame.
     111       89913 : void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
     112             :                                             Handle<ScopeInfo> scope_info,
     113             :                                             bool materialize_arguments_object) {
     114       89913 :   HandleScope scope(isolate_);
     115             :   // First fill all parameters.
     116      237914 :   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
     117             :     // Do not materialize the parameter if it is shadowed by a context local.
     118             :     // TODO(yangguo): check whether this is necessary, now that we materialize
     119             :     //                context locals as well.
     120       29044 :     Handle<String> name(scope_info->ParameterName(i));
     121       35693 :     if (ScopeInfo::VariableIsSynthetic(*name)) continue;
     122       28223 :     if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
     123             : 
     124             :     Handle<Object> value =
     125       22395 :         i < GetParametersCount()
     126             :             ? GetParameter(i)
     127       23263 :             : Handle<Object>::cast(isolate_->factory()->undefined_value());
     128             :     DCHECK(!value->IsTheHole(isolate_));
     129             : 
     130       44790 :     JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
     131             :   }
     132             : 
     133             :   // Second fill all stack locals.
     134     6847385 :   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
     135     3378736 :     Handle<String> name(scope_info->StackLocalName(i));
     136     3378736 :     if (ScopeInfo::VariableIsSynthetic(*name)) continue;
     137     3297497 :     Handle<Object> value = GetExpression(scope_info->StackLocalIndex(i));
     138             :     // TODO(yangguo): We convert optimized out values to {undefined} when they
     139             :     // are passed to the debugger. Eventually we should handle them somehow.
     140     6594994 :     if (value->IsTheHole(isolate_)) {
     141          72 :       value = isolate_->factory()->undefined_value();
     142             :     }
     143     6594994 :     if (value->IsOptimizedOut(isolate_)) {
     144         768 :       if (materialize_arguments_object) {
     145          78 :         Handle<String> arguments_str = isolate_->factory()->arguments_string();
     146          39 :         if (String::Equals(name, arguments_str)) continue;
     147             :       }
     148         766 :       value = isolate_->factory()->undefined_value();
     149             :     }
     150     6594990 :     JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
     151             :   }
     152       89913 : }
     153             : 
     154       10148 : void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
     155             :                                             Handle<JSFunction> function,
     156             :                                             bool materialize_arguments_object) {
     157             :   // Do not materialize the arguments object for eval or top-level code.
     158       10148 :   if (function->shared()->is_toplevel()) materialize_arguments_object = false;
     159             : 
     160             :   Handle<SharedFunctionInfo> shared(function->shared());
     161             :   Handle<ScopeInfo> scope_info(shared->scope_info());
     162       10148 :   MaterializeStackLocals(target, scope_info, materialize_arguments_object);
     163             : 
     164             :   // Third materialize the arguments object.
     165       10148 :   if (materialize_arguments_object) {
     166             :     // Skip if "arguments" is already taken and wasn't optimized out (which
     167             :     // causes {MaterializeStackLocals} above to skip the local variable).
     168       10148 :     Handle<String> arguments_str = isolate_->factory()->arguments_string();
     169       10148 :     Maybe<bool> maybe = JSReceiver::HasOwnProperty(target, arguments_str);
     170             :     DCHECK(maybe.IsJust());
     171       10182 :     if (maybe.FromJust()) return;
     172             : 
     173             :     // FunctionGetArguments can't throw an exception.
     174       10114 :     Handle<JSObject> arguments = Accessors::FunctionGetArguments(function);
     175             :     JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments,
     176       10114 :                                              NONE)
     177       20228 :         .Check();
     178             :   }
     179             : }
     180             : 
     181             : 
     182        9542 : void FrameInspector::UpdateStackLocalsFromMaterializedObject(
     183             :     Handle<JSObject> target, Handle<ScopeInfo> scope_info) {
     184             :   // Optimized frames and wasm frames are not supported. Simply give up.
     185       24876 :   if (is_optimized_ || frame_->is_wasm()) return;
     186             : 
     187        5792 :   HandleScope scope(isolate_);
     188             : 
     189             :   // Parameters.
     190       16672 :   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
     191             :     // Shadowed parameters were not materialized.
     192        2544 :     Handle<String> name(scope_info->ParameterName(i));
     193        2544 :     if (ScopeInfo::VariableIsSynthetic(*name)) continue;
     194        2352 :     if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
     195             : 
     196             :     DCHECK(!javascript_frame()->GetParameter(i)->IsTheHole(isolate_));
     197             :     Handle<Object> value =
     198        4112 :         Object::GetPropertyOrElement(target, name).ToHandleChecked();
     199        2056 :     javascript_frame()->SetParameterValue(i, *value);
     200             :   }
     201             : 
     202             :   // Stack locals.
     203       84902 :   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
     204       39555 :     Handle<String> name(scope_info->StackLocalName(i));
     205       39555 :     if (ScopeInfo::VariableIsSynthetic(*name)) continue;
     206       39174 :     int index = scope_info->StackLocalIndex(i);
     207       78348 :     if (frame_->GetExpression(index)->IsTheHole(isolate_)) continue;
     208             :     Handle<Object> value =
     209       78348 :         Object::GetPropertyOrElement(target, name).ToHandleChecked();
     210       39174 :     frame_->SetExpression(index, *value);
     211             :   }
     212             : }
     213             : 
     214             : 
     215           0 : bool FrameInspector::ParameterIsShadowedByContextLocal(
     216             :     Handle<ScopeInfo> info, Handle<String> parameter_name) {
     217             :   VariableMode mode;
     218             :   InitializationFlag init_flag;
     219             :   MaybeAssignedFlag maybe_assigned_flag;
     220             :   return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag,
     221       30575 :                                      &maybe_assigned_flag) != -1;
     222             : }
     223             : 
     224       40710 : SaveContext* DebugFrameHelper::FindSavedContextForFrame(Isolate* isolate,
     225             :                                                         StandardFrame* frame) {
     226       80112 :   SaveContext* save = isolate->save_context();
     227      161532 :   while (save != nullptr && !save->IsBelowFrame(frame)) {
     228             :     save = save->prev();
     229             :   }
     230             :   DCHECK(save != nullptr);
     231       40710 :   return save;
     232             : }
     233             : 
     234       30219 : int DebugFrameHelper::FindIndexedNonNativeFrame(StackTraceFrameIterator* it,
     235             :                                                 int index) {
     236             :   int count = -1;
     237       60518 :   for (; !it->done(); it->Advance()) {
     238             :     std::vector<FrameSummary> frames;
     239       30259 :     frames.reserve(FLAG_max_inlining_levels + 1);
     240       30259 :     it->frame()->Summarize(&frames);
     241       90832 :     for (size_t i = frames.size(); i != 0; i--) {
     242             :       // Omit functions from native and extension scripts.
     243       60548 :       if (!frames[i - 1].is_subject_to_debugging()) continue;
     244       30274 :       if (++count == index) return static_cast<int>(i) - 1;
     245             :     }
     246          40 :   }
     247             :   return -1;
     248             : }
     249             : 
     250             : 
     251             : }  // namespace internal
     252             : }  // namespace v8

Generated by: LCOV version 1.10