LCOV - code coverage report
Current view: top level - src/objects - debug-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 142 152 93.4 %
Date: 2019-03-21 Functions: 32 33 97.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/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       58815 : bool DebugInfo::IsEmpty() const {
      16      117442 :   return flags() == kNone && debugger_hints() == 0;
      17             : }
      18             : 
      19     3269806 : 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     1145845 : void DebugInfo::SetDebugExecutionMode(ExecutionMode value) {
      26     2291690 :   set_flags(value == kSideEffects ? (flags() | kDebugExecutionMode)
      27             :                                   : (flags() & ~kDebugExecutionMode));
      28     1145845 : }
      29             : 
      30       28399 : void DebugInfo::ClearBreakInfo(Isolate* isolate) {
      31       28399 :   if (HasInstrumentedBytecodeArray()) {
      32             :     // Reset function's bytecode array field to point to the original bytecode
      33             :     // array.
      34       10592 :     shared()->SetDebugBytecodeArray(OriginalBytecodeArray());
      35       10592 :     set_original_bytecode_array(ReadOnlyRoots(isolate).undefined_value());
      36       10592 :     set_debug_bytecode_array(ReadOnlyRoots(isolate).undefined_value());
      37             :   }
      38       28399 :   set_break_points(ReadOnlyRoots(isolate).empty_fixed_array());
      39             : 
      40             :   int new_flags = flags();
      41             :   new_flags &= ~kHasBreakInfo & ~kPreparedForDebugExecution;
      42             :   new_flags &= ~kBreakAtEntry & ~kCanBreakAtEntry;
      43       28399 :   new_flags &= ~kDebugExecutionMode;
      44             :   set_flags(new_flags);
      45       28399 : }
      46             : 
      47         585 : void DebugInfo::SetBreakAtEntry() {
      48             :   DCHECK(CanBreakAtEntry());
      49         585 :   set_flags(flags() | kBreakAtEntry);
      50         585 : }
      51             : 
      52         735 : void DebugInfo::ClearBreakAtEntry() {
      53             :   DCHECK(CanBreakAtEntry());
      54         735 :   set_flags(flags() & ~kBreakAtEntry);
      55         735 : }
      56             : 
      57       10246 : bool DebugInfo::BreakAtEntry() const { return (flags() & kBreakAtEntry) != 0; }
      58             : 
      59     3079820 : bool DebugInfo::CanBreakAtEntry() const {
      60     3079820 :   return (flags() & kCanBreakAtEntry) != 0;
      61             : }
      62             : 
      63             : // Check if there is a break point at this source position.
      64      186857 : bool DebugInfo::HasBreakPoint(Isolate* isolate, int source_position) {
      65             :   DCHECK(HasBreakInfo());
      66             :   // Get the break point info object for this code offset.
      67      186857 :   Object break_point_info = GetBreakPointInfo(isolate, source_position);
      68             : 
      69             :   // If there is no break point info object or no break points in the break
      70             :   // point info object there is no break point at this code offset.
      71      186857 :   if (break_point_info->IsUndefined(isolate)) return false;
      72        8538 :   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount(isolate) >
      73        4269 :          0;
      74             : }
      75             : 
      76             : // Get the break point info object for this source position.
      77      193523 : Object DebugInfo::GetBreakPointInfo(Isolate* isolate, int source_position) {
      78             :   DCHECK(HasBreakInfo());
      79     1675055 :   for (int i = 0; i < break_points()->length(); i++) {
      80             :     if (!break_points()->get(i)->IsUndefined(isolate)) {
      81             :       BreakPointInfo break_point_info =
      82             :           BreakPointInfo::cast(break_points()->get(i));
      83       40516 :       if (break_point_info->source_position() == source_position) {
      84        8584 :         return break_point_info;
      85             :       }
      86             :     }
      87             :   }
      88      184939 :   return ReadOnlyRoots(isolate).undefined_value();
      89             : }
      90             : 
      91        2293 : bool DebugInfo::ClearBreakPoint(Isolate* isolate, Handle<DebugInfo> debug_info,
      92             :                                 Handle<BreakPoint> break_point) {
      93             :   DCHECK(debug_info->HasBreakInfo());
      94        3495 :   for (int i = 0; i < debug_info->break_points()->length(); i++) {
      95        2894 :     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) continue;
      96             :     Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
      97             :         BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
      98        2894 :     if (BreakPointInfo::HasBreakPoint(isolate, break_point_info, break_point)) {
      99        2293 :       BreakPointInfo::ClearBreakPoint(isolate, break_point_info, break_point);
     100        2293 :       return true;
     101             :     }
     102             :   }
     103             :   return false;
     104             : }
     105             : 
     106        2483 : void DebugInfo::SetBreakPoint(Isolate* isolate, Handle<DebugInfo> debug_info,
     107             :                               int source_position,
     108             :                               Handle<BreakPoint> break_point) {
     109             :   DCHECK(debug_info->HasBreakInfo());
     110             :   Handle<Object> break_point_info(
     111        4966 :       debug_info->GetBreakPointInfo(isolate, source_position), isolate);
     112        2483 :   if (!break_point_info->IsUndefined(isolate)) {
     113             :     BreakPointInfo::SetBreakPoint(
     114         132 :         isolate, Handle<BreakPointInfo>::cast(break_point_info), break_point);
     115         132 :     return;
     116             :   }
     117             : 
     118             :   // Adding a new break point for a code offset which did not have any
     119             :   // break points before. Try to find a free slot.
     120             :   static const int kNoBreakPointInfo = -1;
     121             :   int index = kNoBreakPointInfo;
     122        3549 :   for (int i = 0; i < debug_info->break_points()->length(); i++) {
     123        2936 :     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) {
     124             :       index = i;
     125             :       break;
     126             :     }
     127             :   }
     128        2351 :   if (index == kNoBreakPointInfo) {
     129             :     // No free slot - extend break point info array.
     130             :     Handle<FixedArray> old_break_points =
     131             :         Handle<FixedArray>(debug_info->break_points(), isolate);
     132             :     Handle<FixedArray> new_break_points = isolate->factory()->NewFixedArray(
     133             :         old_break_points->length() +
     134          14 :         DebugInfo::kEstimatedNofBreakPointsInFunction);
     135             : 
     136          14 :     debug_info->set_break_points(*new_break_points);
     137         126 :     for (int i = 0; i < old_break_points->length(); i++) {
     138          56 :       new_break_points->set(i, old_break_points->get(i));
     139             :     }
     140             :     index = old_break_points->length();
     141             :   }
     142             :   DCHECK_NE(index, kNoBreakPointInfo);
     143             : 
     144             :   // Allocate new BreakPointInfo object and set the break point.
     145             :   Handle<BreakPointInfo> new_break_point_info =
     146        2351 :       isolate->factory()->NewBreakPointInfo(source_position);
     147        2351 :   BreakPointInfo::SetBreakPoint(isolate, new_break_point_info, break_point);
     148        4702 :   debug_info->break_points()->set(index, *new_break_point_info);
     149             : }
     150             : 
     151             : // Get the break point objects for a source position.
     152        4183 : Handle<Object> DebugInfo::GetBreakPoints(Isolate* isolate,
     153             :                                          int source_position) {
     154             :   DCHECK(HasBreakInfo());
     155        4183 :   Object break_point_info = GetBreakPointInfo(isolate, source_position);
     156        4183 :   if (break_point_info->IsUndefined(isolate)) {
     157           0 :     return isolate->factory()->undefined_value();
     158             :   }
     159             :   return Handle<Object>(BreakPointInfo::cast(break_point_info)->break_points(),
     160        4183 :                         isolate);
     161             : }
     162             : 
     163             : // Get the total number of break points.
     164        3121 : int DebugInfo::GetBreakPointCount(Isolate* isolate) {
     165             :   DCHECK(HasBreakInfo());
     166             :   int count = 0;
     167       29161 :   for (int i = 0; i < break_points()->length(); i++) {
     168       13020 :     if (!break_points()->get(i)->IsUndefined(isolate)) {
     169             :       BreakPointInfo break_point_info =
     170        5425 :           BreakPointInfo::cast(break_points()->get(i));
     171        5425 :       count += break_point_info->GetBreakPointCount(isolate);
     172             :     }
     173             :   }
     174        3121 :   return count;
     175             : }
     176             : 
     177        8010 : Handle<Object> DebugInfo::FindBreakPointInfo(Isolate* isolate,
     178             :                                              Handle<DebugInfo> debug_info,
     179             :                                              Handle<BreakPoint> break_point) {
     180             :   DCHECK(debug_info->HasBreakInfo());
     181       55532 :   for (int i = 0; i < debug_info->break_points()->length(); i++) {
     182       26054 :     if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
     183             :       Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
     184             :           BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
     185        4791 :       if (BreakPointInfo::HasBreakPoint(isolate, break_point_info,
     186             :                                         break_point)) {
     187        2293 :         return break_point_info;
     188             :       }
     189             :     }
     190             :   }
     191        5717 :   return isolate->factory()->undefined_value();
     192             : }
     193             : 
     194      192428 : bool DebugInfo::HasCoverageInfo() const {
     195      208084 :   return (flags() & kHasCoverageInfo) != 0;
     196             : }
     197             : 
     198       15656 : void DebugInfo::ClearCoverageInfo(Isolate* isolate) {
     199       15656 :   if (HasCoverageInfo()) {
     200         880 :     set_coverage_info(ReadOnlyRoots(isolate).undefined_value());
     201             : 
     202         880 :     int new_flags = flags() & ~kHasCoverageInfo;
     203             :     set_flags(new_flags);
     204             :   }
     205       15656 : }
     206             : 
     207       13770 : DebugInfo::SideEffectState DebugInfo::GetSideEffectState(Isolate* isolate) {
     208       13770 :   if (side_effect_state() == kNotComputed) {
     209             :     SideEffectState has_no_side_effect =
     210             :         DebugEvaluate::FunctionGetSideEffectState(isolate,
     211       12228 :                                                   handle(shared(), isolate));
     212       12228 :     set_side_effect_state(has_no_side_effect);
     213             :   }
     214       13770 :   return static_cast<SideEffectState>(side_effect_state());
     215             : }
     216             : 
     217             : namespace {
     218       11704 : bool IsEqual(BreakPoint break_point1, BreakPoint break_point2) {
     219       11704 :   return break_point1->id() == break_point2->id();
     220             : }
     221             : }  // namespace
     222             : 
     223             : // Remove the specified break point object.
     224        2293 : void BreakPointInfo::ClearBreakPoint(Isolate* isolate,
     225             :                                      Handle<BreakPointInfo> break_point_info,
     226             :                                      Handle<BreakPoint> break_point) {
     227             :   // If there are no break points just ignore.
     228        2293 :   if (break_point_info->break_points()->IsUndefined(isolate)) return;
     229             :   // If there is a single break point clear it if it is the same.
     230        2293 :   if (!break_point_info->break_points()->IsFixedArray()) {
     231        2134 :     if (IsEqual(BreakPoint::cast(break_point_info->break_points()),
     232             :                 *break_point)) {
     233        4268 :       break_point_info->set_break_points(
     234        6402 :           ReadOnlyRoots(isolate).undefined_value());
     235             :     }
     236             :     return;
     237             :   }
     238             :   // If there are multiple break points shrink the array
     239             :   DCHECK(break_point_info->break_points()->IsFixedArray());
     240             :   Handle<FixedArray> old_array = Handle<FixedArray>(
     241             :       FixedArray::cast(break_point_info->break_points()), isolate);
     242             :   Handle<FixedArray> new_array =
     243         159 :       isolate->factory()->NewFixedArray(old_array->length() - 1);
     244             :   int found_count = 0;
     245        2109 :   for (int i = 0; i < old_array->length(); i++) {
     246         975 :     if (IsEqual(BreakPoint::cast(old_array->get(i)), *break_point)) {
     247             :       DCHECK_EQ(found_count, 0);
     248         159 :       found_count++;
     249             :     } else {
     250        1632 :       new_array->set(i - found_count, old_array->get(i));
     251             :     }
     252             :   }
     253             :   // If the break point was found in the list change it.
     254         477 :   if (found_count > 0) break_point_info->set_break_points(*new_array);
     255             : }
     256             : 
     257             : // Add the specified break point object.
     258        2595 : void BreakPointInfo::SetBreakPoint(Isolate* isolate,
     259             :                                    Handle<BreakPointInfo> break_point_info,
     260             :                                    Handle<BreakPoint> break_point) {
     261             :   // If there was no break point objects before just set it.
     262        2595 :   if (break_point_info->break_points()->IsUndefined(isolate)) {
     263        2463 :     break_point_info->set_break_points(*break_point);
     264        2463 :     return;
     265             :   }
     266             :   // If the break point object is the same as before just ignore.
     267         132 :   if (break_point_info->break_points() == *break_point) return;
     268             :   // If there was one break point object before replace with array.
     269         132 :   if (!break_point_info->break_points()->IsFixedArray()) {
     270          27 :     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
     271          27 :     array->set(0, break_point_info->break_points());
     272          54 :     array->set(1, *break_point);
     273          54 :     break_point_info->set_break_points(*array);
     274             :     return;
     275             :   }
     276             :   // If there was more than one break point before extend array.
     277             :   Handle<FixedArray> old_array = Handle<FixedArray>(
     278             :       FixedArray::cast(break_point_info->break_points()), isolate);
     279             :   Handle<FixedArray> new_array =
     280         105 :       isolate->factory()->NewFixedArray(old_array->length() + 1);
     281        1683 :   for (int i = 0; i < old_array->length(); i++) {
     282             :     // If the break point was there before just ignore.
     283         789 :     if (IsEqual(BreakPoint::cast(old_array->get(i)), *break_point)) return;
     284         789 :     new_array->set(i, old_array->get(i));
     285             :   }
     286             :   // Add the new break point.
     287         210 :   new_array->set(old_array->length(), *break_point);
     288         210 :   break_point_info->set_break_points(*new_array);
     289             : }
     290             : 
     291        7685 : bool BreakPointInfo::HasBreakPoint(Isolate* isolate,
     292             :                                    Handle<BreakPointInfo> break_point_info,
     293             :                                    Handle<BreakPoint> break_point) {
     294             :   // No break point.
     295        7685 :   if (break_point_info->break_points()->IsUndefined(isolate)) {
     296             :     return false;
     297             :   }
     298             :   // Single break point.
     299        6858 :   if (!break_point_info->break_points()->IsFixedArray()) {
     300             :     return IsEqual(BreakPoint::cast(break_point_info->break_points()),
     301        6460 :                    *break_point);
     302             :   }
     303             :   // Multiple break points.
     304             :   FixedArray array = FixedArray::cast(break_point_info->break_points());
     305        2454 :   for (int i = 0; i < array->length(); i++) {
     306        1346 :     if (IsEqual(BreakPoint::cast(array->get(i)), *break_point)) {
     307             :       return true;
     308             :     }
     309             :   }
     310             :   return false;
     311             : }
     312             : 
     313             : // Get the number of break points.
     314       78514 : int BreakPointInfo::GetBreakPointCount(Isolate* isolate) {
     315             :   // No break point.
     316       78514 :   if (break_points()->IsUndefined(isolate)) return 0;
     317             :   // Single break point.
     318       74458 :   if (!break_points()->IsFixedArray()) return 1;
     319             :   // Multiple break points.
     320             :   return FixedArray::cast(break_points())->length();
     321             : }
     322             : 
     323      124868 : int CoverageInfo::SlotCount() const {
     324             :   DCHECK_EQ(kFirstSlotIndex, length() % kSlotIndexCount);
     325      124868 :   return (length() - kFirstSlotIndex) / kSlotIndexCount;
     326             : }
     327             : 
     328       46264 : int CoverageInfo::StartSourcePosition(int slot_index) const {
     329             :   DCHECK_LT(slot_index, SlotCount());
     330             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     331       46264 :   return Smi::ToInt(get(slot_start + kSlotStartSourcePositionIndex));
     332             : }
     333             : 
     334       46264 : int CoverageInfo::EndSourcePosition(int slot_index) const {
     335             :   DCHECK_LT(slot_index, SlotCount());
     336             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     337       92528 :   return Smi::ToInt(get(slot_start + kSlotEndSourcePositionIndex));
     338             : }
     339             : 
     340      225764 : int CoverageInfo::BlockCount(int slot_index) const {
     341             :   DCHECK_LT(slot_index, SlotCount());
     342             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     343      451528 :   return Smi::ToInt(get(slot_start + kSlotBlockCountIndex));
     344             : }
     345             : 
     346        2268 : void CoverageInfo::InitializeSlot(int slot_index, int from_pos, int to_pos) {
     347             :   DCHECK_LT(slot_index, SlotCount());
     348             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     349             :   set(slot_start + kSlotStartSourcePositionIndex, Smi::FromInt(from_pos));
     350             :   set(slot_start + kSlotEndSourcePositionIndex, Smi::FromInt(to_pos));
     351        2268 :   set(slot_start + kSlotBlockCountIndex, Smi::kZero);
     352        2268 : }
     353             : 
     354      179500 : void CoverageInfo::IncrementBlockCount(int slot_index) {
     355             :   DCHECK_LT(slot_index, SlotCount());
     356             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     357      179500 :   const int old_count = BlockCount(slot_index);
     358      179500 :   set(slot_start + kSlotBlockCountIndex, Smi::FromInt(old_count + 1));
     359      179500 : }
     360             : 
     361       46264 : void CoverageInfo::ResetBlockCount(int slot_index) {
     362             :   DCHECK_LT(slot_index, SlotCount());
     363             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     364       46264 :   set(slot_start + kSlotBlockCountIndex, Smi::kZero);
     365       46264 : }
     366             : 
     367           0 : void CoverageInfo::Print(std::unique_ptr<char[]> function_name) {
     368             :   DCHECK(FLAG_trace_block_coverage);
     369             :   DisallowHeapAllocation no_gc;
     370             : 
     371           0 :   StdoutStream os;
     372           0 :   os << "Coverage info (";
     373           0 :   if (strlen(function_name.get()) > 0) {
     374           0 :     os << function_name.get();
     375             :   } else {
     376           0 :     os << "{anonymous}";
     377             :   }
     378             :   os << "):" << std::endl;
     379             : 
     380           0 :   for (int i = 0; i < SlotCount(); i++) {
     381           0 :     os << "{" << StartSourcePosition(i) << "," << EndSourcePosition(i) << "}"
     382             :        << std::endl;
     383             :   }
     384           0 : }
     385             : 
     386             : }  // namespace internal
     387      120216 : }  // namespace v8

Generated by: LCOV version 1.10