LCOV - code coverage report
Current view: top level - src/objects - debug-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 143 153 93.5 %
Date: 2019-04-17 Functions: 31 32 96.9 %

          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/objects/debug-objects.h"
       6             : 
       7             : #include "src/debug/debug-evaluate.h"
       8             : #include "src/handles-inl.h"
       9             : #include "src/objects/debug-objects-inl.h"
      10             : #include "src/ostreams.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15       58905 : bool DebugInfo::IsEmpty() const {
      16      117622 :   return flags() == kNone && debugger_hints() == 0;
      17             : }
      18             : 
      19     3270040 : bool DebugInfo::HasBreakInfo() const { return (flags() & kHasBreakInfo) != 0; }
      20             : 
      21       13115 : DebugInfo::ExecutionMode DebugInfo::DebugExecutionMode() const {
      22       13115 :   return (flags() & kDebugExecutionMode) != 0 ? kSideEffects : kBreakpoints;
      23             : }
      24             : 
      25     1145873 : void DebugInfo::SetDebugExecutionMode(ExecutionMode value) {
      26     2291746 :   set_flags(value == kSideEffects ? (flags() | kDebugExecutionMode)
      27             :                                   : (flags() & ~kDebugExecutionMode));
      28     1145873 : }
      29             : 
      30       28435 : void DebugInfo::ClearBreakInfo(Isolate* isolate) {
      31       28435 :   if (HasInstrumentedBytecodeArray()) {
      32             :     // Reset function's bytecode array field to point to the original bytecode
      33             :     // array.
      34       10601 :     shared()->SetDebugBytecodeArray(OriginalBytecodeArray());
      35             : 
      36             :     // If the function is currently running on the stack, we need to update the
      37             :     // bytecode pointers on the stack so they point to the original
      38             :     // BytecodeArray before releasing that BytecodeArray from this DebugInfo.
      39             :     // Otherwise, it could be flushed and cause problems on resume. See v8:9067.
      40             :     {
      41             :       RedirectActiveFunctions redirect_visitor(
      42       10601 :           shared(), RedirectActiveFunctions::Mode::kUseOriginalBytecode);
      43       10601 :       redirect_visitor.VisitThread(isolate, isolate->thread_local_top());
      44       10601 :       isolate->thread_manager()->IterateArchivedThreads(&redirect_visitor);
      45             :     }
      46             : 
      47       10601 :     set_original_bytecode_array(ReadOnlyRoots(isolate).undefined_value());
      48       10601 :     set_debug_bytecode_array(ReadOnlyRoots(isolate).undefined_value());
      49             :   }
      50       28435 :   set_break_points(ReadOnlyRoots(isolate).empty_fixed_array());
      51             : 
      52             :   int new_flags = flags();
      53             :   new_flags &= ~kHasBreakInfo & ~kPreparedForDebugExecution;
      54             :   new_flags &= ~kBreakAtEntry & ~kCanBreakAtEntry;
      55       28435 :   new_flags &= ~kDebugExecutionMode;
      56             :   set_flags(new_flags);
      57       28435 : }
      58             : 
      59         595 : void DebugInfo::SetBreakAtEntry() {
      60             :   DCHECK(CanBreakAtEntry());
      61         595 :   set_flags(flags() | kBreakAtEntry);
      62         595 : }
      63             : 
      64         745 : void DebugInfo::ClearBreakAtEntry() {
      65             :   DCHECK(CanBreakAtEntry());
      66         745 :   set_flags(flags() & ~kBreakAtEntry);
      67         745 : }
      68             : 
      69       10008 : bool DebugInfo::BreakAtEntry() const { return (flags() & kBreakAtEntry) != 0; }
      70             : 
      71     3080032 : bool DebugInfo::CanBreakAtEntry() const {
      72     3080032 :   return (flags() & kCanBreakAtEntry) != 0;
      73             : }
      74             : 
      75             : // Check if there is a break point at this source position.
      76      186876 : bool DebugInfo::HasBreakPoint(Isolate* isolate, int source_position) {
      77             :   DCHECK(HasBreakInfo());
      78             :   // Get the break point info object for this code offset.
      79      186876 :   Object break_point_info = GetBreakPointInfo(isolate, source_position);
      80             : 
      81             :   // If there is no break point info object or no break points in the break
      82             :   // point info object there is no break point at this code offset.
      83      186876 :   if (break_point_info->IsUndefined(isolate)) return false;
      84        8576 :   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount(isolate) >
      85        4288 :          0;
      86             : }
      87             : 
      88             : // Get the break point info object for this source position.
      89      193570 : Object DebugInfo::GetBreakPointInfo(Isolate* isolate, int source_position) {
      90             :   DCHECK(HasBreakInfo());
      91     1675174 :   for (int i = 0; i < break_points()->length(); i++) {
      92      749424 :     if (!break_points()->get(i)->IsUndefined(isolate)) {
      93             :       BreakPointInfo break_point_info =
      94             :           BreakPointInfo::cast(break_points()->get(i));
      95       40554 :       if (break_point_info->source_position() == source_position) {
      96        8622 :         return break_point_info;
      97             :       }
      98             :     }
      99             :   }
     100      184948 :   return ReadOnlyRoots(isolate).undefined_value();
     101             : }
     102             : 
     103        2302 : bool DebugInfo::ClearBreakPoint(Isolate* isolate, Handle<DebugInfo> debug_info,
     104             :                                 Handle<BreakPoint> break_point) {
     105             :   DCHECK(debug_info->HasBreakInfo());
     106        3504 :   for (int i = 0; i < debug_info->break_points()->length(); i++) {
     107        2903 :     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) continue;
     108             :     Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
     109             :         BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
     110        2903 :     if (BreakPointInfo::HasBreakPoint(isolate, break_point_info, break_point)) {
     111        2302 :       BreakPointInfo::ClearBreakPoint(isolate, break_point_info, break_point);
     112        2302 :       return true;
     113             :     }
     114             :   }
     115             :   return false;
     116             : }
     117             : 
     118        2492 : void DebugInfo::SetBreakPoint(Isolate* isolate, Handle<DebugInfo> debug_info,
     119             :                               int source_position,
     120             :                               Handle<BreakPoint> break_point) {
     121             :   DCHECK(debug_info->HasBreakInfo());
     122             :   Handle<Object> break_point_info(
     123        4984 :       debug_info->GetBreakPointInfo(isolate, source_position), isolate);
     124        2492 :   if (!break_point_info->IsUndefined(isolate)) {
     125             :     BreakPointInfo::SetBreakPoint(
     126         132 :         isolate, Handle<BreakPointInfo>::cast(break_point_info), break_point);
     127         132 :     return;
     128             :   }
     129             : 
     130             :   // Adding a new break point for a code offset which did not have any
     131             :   // break points before. Try to find a free slot.
     132             :   static const int kNoBreakPointInfo = -1;
     133             :   int index = kNoBreakPointInfo;
     134        3558 :   for (int i = 0; i < debug_info->break_points()->length(); i++) {
     135        2945 :     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) {
     136             :       index = i;
     137             :       break;
     138             :     }
     139             :   }
     140        2360 :   if (index == kNoBreakPointInfo) {
     141             :     // No free slot - extend break point info array.
     142             :     Handle<FixedArray> old_break_points =
     143             :         Handle<FixedArray>(debug_info->break_points(), isolate);
     144             :     Handle<FixedArray> new_break_points = isolate->factory()->NewFixedArray(
     145             :         old_break_points->length() +
     146          14 :         DebugInfo::kEstimatedNofBreakPointsInFunction);
     147             : 
     148          14 :     debug_info->set_break_points(*new_break_points);
     149         126 :     for (int i = 0; i < old_break_points->length(); i++) {
     150          56 :       new_break_points->set(i, old_break_points->get(i));
     151             :     }
     152             :     index = old_break_points->length();
     153             :   }
     154             :   DCHECK_NE(index, kNoBreakPointInfo);
     155             : 
     156             :   // Allocate new BreakPointInfo object and set the break point.
     157             :   Handle<BreakPointInfo> new_break_point_info =
     158        2360 :       isolate->factory()->NewBreakPointInfo(source_position);
     159        2360 :   BreakPointInfo::SetBreakPoint(isolate, new_break_point_info, break_point);
     160        4720 :   debug_info->break_points()->set(index, *new_break_point_info);
     161             : }
     162             : 
     163             : // Get the break point objects for a source position.
     164        4202 : Handle<Object> DebugInfo::GetBreakPoints(Isolate* isolate,
     165             :                                          int source_position) {
     166             :   DCHECK(HasBreakInfo());
     167        4202 :   Object break_point_info = GetBreakPointInfo(isolate, source_position);
     168        4202 :   if (break_point_info->IsUndefined(isolate)) {
     169           0 :     return isolate->factory()->undefined_value();
     170             :   }
     171             :   return Handle<Object>(BreakPointInfo::cast(break_point_info)->break_points(),
     172        4202 :                         isolate);
     173             : }
     174             : 
     175             : // Get the total number of break points.
     176        3130 : int DebugInfo::GetBreakPointCount(Isolate* isolate) {
     177             :   DCHECK(HasBreakInfo());
     178             :   int count = 0;
     179       29242 :   for (int i = 0; i < break_points()->length(); i++) {
     180       13056 :     if (!break_points()->get(i)->IsUndefined(isolate)) {
     181             :       BreakPointInfo break_point_info =
     182        5434 :           BreakPointInfo::cast(break_points()->get(i));
     183        5434 :       count += break_point_info->GetBreakPointCount(isolate);
     184             :     }
     185             :   }
     186        3130 :   return count;
     187             : }
     188             : 
     189        8019 : Handle<Object> DebugInfo::FindBreakPointInfo(Isolate* isolate,
     190             :                                              Handle<DebugInfo> debug_info,
     191             :                                              Handle<BreakPoint> break_point) {
     192             :   DCHECK(debug_info->HasBreakInfo());
     193       55541 :   for (int i = 0; i < debug_info->break_points()->length(); i++) {
     194       26063 :     if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
     195             :       Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
     196             :           BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
     197        4800 :       if (BreakPointInfo::HasBreakPoint(isolate, break_point_info,
     198             :                                         break_point)) {
     199        2302 :         return break_point_info;
     200             :       }
     201             :     }
     202             :   }
     203        5717 :   return isolate->factory()->undefined_value();
     204             : }
     205             : 
     206      192428 : bool DebugInfo::HasCoverageInfo() const {
     207      208111 :   return (flags() & kHasCoverageInfo) != 0;
     208             : }
     209             : 
     210       15683 : void DebugInfo::ClearCoverageInfo(Isolate* isolate) {
     211       15683 :   if (HasCoverageInfo()) {
     212         880 :     set_coverage_info(ReadOnlyRoots(isolate).undefined_value());
     213             : 
     214         880 :     int new_flags = flags() & ~kHasCoverageInfo;
     215             :     set_flags(new_flags);
     216             :   }
     217       15683 : }
     218             : 
     219       13869 : DebugInfo::SideEffectState DebugInfo::GetSideEffectState(Isolate* isolate) {
     220       13869 :   if (side_effect_state() == kNotComputed) {
     221             :     SideEffectState has_no_side_effect =
     222             :         DebugEvaluate::FunctionGetSideEffectState(isolate,
     223       12255 :                                                   handle(shared(), isolate));
     224       12255 :     set_side_effect_state(has_no_side_effect);
     225             :   }
     226       13869 :   return static_cast<SideEffectState>(side_effect_state());
     227             : }
     228             : 
     229             : namespace {
     230             : bool IsEqual(BreakPoint break_point1, BreakPoint break_point2) {
     231        6478 :   return break_point1->id() == break_point2->id();
     232             : }
     233             : }  // namespace
     234             : 
     235             : // Remove the specified break point object.
     236        2302 : void BreakPointInfo::ClearBreakPoint(Isolate* isolate,
     237             :                                      Handle<BreakPointInfo> break_point_info,
     238             :                                      Handle<BreakPoint> break_point) {
     239             :   // If there are no break points just ignore.
     240        2302 :   if (break_point_info->break_points()->IsUndefined(isolate)) return;
     241             :   // If there is a single break point clear it if it is the same.
     242        2302 :   if (!break_point_info->break_points()->IsFixedArray()) {
     243        2143 :     if (IsEqual(BreakPoint::cast(break_point_info->break_points()),
     244             :                 *break_point)) {
     245        4286 :       break_point_info->set_break_points(
     246        6429 :           ReadOnlyRoots(isolate).undefined_value());
     247             :     }
     248             :     return;
     249             :   }
     250             :   // If there are multiple break points shrink the array
     251             :   DCHECK(break_point_info->break_points()->IsFixedArray());
     252             :   Handle<FixedArray> old_array = Handle<FixedArray>(
     253             :       FixedArray::cast(break_point_info->break_points()), isolate);
     254             :   Handle<FixedArray> new_array =
     255         159 :       isolate->factory()->NewFixedArray(old_array->length() - 1);
     256             :   int found_count = 0;
     257        2109 :   for (int i = 0; i < old_array->length(); i++) {
     258         975 :     if (IsEqual(BreakPoint::cast(old_array->get(i)), *break_point)) {
     259             :       DCHECK_EQ(found_count, 0);
     260         159 :       found_count++;
     261             :     } else {
     262        1632 :       new_array->set(i - found_count, old_array->get(i));
     263             :     }
     264             :   }
     265             :   // If the break point was found in the list change it.
     266         477 :   if (found_count > 0) break_point_info->set_break_points(*new_array);
     267             : }
     268             : 
     269             : // Add the specified break point object.
     270        2608 : void BreakPointInfo::SetBreakPoint(Isolate* isolate,
     271             :                                    Handle<BreakPointInfo> break_point_info,
     272             :                                    Handle<BreakPoint> break_point) {
     273             :   // If there was no break point objects before just set it.
     274        2608 :   if (break_point_info->break_points()->IsUndefined(isolate)) {
     275        2476 :     break_point_info->set_break_points(*break_point);
     276        2476 :     return;
     277             :   }
     278             :   // If the break point object is the same as before just ignore.
     279         132 :   if (break_point_info->break_points() == *break_point) return;
     280             :   // If there was one break point object before replace with array.
     281         132 :   if (!break_point_info->break_points()->IsFixedArray()) {
     282          27 :     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
     283          27 :     array->set(0, break_point_info->break_points());
     284          54 :     array->set(1, *break_point);
     285          54 :     break_point_info->set_break_points(*array);
     286             :     return;
     287             :   }
     288             :   // If there was more than one break point before extend array.
     289             :   Handle<FixedArray> old_array = Handle<FixedArray>(
     290             :       FixedArray::cast(break_point_info->break_points()), isolate);
     291             :   Handle<FixedArray> new_array =
     292         105 :       isolate->factory()->NewFixedArray(old_array->length() + 1);
     293        1683 :   for (int i = 0; i < old_array->length(); i++) {
     294             :     // If the break point was there before just ignore.
     295         789 :     if (IsEqual(BreakPoint::cast(old_array->get(i)), *break_point)) return;
     296         789 :     new_array->set(i, old_array->get(i));
     297             :   }
     298             :   // Add the new break point.
     299         210 :   new_array->set(old_array->length(), *break_point);
     300         210 :   break_point_info->set_break_points(*new_array);
     301             : }
     302             : 
     303        7703 : bool BreakPointInfo::HasBreakPoint(Isolate* isolate,
     304             :                                    Handle<BreakPointInfo> break_point_info,
     305             :                                    Handle<BreakPoint> break_point) {
     306             :   // No break point.
     307        7703 :   if (break_point_info->break_points()->IsUndefined(isolate)) {
     308             :     return false;
     309             :   }
     310             :   // Single break point.
     311        6876 :   if (!break_point_info->break_points()->IsFixedArray()) {
     312             :     return IsEqual(BreakPoint::cast(break_point_info->break_points()),
     313             :                    *break_point);
     314             :   }
     315             :   // Multiple break points.
     316             :   FixedArray array = FixedArray::cast(break_point_info->break_points());
     317        2454 :   for (int i = 0; i < array->length(); i++) {
     318        1346 :     if (IsEqual(BreakPoint::cast(array->get(i)), *break_point)) {
     319             :       return true;
     320             :     }
     321             :   }
     322             :   return false;
     323             : }
     324             : 
     325             : // Get the number of break points.
     326       78560 : int BreakPointInfo::GetBreakPointCount(Isolate* isolate) {
     327             :   // No break point.
     328       78560 :   if (break_points()->IsUndefined(isolate)) return 0;
     329             :   // Single break point.
     330       74495 :   if (!break_points()->IsFixedArray()) return 1;
     331             :   // Multiple break points.
     332             :   return FixedArray::cast(break_points())->length();
     333             : }
     334             : 
     335      124868 : int CoverageInfo::SlotCount() const {
     336             :   DCHECK_EQ(kFirstSlotIndex, length() % kSlotIndexCount);
     337      124868 :   return (length() - kFirstSlotIndex) / kSlotIndexCount;
     338             : }
     339             : 
     340       46264 : int CoverageInfo::StartSourcePosition(int slot_index) const {
     341             :   DCHECK_LT(slot_index, SlotCount());
     342             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     343       46264 :   return Smi::ToInt(get(slot_start + kSlotStartSourcePositionIndex));
     344             : }
     345             : 
     346       46264 : int CoverageInfo::EndSourcePosition(int slot_index) const {
     347             :   DCHECK_LT(slot_index, SlotCount());
     348             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     349       92528 :   return Smi::ToInt(get(slot_start + kSlotEndSourcePositionIndex));
     350             : }
     351             : 
     352       46264 : int CoverageInfo::BlockCount(int slot_index) const {
     353             :   DCHECK_LT(slot_index, SlotCount());
     354             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     355      272028 :   return Smi::ToInt(get(slot_start + kSlotBlockCountIndex));
     356             : }
     357             : 
     358        2268 : void CoverageInfo::InitializeSlot(int slot_index, int from_pos, int to_pos) {
     359             :   DCHECK_LT(slot_index, SlotCount());
     360             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     361             :   set(slot_start + kSlotStartSourcePositionIndex, Smi::FromInt(from_pos));
     362             :   set(slot_start + kSlotEndSourcePositionIndex, Smi::FromInt(to_pos));
     363        2268 :   set(slot_start + kSlotBlockCountIndex, Smi::kZero);
     364        2268 : }
     365             : 
     366      179500 : void CoverageInfo::IncrementBlockCount(int slot_index) {
     367             :   DCHECK_LT(slot_index, SlotCount());
     368             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     369             :   const int old_count = BlockCount(slot_index);
     370      179500 :   set(slot_start + kSlotBlockCountIndex, Smi::FromInt(old_count + 1));
     371      179500 : }
     372             : 
     373       46264 : void CoverageInfo::ResetBlockCount(int slot_index) {
     374             :   DCHECK_LT(slot_index, SlotCount());
     375             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     376       46264 :   set(slot_start + kSlotBlockCountIndex, Smi::kZero);
     377       46264 : }
     378             : 
     379           0 : void CoverageInfo::Print(std::unique_ptr<char[]> function_name) {
     380             :   DCHECK(FLAG_trace_block_coverage);
     381             :   DisallowHeapAllocation no_gc;
     382             : 
     383           0 :   StdoutStream os;
     384           0 :   os << "Coverage info (";
     385           0 :   if (strlen(function_name.get()) > 0) {
     386           0 :     os << function_name.get();
     387             :   } else {
     388           0 :     os << "{anonymous}";
     389             :   }
     390             :   os << "):" << std::endl;
     391             : 
     392           0 :   for (int i = 0; i < SlotCount(); i++) {
     393           0 :     os << "{" << StartSourcePosition(i) << "," << EndSourcePosition(i) << "}"
     394             :        << std::endl;
     395             :   }
     396           0 : }
     397             : 
     398             : }  // namespace internal
     399      121996 : }  // namespace v8

Generated by: LCOV version 1.10