LCOV - code coverage report
Current view: top level - src/debug - debug-stack-trace-iterator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 84 84 100.0 %
Date: 2019-01-20 Functions: 16 16 100.0 %

          Line data    Source code
       1             : // Copyright 2017 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-stack-trace-iterator.h"
       6             : 
       7             : #include "src/api-inl.h"
       8             : #include "src/debug/debug-evaluate.h"
       9             : #include "src/debug/debug-scope-iterator.h"
      10             : #include "src/debug/debug.h"
      11             : #include "src/debug/liveedit.h"
      12             : #include "src/frames-inl.h"
      13             : #include "src/isolate.h"
      14             : 
      15             : namespace v8 {
      16             : 
      17      111595 : std::unique_ptr<debug::StackTraceIterator> debug::StackTraceIterator::Create(
      18             :     v8::Isolate* isolate, int index) {
      19             :   return std::unique_ptr<debug::StackTraceIterator>(
      20             :       new internal::DebugStackTraceIterator(
      21      223190 :           reinterpret_cast<internal::Isolate*>(isolate), index));
      22             : }
      23             : 
      24             : namespace internal {
      25             : 
      26      223190 : DebugStackTraceIterator::DebugStackTraceIterator(Isolate* isolate, int index)
      27             :     : isolate_(isolate),
      28             :       iterator_(isolate, isolate->debug()->break_frame_id()),
      29      223190 :       is_top_frame_(true) {
      30      111595 :   if (iterator_.done()) return;
      31             :   std::vector<FrameSummary> frames;
      32      111595 :   iterator_.frame()->Summarize(&frames);
      33      223190 :   inlined_frame_index_ = static_cast<int>(frames.size());
      34      111595 :   Advance();
      35      232006 :   for (; !Done() && index > 0; --index) Advance();
      36             : }
      37             : 
      38             : DebugStackTraceIterator::~DebugStackTraceIterator() = default;
      39             : 
      40      517038 : bool DebugStackTraceIterator::Done() const { return iterator_.done(); }
      41             : 
      42      311874 : void DebugStackTraceIterator::Advance() {
      43             :   while (true) {
      44      442967 :     --inlined_frame_index_;
      45      442995 :     for (; inlined_frame_index_ >= 0; --inlined_frame_index_) {
      46             :       // Omit functions from native and extension scripts.
      47      498618 :       if (FrameSummary::Get(iterator_.frame(), inlined_frame_index_)
      48      498618 :               .is_subject_to_debugging()) {
      49             :         break;
      50             :       }
      51          28 :       is_top_frame_ = false;
      52             :     }
      53      442967 :     if (inlined_frame_index_ >= 0) {
      54             :       frame_inspector_.reset(new FrameInspector(
      55      249281 :           iterator_.frame(), inlined_frame_index_, isolate_));
      56      311874 :       break;
      57             :     }
      58      193686 :     is_top_frame_ = false;
      59             :     frame_inspector_.reset();
      60      193686 :     iterator_.Advance();
      61      193686 :     if (iterator_.done()) break;
      62             :     std::vector<FrameSummary> frames;
      63      131093 :     iterator_.frame()->Summarize(&frames);
      64      262186 :     inlined_frame_index_ = static_cast<int>(frames.size());
      65      131093 :   }
      66      311874 : }
      67             : 
      68      146914 : int DebugStackTraceIterator::GetContextId() const {
      69             :   DCHECK(!Done());
      70      146914 :   Handle<Object> context = frame_inspector_->GetContext();
      71      293828 :   if (context->IsContext()) {
      72             :     Object value =
      73      146805 :         Context::cast(*context)->native_context()->debug_context_id();
      74      146805 :     if (value->IsSmi()) return Smi::ToInt(value);
      75             :   }
      76             :   return 0;
      77             : }
      78             : 
      79      146795 : v8::MaybeLocal<v8::Value> DebugStackTraceIterator::GetReceiver() const {
      80             :   DCHECK(!Done());
      81      439810 :   if (frame_inspector_->IsJavaScript() &&
      82      293015 :       frame_inspector_->GetFunction()->shared()->kind() == kArrowFunction) {
      83             :     // FrameInspector is not able to get receiver for arrow function.
      84             :     // So let's try to fetch it using same logic as is used to retrieve 'this'
      85             :     // during DebugEvaluate::Local.
      86             :     Handle<JSFunction> function = frame_inspector_->GetFunction();
      87        7410 :     Handle<Context> context(function->context(), isolate_);
      88             :     // Arrow function defined in top level function without references to
      89             :     // variables may have NativeContext as context.
      90        2470 :     if (!context->IsFunctionContext()) return v8::MaybeLocal<v8::Value>();
      91             :     ScopeIterator scope_iterator(isolate_, frame_inspector_.get(),
      92         439 :                                  ScopeIterator::COLLECT_NON_LOCALS);
      93             :     // We lookup this variable in function context only when it is used in arrow
      94             :     // function otherwise V8 can optimize it out.
      95         878 :     if (!scope_iterator.GetNonLocals()->Has(isolate_,
      96         878 :                                             isolate_->factory()->this_string()))
      97         362 :       return v8::MaybeLocal<v8::Value>();
      98             : 
      99         231 :     Handle<ScopeInfo> scope_info(context->scope_info(), isolate_);
     100             :     VariableMode mode;
     101             :     InitializationFlag flag;
     102             :     MaybeAssignedFlag maybe_assigned_flag;
     103             :     int slot_index = ScopeInfo::ContextSlotIndex(
     104             :         scope_info, isolate_->factory()->this_string(), &mode, &flag,
     105         154 :         &maybe_assigned_flag);
     106          77 :     if (slot_index < 0) return v8::MaybeLocal<v8::Value>();
     107         231 :     Handle<Object> value = handle(context->get(slot_index), isolate_);
     108         231 :     if (value->IsTheHole(isolate_)) return v8::MaybeLocal<v8::Value>();
     109          77 :     return Utils::ToLocal(value);
     110             :   }
     111             :   Handle<Object> value = frame_inspector_->GetReceiver();
     112      721607 :   if (value.is_null() || (value->IsSmi() || !value->IsTheHole(isolate_))) {
     113      144040 :     return Utils::ToLocal(value);
     114             :   }
     115         285 :   return v8::MaybeLocal<v8::Value>();
     116             : }
     117             : 
     118      191458 : v8::Local<v8::Value> DebugStackTraceIterator::GetReturnValue() const {
     119             :   DCHECK(!Done());
     120      191458 :   if (frame_inspector_ && frame_inspector_->IsWasm()) {
     121         976 :     return v8::Local<v8::Value>();
     122             :   }
     123      190482 :   bool is_optimized = iterator_.frame()->is_optimized();
     124      288037 :   if (is_optimized || !is_top_frame_ ||
     125      107962 :       !isolate_->debug()->IsBreakAtReturn(iterator_.javascript_frame())) {
     126      180075 :     return v8::Local<v8::Value>();
     127             :   }
     128       20814 :   return Utils::ToLocal(isolate_->debug()->return_value_handle());
     129             : }
     130             : 
     131      146904 : v8::Local<v8::String> DebugStackTraceIterator::GetFunctionDebugName() const {
     132             :   DCHECK(!Done());
     133      146904 :   return Utils::ToLocal(frame_inspector_->GetFunctionName());
     134             : }
     135             : 
     136      293878 : v8::Local<v8::debug::Script> DebugStackTraceIterator::GetScript() const {
     137             :   DCHECK(!Done());
     138             :   Handle<Object> value = frame_inspector_->GetScript();
     139      587756 :   if (!value->IsScript()) return v8::Local<v8::debug::Script>();
     140      293878 :   return ToApiHandle<debug::Script>(Handle<Script>::cast(value));
     141             : }
     142             : 
     143      146974 : debug::Location DebugStackTraceIterator::GetSourceLocation() const {
     144             :   DCHECK(!Done());
     145      146974 :   v8::Local<v8::debug::Script> script = GetScript();
     146      146974 :   if (script.IsEmpty()) return v8::debug::Location();
     147      146974 :   return script->GetSourceLocation(frame_inspector_->GetSourcePosition());
     148             : }
     149             : 
     150      146904 : v8::Local<v8::Function> DebugStackTraceIterator::GetFunction() const {
     151             :   DCHECK(!Done());
     152      146904 :   if (!frame_inspector_->IsJavaScript()) return v8::Local<v8::Function>();
     153             :   return Utils::ToLocal(frame_inspector_->GetFunction());
     154             : }
     155             : 
     156             : std::unique_ptr<v8::debug::ScopeIterator>
     157      147120 : DebugStackTraceIterator::GetScopeIterator() const {
     158             :   DCHECK(!Done());
     159             :   StandardFrame* frame = iterator_.frame();
     160      294240 :   if (frame->is_wasm_interpreter_entry()) {
     161             :     return std::unique_ptr<v8::debug::ScopeIterator>(new DebugWasmScopeIterator(
     162         575 :         isolate_, iterator_.frame(), inlined_frame_index_));
     163             :   }
     164             :   return std::unique_ptr<v8::debug::ScopeIterator>(
     165      146545 :       new DebugScopeIterator(isolate_, frame_inspector_.get()));
     166             : }
     167             : 
     168          99 : bool DebugStackTraceIterator::Restart() {
     169             :   DCHECK(!Done());
     170          99 :   if (iterator_.is_wasm()) return false;
     171          99 :   return !LiveEdit::RestartFrame(iterator_.javascript_frame());
     172             : }
     173             : 
     174       11092 : v8::MaybeLocal<v8::Value> DebugStackTraceIterator::Evaluate(
     175             :     v8::Local<v8::String> source, bool throw_on_side_effect) {
     176             :   DCHECK(!Done());
     177             :   Handle<Object> value;
     178       11092 :   i::SafeForInterruptsScope safe_for_interrupt_scope(isolate_);
     179       11092 :   if (!DebugEvaluate::Local(isolate_, iterator_.frame()->id(),
     180             :                             inlined_frame_index_, Utils::OpenHandle(*source),
     181       44368 :                             throw_on_side_effect)
     182       22184 :            .ToHandle(&value)) {
     183        1197 :     isolate_->OptionalRescheduleException(false);
     184        1197 :     return v8::MaybeLocal<v8::Value>();
     185             :   }
     186        9895 :   return Utils::ToLocal(value);
     187             : }
     188             : }  // namespace internal
     189      183867 : }  // namespace v8

Generated by: LCOV version 1.10