LCOV - code coverage report
Current view: top level - src/objects - debug-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 120 134 89.6 %
Date: 2017-10-20 Functions: 24 26 92.3 %

          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             : #include "src/objects/debug-objects-inl.h"
       7             : 
       8             : namespace v8 {
       9             : namespace internal {
      10             : 
      11           0 : bool DebugInfo::IsEmpty() const { return flags() == kNone; }
      12             : 
      13      617026 : bool DebugInfo::HasBreakInfo() const { return (flags() & kHasBreakInfo) != 0; }
      14             : 
      15       64481 : bool DebugInfo::IsPreparedForBreakpoints() const {
      16             :   DCHECK(HasBreakInfo());
      17       64481 :   return (flags() & kPreparedForBreakpoints) != 0;
      18             : }
      19             : 
      20        8341 : bool DebugInfo::ClearBreakInfo() {
      21             :   Isolate* isolate = GetIsolate();
      22             : 
      23        8341 :   set_debug_bytecode_array(isolate->heap()->undefined_value());
      24        8341 :   set_break_points(isolate->heap()->empty_fixed_array());
      25             : 
      26        8341 :   int new_flags = flags() & ~kHasBreakInfo & ~kPreparedForBreakpoints;
      27             :   set_flags(new_flags);
      28             : 
      29        8341 :   return new_flags == kNone;
      30             : }
      31             : 
      32             : // Check if there is a break point at this source position.
      33       60514 : bool DebugInfo::HasBreakPoint(int source_position) {
      34             :   DCHECK(HasBreakInfo());
      35             :   // Get the break point info object for this code offset.
      36       60514 :   Object* break_point_info = GetBreakPointInfo(source_position);
      37             : 
      38             :   // If there is no break point info object or no break points in the break
      39             :   // point info object there is no break point at this code offset.
      40       60514 :   if (break_point_info->IsUndefined(GetIsolate())) return false;
      41        4152 :   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
      42             : }
      43             : 
      44             : // Get the break point info object for this source position.
      45       66909 : Object* DebugInfo::GetBreakPointInfo(int source_position) {
      46             :   DCHECK(HasBreakInfo());
      47             :   Isolate* isolate = GetIsolate();
      48       66909 :   if (!break_points()->IsUndefined(isolate)) {
      49      537499 :     for (int i = 0; i < break_points()->length(); i++) {
      50      243662 :       if (!break_points()->get(i)->IsUndefined(isolate)) {
      51             :         BreakPointInfo* break_point_info =
      52             :             BreakPointInfo::cast(break_points()->get(i));
      53       36642 :         if (break_point_info->source_position() == source_position) {
      54             :           return break_point_info;
      55             :         }
      56             :       }
      57             :     }
      58             :   }
      59       58542 :   return isolate->heap()->undefined_value();
      60             : }
      61             : 
      62         894 : bool DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
      63             :                                 Handle<Object> break_point_object) {
      64             :   DCHECK(debug_info->HasBreakInfo());
      65             :   Isolate* isolate = debug_info->GetIsolate();
      66         894 :   if (debug_info->break_points()->IsUndefined(isolate)) return false;
      67             : 
      68        1112 :   for (int i = 0; i < debug_info->break_points()->length(); i++) {
      69        1003 :     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) continue;
      70             :     Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
      71             :         BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
      72        1003 :     if (BreakPointInfo::HasBreakPointObject(break_point_info,
      73             :                                             break_point_object)) {
      74         894 :       BreakPointInfo::ClearBreakPoint(break_point_info, break_point_object);
      75         894 :       return true;
      76             :     }
      77             :   }
      78             :   return false;
      79             : }
      80             : 
      81        2359 : void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info, int source_position,
      82             :                               Handle<Object> break_point_object) {
      83             :   DCHECK(debug_info->HasBreakInfo());
      84             :   Isolate* isolate = debug_info->GetIsolate();
      85             :   Handle<Object> break_point_info(
      86        2359 :       debug_info->GetBreakPointInfo(source_position), isolate);
      87        2359 :   if (!break_point_info->IsUndefined(isolate)) {
      88             :     BreakPointInfo::SetBreakPoint(
      89         179 :         Handle<BreakPointInfo>::cast(break_point_info), break_point_object);
      90        2538 :     return;
      91             :   }
      92             : 
      93             :   // Adding a new break point for a code offset which did not have any
      94             :   // break points before. Try to find a free slot.
      95             :   static const int kNoBreakPointInfo = -1;
      96             :   int index = kNoBreakPointInfo;
      97        3410 :   for (int i = 0; i < debug_info->break_points()->length(); i++) {
      98        2780 :     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) {
      99             :       index = i;
     100             :       break;
     101             :     }
     102             :   }
     103        2180 :   if (index == kNoBreakPointInfo) {
     104             :     // No free slot - extend break point info array.
     105             :     Handle<FixedArray> old_break_points = Handle<FixedArray>(
     106             :         FixedArray::cast(debug_info->break_points()), isolate);
     107             :     Handle<FixedArray> new_break_points = isolate->factory()->NewFixedArray(
     108             :         old_break_points->length() +
     109          15 :         DebugInfo::kEstimatedNofBreakPointsInFunction);
     110             : 
     111          15 :     debug_info->set_break_points(*new_break_points);
     112         150 :     for (int i = 0; i < old_break_points->length(); i++) {
     113          60 :       new_break_points->set(i, old_break_points->get(i));
     114             :     }
     115             :     index = old_break_points->length();
     116             :   }
     117             :   DCHECK_NE(index, kNoBreakPointInfo);
     118             : 
     119             :   // Allocate new BreakPointInfo object and set the break point.
     120             :   Handle<BreakPointInfo> new_break_point_info =
     121        2180 :       isolate->factory()->NewBreakPointInfo(source_position);
     122        2180 :   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
     123        2180 :   debug_info->break_points()->set(index, *new_break_point_info);
     124             : }
     125             : 
     126             : // Get the break point objects for a source position.
     127        4036 : Handle<Object> DebugInfo::GetBreakPointObjects(int source_position) {
     128             :   DCHECK(HasBreakInfo());
     129        4036 :   Object* break_point_info = GetBreakPointInfo(source_position);
     130             :   Isolate* isolate = GetIsolate();
     131        4036 :   if (break_point_info->IsUndefined(isolate)) {
     132           0 :     return isolate->factory()->undefined_value();
     133             :   }
     134             :   return Handle<Object>(
     135        4036 :       BreakPointInfo::cast(break_point_info)->break_point_objects(), isolate);
     136             : }
     137             : 
     138             : // Get the total number of break points.
     139        1326 : int DebugInfo::GetBreakPointCount() {
     140             :   DCHECK(HasBreakInfo());
     141             :   Isolate* isolate = GetIsolate();
     142        1326 :   if (break_points()->IsUndefined(isolate)) return 0;
     143             :   int count = 0;
     144       11934 :   for (int i = 0; i < break_points()->length(); i++) {
     145        5304 :     if (!break_points()->get(i)->IsUndefined(isolate)) {
     146             :       BreakPointInfo* break_point_info =
     147             :           BreakPointInfo::cast(break_points()->get(i));
     148        1994 :       count += break_point_info->GetBreakPointCount();
     149             :     }
     150             :   }
     151             :   return count;
     152             : }
     153             : 
     154        1204 : Handle<Object> DebugInfo::FindBreakPointInfo(
     155             :     Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
     156             :   DCHECK(debug_info->HasBreakInfo());
     157             :   Isolate* isolate = debug_info->GetIsolate();
     158        1204 :   if (!debug_info->break_points()->IsUndefined(isolate)) {
     159        3902 :     for (int i = 0; i < debug_info->break_points()->length(); i++) {
     160        2243 :       if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
     161             :         Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
     162             :             BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
     163        1318 :         if (BreakPointInfo::HasBreakPointObject(break_point_info,
     164             :                                                 break_point_object)) {
     165         894 :           return break_point_info;
     166             :         }
     167             :       }
     168             :     }
     169             :   }
     170         310 :   return isolate->factory()->undefined_value();
     171             : }
     172             : 
     173      232585 : bool DebugInfo::HasCoverageInfo() const {
     174      233366 :   return (flags() & kHasCoverageInfo) != 0;
     175             : }
     176             : 
     177         781 : bool DebugInfo::ClearCoverageInfo() {
     178         781 :   if (HasCoverageInfo()) {
     179             :     Isolate* isolate = GetIsolate();
     180             : 
     181         781 :     set_coverage_info(isolate->heap()->undefined_value());
     182             : 
     183         781 :     int new_flags = flags() & ~kHasCoverageInfo;
     184             :     set_flags(new_flags);
     185             :   }
     186         781 :   return flags() == kNone;
     187             : }
     188             : 
     189             : namespace {
     190        3962 : bool IsEqual(Object* break_point1, Object* break_point2) {
     191             :   // TODO(kozyatinskiy): remove non-BreakPoint logic once the JS debug API has
     192             :   // been removed.
     193        3962 :   if (break_point1->IsBreakPoint() != break_point2->IsBreakPoint())
     194             :     return false;
     195        3962 :   if (!break_point1->IsBreakPoint()) return break_point1 == break_point2;
     196             :   return BreakPoint::cast(break_point1)->id() ==
     197        3162 :          BreakPoint::cast(break_point2)->id();
     198             : }
     199             : }  // namespace
     200             : 
     201             : // Remove the specified break point object.
     202         894 : void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
     203             :                                      Handle<Object> break_point_object) {
     204             :   Isolate* isolate = break_point_info->GetIsolate();
     205             :   // If there are no break points just ignore.
     206         894 :   if (break_point_info->break_point_objects()->IsUndefined(isolate)) return;
     207             :   // If there is a single break point clear it if it is the same.
     208         894 :   if (!break_point_info->break_point_objects()->IsFixedArray()) {
     209         874 :     if (IsEqual(break_point_info->break_point_objects(), *break_point_object)) {
     210             :       break_point_info->set_break_point_objects(
     211        1748 :           isolate->heap()->undefined_value());
     212             :     }
     213             :     return;
     214             :   }
     215             :   // If there are multiple break points shrink the array
     216             :   DCHECK(break_point_info->break_point_objects()->IsFixedArray());
     217             :   Handle<FixedArray> old_array = Handle<FixedArray>(
     218             :       FixedArray::cast(break_point_info->break_point_objects()));
     219             :   Handle<FixedArray> new_array =
     220          20 :       isolate->factory()->NewFixedArray(old_array->length() - 1);
     221             :   int found_count = 0;
     222         110 :   for (int i = 0; i < old_array->length(); i++) {
     223          35 :     if (IsEqual(old_array->get(i), *break_point_object)) {
     224             :       DCHECK_EQ(found_count, 0);
     225          20 :       found_count++;
     226             :     } else {
     227          30 :       new_array->set(i - found_count, old_array->get(i));
     228             :     }
     229             :   }
     230             :   // If the break point was found in the list change it.
     231          40 :   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
     232             : }
     233             : 
     234             : // Add the specified break point object.
     235        2453 : void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
     236             :                                    Handle<Object> break_point_object) {
     237             :   Isolate* isolate = break_point_info->GetIsolate();
     238             : 
     239             :   // If there was no break point objects before just set it.
     240        2453 :   if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
     241        2274 :     break_point_info->set_break_point_objects(*break_point_object);
     242        2274 :     return;
     243             :   }
     244             :   // If the break point object is the same as before just ignore.
     245         179 :   if (break_point_info->break_point_objects() == *break_point_object) return;
     246             :   // If there was one break point object before replace with array.
     247         179 :   if (!break_point_info->break_point_objects()->IsFixedArray()) {
     248          49 :     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
     249          49 :     array->set(0, break_point_info->break_point_objects());
     250          49 :     array->set(1, *break_point_object);
     251          49 :     break_point_info->set_break_point_objects(*array);
     252             :     return;
     253             :   }
     254             :   // If there was more than one break point before extend array.
     255             :   Handle<FixedArray> old_array = Handle<FixedArray>(
     256             :       FixedArray::cast(break_point_info->break_point_objects()));
     257             :   Handle<FixedArray> new_array =
     258         130 :       isolate->factory()->NewFixedArray(old_array->length() + 1);
     259        2230 :   for (int i = 0; i < old_array->length(); i++) {
     260             :     // If the break point was there before just ignore.
     261         985 :     if (IsEqual(old_array->get(i), *break_point_object)) return;
     262         985 :     new_array->set(i, old_array->get(i));
     263             :   }
     264             :   // Add the new break point.
     265         130 :   new_array->set(old_array->length(), *break_point_object);
     266         130 :   break_point_info->set_break_point_objects(*new_array);
     267             : }
     268             : 
     269        2321 : bool BreakPointInfo::HasBreakPointObject(
     270             :     Handle<BreakPointInfo> break_point_info,
     271             :     Handle<Object> break_point_object) {
     272             :   // No break point.
     273             :   Isolate* isolate = break_point_info->GetIsolate();
     274        2321 :   if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
     275             :     return false;
     276             :   }
     277             :   // Single break point.
     278        2058 :   if (!break_point_info->break_point_objects()->IsFixedArray()) {
     279             :     return IsEqual(break_point_info->break_point_objects(),
     280        2018 :                    *break_point_object);
     281             :   }
     282             :   // Multiple break points.
     283             :   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
     284         100 :   for (int i = 0; i < array->length(); i++) {
     285          50 :     if (IsEqual(array->get(i), *break_point_object)) {
     286             :       return true;
     287             :     }
     288             :   }
     289             :   return false;
     290             : }
     291             : 
     292             : // Get the number of break points.
     293       66615 : int BreakPointInfo::GetBreakPointCount() {
     294             :   // No break point.
     295       66615 :   if (break_point_objects()->IsUndefined(GetIsolate())) return 0;
     296             :   // Single break point.
     297       65243 :   if (!break_point_objects()->IsFixedArray()) return 1;
     298             :   // Multiple break points.
     299         591 :   return FixedArray::cast(break_point_objects())->length();
     300             : }
     301             : 
     302       96236 : int CoverageInfo::SlotCount() const {
     303             :   DCHECK_EQ(kFirstSlotIndex, length() % kSlotIndexCount);
     304       96236 :   return (length() - kFirstSlotIndex) / kSlotIndexCount;
     305             : }
     306             : 
     307       38308 : int CoverageInfo::StartSourcePosition(int slot_index) const {
     308             :   DCHECK_LT(slot_index, SlotCount());
     309             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     310       38308 :   return Smi::ToInt(get(slot_start + kSlotStartSourcePositionIndex));
     311             : }
     312             : 
     313       38308 : int CoverageInfo::EndSourcePosition(int slot_index) const {
     314             :   DCHECK_LT(slot_index, SlotCount());
     315             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     316       76616 :   return Smi::ToInt(get(slot_start + kSlotEndSourcePositionIndex));
     317             : }
     318             : 
     319      262953 : int CoverageInfo::BlockCount(int slot_index) const {
     320             :   DCHECK_LT(slot_index, SlotCount());
     321             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     322      525906 :   return Smi::ToInt(get(slot_start + kSlotBlockCountIndex));
     323             : }
     324             : 
     325        3169 : void CoverageInfo::InitializeSlot(int slot_index, int from_pos, int to_pos) {
     326             :   DCHECK_LT(slot_index, SlotCount());
     327             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     328             :   set(slot_start + kSlotStartSourcePositionIndex, Smi::FromInt(from_pos));
     329             :   set(slot_start + kSlotEndSourcePositionIndex, Smi::FromInt(to_pos));
     330             :   set(slot_start + kSlotBlockCountIndex, Smi::kZero);
     331        3169 : }
     332             : 
     333      224645 : void CoverageInfo::IncrementBlockCount(int slot_index) {
     334             :   DCHECK_LT(slot_index, SlotCount());
     335             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     336      224645 :   const int old_count = BlockCount(slot_index);
     337      224645 :   set(slot_start + kSlotBlockCountIndex, Smi::FromInt(old_count + 1));
     338      224645 : }
     339             : 
     340       38308 : void CoverageInfo::ResetBlockCount(int slot_index) {
     341             :   DCHECK_LT(slot_index, SlotCount());
     342             :   const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
     343             :   set(slot_start + kSlotBlockCountIndex, Smi::kZero);
     344       38308 : }
     345             : 
     346           0 : void CoverageInfo::Print(String* function_name) {
     347             :   DCHECK(FLAG_trace_block_coverage);
     348             :   DisallowHeapAllocation no_gc;
     349             : 
     350           0 :   OFStream os(stdout);
     351           0 :   os << "Coverage info (";
     352           0 :   if (function_name->length() > 0) {
     353           0 :     auto function_name_cstr = function_name->ToCString();
     354           0 :     os << function_name_cstr.get();
     355             :   } else {
     356           0 :     os << "{anonymous}";
     357             :   }
     358           0 :   os << "):" << std::endl;
     359             : 
     360           0 :   for (int i = 0; i < SlotCount(); i++) {
     361           0 :     os << "{" << StartSourcePosition(i) << "," << EndSourcePosition(i) << "}"
     362             :        << std::endl;
     363           0 :   }
     364           0 : }
     365             : 
     366             : }  // namespace internal
     367             : }  // namespace v8

Generated by: LCOV version 1.10