LCOV - code coverage report
Current view: top level - src/objects - debug-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 146 158 92.4 %
Date: 2019-02-19 Functions: 33 34 97.1 %

          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       58617 : bool DebugInfo::IsEmpty() const {
      16      117046 :   return flags() == kNone && debugger_hints() == 0;
      17             : }
      18             : 
      19     3251814 : bool DebugInfo::HasBreakInfo() const { return (flags() & kHasBreakInfo) != 0; }
      20             : 
      21       12975 : DebugInfo::ExecutionMode DebugInfo::DebugExecutionMode() const {
      22       12975 :   return (flags() & kDebugExecutionMode) != 0 ? kSideEffects : kBreakpoints;
      23             : }
      24             : 
      25     1138056 : void DebugInfo::SetDebugExecutionMode(ExecutionMode value) {
      26             :   set_flags(value == kSideEffects ? (flags() | kDebugExecutionMode)
      27     2276112 :                                   : (flags() & ~kDebugExecutionMode));
      28     1138056 : }
      29             : 
      30       28349 : void DebugInfo::ClearBreakInfo(Isolate* isolate) {
      31       28349 :   if (HasInstrumentedBytecodeArray()) {
      32             :     // Reset function's bytecode array field to point to the original bytecode
      33             :     // array.
      34       10577 :     shared()->SetDebugBytecodeArray(OriginalBytecodeArray());
      35       10577 :     set_original_bytecode_array(ReadOnlyRoots(isolate).undefined_value());
      36       10577 :     set_debug_bytecode_array(ReadOnlyRoots(isolate).undefined_value());
      37             :   }
      38       28349 :   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       28349 :   new_flags &= ~kDebugExecutionMode;
      44             :   set_flags(new_flags);
      45       28349 : }
      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       10208 : bool DebugInfo::BreakAtEntry() const { return (flags() & kBreakAtEntry) != 0; }
      58             : 
      59     2987554 : bool DebugInfo::CanBreakAtEntry() const {
      60     2987554 :   return (flags() & kCanBreakAtEntry) != 0;
      61             : }
      62             : 
      63             : // Check if there is a break point at this source position.
      64      186838 : bool DebugInfo::HasBreakPoint(Isolate* isolate, int source_position) {
      65             :   DCHECK(HasBreakInfo());
      66             :   // Get the break point info object for this code offset.
      67      186838 :   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      186838 :   if (break_point_info->IsUndefined(isolate)) return false;
      72        8500 :   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount(isolate) >
      73        4250 :          0;
      74             : }
      75             : 
      76             : // Get the break point info object for this source position.
      77      193470 : Object DebugInfo::GetBreakPointInfo(Isolate* isolate, int source_position) {
      78             :   DCHECK(HasBreakInfo());
      79     1868352 :   for (int i = 0; i < break_points()->length(); i++) {
      80     2247756 :     if (!break_points()->get(i)->IsUndefined(isolate)) {
      81             :       BreakPointInfo break_point_info =
      82       80956 :           BreakPointInfo::cast(break_points()->get(i));
      83       40478 :       if (break_point_info->source_position() == source_position) {
      84        8546 :         return break_point_info;
      85             :       }
      86             :     }
      87             :   }
      88      184924 :   return ReadOnlyRoots(isolate).undefined_value();
      89             : }
      90             : 
      91        2278 : bool DebugInfo::ClearBreakPoint(Isolate* isolate, Handle<DebugInfo> debug_info,
      92             :                                 Handle<BreakPoint> break_point) {
      93             :   DCHECK(debug_info->HasBreakInfo());
      94        8637 :   for (int i = 0; i < debug_info->break_points()->length(); i++) {
      95        8637 :     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) continue;
      96             :     Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
      97        5758 :         BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
      98        2879 :     if (BreakPointInfo::HasBreakPoint(isolate, break_point_info, break_point)) {
      99        2278 :       BreakPointInfo::ClearBreakPoint(isolate, break_point_info, break_point);
     100        2278 :       return true;
     101             :     }
     102             :   }
     103             :   return false;
     104             : }
     105             : 
     106        2468 : 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        4936 :       debug_info->GetBreakPointInfo(isolate, source_position), isolate);
     112        4936 :   if (!break_point_info->IsUndefined(isolate)) {
     113             :     BreakPointInfo::SetBreakPoint(
     114         132 :         isolate, Handle<BreakPointInfo>::cast(break_point_info), break_point);
     115        2600 :     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        6469 :   for (int i = 0; i < debug_info->break_points()->length(); i++) {
     123        8763 :     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) {
     124             :       index = i;
     125             :       break;
     126             :     }
     127             :   }
     128        2336 :   if (index == kNoBreakPointInfo) {
     129             :     // No free slot - extend break point info array.
     130             :     Handle<FixedArray> old_break_points =
     131          28 :         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         140 :     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        2336 :       isolate->factory()->NewBreakPointInfo(source_position);
     147        2336 :   BreakPointInfo::SetBreakPoint(isolate, new_break_point_info, break_point);
     148        4672 :   debug_info->break_points()->set(index, *new_break_point_info);
     149             : }
     150             : 
     151             : // Get the break point objects for a source position.
     152        4164 : Handle<Object> DebugInfo::GetBreakPoints(Isolate* isolate,
     153             :                                          int source_position) {
     154             :   DCHECK(HasBreakInfo());
     155        4164 :   Object break_point_info = GetBreakPointInfo(isolate, source_position);
     156        4164 :   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        4164 :                         isolate);
     161             : }
     162             : 
     163             : // Get the total number of break points.
     164        3106 : int DebugInfo::GetBreakPointCount(Isolate* isolate) {
     165             :   DCHECK(HasBreakInfo());
     166             :   int count = 0;
     167       32132 :   for (int i = 0; i < break_points()->length(); i++) {
     168       38880 :     if (!break_points()->get(i)->IsUndefined(isolate)) {
     169             :       BreakPointInfo break_point_info =
     170       10820 :           BreakPointInfo::cast(break_points()->get(i));
     171        5410 :       count += break_point_info->GetBreakPointCount(isolate);
     172             :     }
     173             :   }
     174        3106 :   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       95493 :   for (int i = 0; i < debug_info->break_points()->length(); i++) {
     182       78297 :     if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
     183             :       Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
     184        9552 :           BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
     185        4776 :       if (BreakPointInfo::HasBreakPoint(isolate, break_point_info,
     186             :                                         break_point)) {
     187        2278 :         return break_point_info;
     188             :       }
     189             :     }
     190             :   }
     191        5732 :   return isolate->factory()->undefined_value();
     192             : }
     193             : 
     194      207498 : bool DebugInfo::HasCoverageInfo() const {
     195      207498 :   return (flags() & kHasCoverageInfo) != 0;
     196             : }
     197             : 
     198       15578 : void DebugInfo::ClearCoverageInfo(Isolate* isolate) {
     199       15578 :   if (HasCoverageInfo()) {
     200         872 :     set_coverage_info(ReadOnlyRoots(isolate).undefined_value());
     201             : 
     202         872 :     int new_flags = flags() & ~kHasCoverageInfo;
     203             :     set_flags(new_flags);
     204             :   }
     205       15578 : }
     206             : 
     207       13700 : DebugInfo::SideEffectState DebugInfo::GetSideEffectState(Isolate* isolate) {
     208       13700 :   if (side_effect_state() == kNotComputed) {
     209             :     SideEffectState has_no_side_effect =
     210             :         DebugEvaluate::FunctionGetSideEffectState(isolate,
     211       24316 :                                                   handle(shared(), isolate));
     212       12158 :     set_side_effect_state(has_no_side_effect);
     213             :   }
     214       13700 :   return static_cast<SideEffectState>(side_effect_state());
     215             : }
     216             : 
     217             : namespace {
     218       11689 : bool IsEqual(BreakPoint break_point1, BreakPoint break_point2) {
     219       11689 :   return break_point1->id() == break_point2->id();
     220             : }
     221             : }  // namespace
     222             : 
     223             : // Remove the specified break point object.
     224        2278 : 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        4556 :   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        4556 :   if (!break_point_info->break_points()->IsFixedArray()) {
     231        2119 :     if (IsEqual(BreakPoint::cast(break_point_info->break_points()),
     232             :                 *break_point)) {
     233             :       break_point_info->set_break_points(
     234        4238 :           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        2268 :   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        2580 : 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        5160 :   if (break_point_info->break_points()->IsUndefined(isolate)) {
     263        4896 :     break_point_info->set_break_points(*break_point);
     264        2448 :     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         264 :   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        1788 :   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        7655 : bool BreakPointInfo::HasBreakPoint(Isolate* isolate,
     292             :                                    Handle<BreakPointInfo> break_point_info,
     293             :                                    Handle<BreakPoint> break_point) {
     294             :   // No break point.
     295       15310 :   if (break_point_info->break_points()->IsUndefined(isolate)) {
     296             :     return false;
     297             :   }
     298             :   // Single break point.
     299       13716 :   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        2852 :   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       78451 : int BreakPointInfo::GetBreakPointCount(Isolate* isolate) {
     315             :   // No break point.
     316      156902 :   if (break_points()->IsUndefined(isolate)) return 0;
     317             :   // Single break point.
     318      148820 :   if (!break_points()->IsFixedArray()) return 1;
     319             :   // Multiple break points.
     320             :   return FixedArray::cast(break_points())->length();
     321             : }
     322             : 
     323      121912 : int CoverageInfo::SlotCount() const {
     324             :   DCHECK_EQ(kFirstSlotIndex, length() % kSlotIndexCount);
     325      121912 :   return (length() - kFirstSlotIndex) / kSlotIndexCount;
     326             : }
     327             : 
     328       45380 : int CoverageInfo::StartSourcePosition(int slot_index) const {
     329             :   DCHECK_LT(slot_index, SlotCount());
     330             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     331       45380 :   return Smi::ToInt(get(slot_start + kSlotStartSourcePositionIndex));
     332             : }
     333             : 
     334       45380 : int CoverageInfo::EndSourcePosition(int slot_index) const {
     335             :   DCHECK_LT(slot_index, SlotCount());
     336             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     337       90760 :   return Smi::ToInt(get(slot_start + kSlotEndSourcePositionIndex));
     338             : }
     339             : 
     340      224828 : int CoverageInfo::BlockCount(int slot_index) const {
     341             :   DCHECK_LT(slot_index, SlotCount());
     342             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     343      449656 :   return Smi::ToInt(get(slot_start + kSlotBlockCountIndex));
     344             : }
     345             : 
     346        2272 : 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        2272 :   set(slot_start + kSlotBlockCountIndex, Smi::kZero);
     352        2272 : }
     353             : 
     354      179448 : void CoverageInfo::IncrementBlockCount(int slot_index) {
     355             :   DCHECK_LT(slot_index, SlotCount());
     356             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     357      179448 :   const int old_count = BlockCount(slot_index);
     358      179448 :   set(slot_start + kSlotBlockCountIndex, Smi::FromInt(old_count + 1));
     359      179448 : }
     360             : 
     361       45380 : void CoverageInfo::ResetBlockCount(int slot_index) {
     362             :   DCHECK_LT(slot_index, SlotCount());
     363             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     364       45380 :   set(slot_start + kSlotBlockCountIndex, Smi::kZero);
     365       45380 : }
     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           0 :   os << "):" << std::endl;
     379             : 
     380           0 :   for (int i = 0; i < SlotCount(); i++) {
     381           0 :     os << "{" << StartSourcePosition(i) << "," << EndSourcePosition(i) << "}"
     382             :        << std::endl;
     383           0 :   }
     384           0 : }
     385             : 
     386             : }  // namespace internal
     387      178779 : }  // namespace v8

Generated by: LCOV version 1.10