LCOV - code coverage report
Current view: top level - src - source-position-table.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 64 64 100.0 %
Date: 2017-10-20 Functions: 11 11 100.0 %

          Line data    Source code
       1             : // Copyright 2016 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/source-position-table.h"
       6             : 
       7             : #include "src/objects-inl.h"
       8             : #include "src/objects.h"
       9             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : 
      13             : // We'll use a simple encoding scheme to record the source positions.
      14             : // Conceptually, each position consists of:
      15             : // - code_offset: An integer index into the BytecodeArray or code.
      16             : // - source_position: An integer index into the source string.
      17             : // - position type: Each position is either a statement or an expression.
      18             : //
      19             : // The basic idea for the encoding is to use a variable-length integer coding,
      20             : // where each byte contains 7 bits of payload data, and 1 'more' bit that
      21             : // determines whether additional bytes follow. Additionally:
      22             : // - we record the difference from the previous position,
      23             : // - we just stuff one bit for the type into the code offset,
      24             : // - we write least-significant bits first,
      25             : // - we use zig-zag encoding to encode both positive and negative numbers.
      26             : 
      27             : namespace {
      28             : 
      29             : // Each byte is encoded as MoreBit | ValueBits.
      30             : class MoreBit : public BitField8<bool, 7, 1> {};
      31             : class ValueBits : public BitField8<unsigned, 0, 7> {};
      32             : 
      33             : // Helper: Add the offsets from 'other' to 'value'. Also set is_statement.
      34             : void AddAndSetEntry(PositionTableEntry& value,
      35             :                     const PositionTableEntry& other) {
      36    97630228 :   value.code_offset += other.code_offset;
      37    97630228 :   value.source_position += other.source_position;
      38    97630228 :   value.is_statement = other.is_statement;
      39             : }
      40             : 
      41             : // Helper: Subtract the offsets from 'other' from 'value'.
      42             : void SubtractFromEntry(PositionTableEntry& value,
      43             :                        const PositionTableEntry& other) {
      44    23946159 :   value.code_offset -= other.code_offset;
      45    23946159 :   value.source_position -= other.source_position;
      46             : }
      47             : 
      48             : // Helper: Encode an integer.
      49             : template <typename T>
      50    47892371 : void EncodeInt(ZoneVector<byte>& bytes, T value) {
      51             :   // Zig-zag encoding.
      52             :   static const int kShift = sizeof(T) * kBitsPerByte - 1;
      53    47892371 :   value = ((value << 1) ^ (value >> kShift));
      54             :   DCHECK_GE(value, 0);
      55    47892371 :   auto encoded = static_cast<typename std::make_unsigned<T>::type>(value);
      56             :   bool more;
      57    52427440 :   do {
      58    52427336 :     more = encoded > ValueBits::kMax;
      59             :     byte current =
      60   104854672 :         MoreBit::encode(more) | ValueBits::encode(encoded & ValueBits::kMask);
      61    52427336 :     bytes.push_back(current);
      62    52427440 :     encoded >>= ValueBits::kSize;
      63             :   } while (more);
      64    47892475 : }
      65             : 
      66             : // Encode a PositionTableEntry.
      67    23946166 : void EncodeEntry(ZoneVector<byte>& bytes, const PositionTableEntry& entry) {
      68             :   // We only accept ascending code offsets.
      69             :   DCHECK_GE(entry.code_offset, 0);
      70             :   // Since code_offset is not negative, we use sign to encode is_statement.
      71             :   EncodeInt(bytes,
      72    23946166 :             entry.is_statement ? entry.code_offset : -entry.code_offset - 1);
      73    23946207 :   EncodeInt(bytes, entry.source_position);
      74    23946249 : }
      75             : 
      76             : // Helper: Decode an integer.
      77             : template <typename T>
      78             : T DecodeInt(ByteArray* bytes, int* index) {
      79             :   byte current;
      80             :   int shift = 0;
      81             :   T decoded = 0;
      82             :   bool more;
      83   200688864 :   do {
      84   200688864 :     current = bytes->get((*index)++);
      85   200688864 :     decoded |= static_cast<typename std::make_unsigned<T>::type>(
      86             :                    ValueBits::decode(current))
      87             :                << shift;
      88             :     more = MoreBit::decode(current);
      89   200688864 :     shift += ValueBits::kSize;
      90             :   } while (more);
      91             :   DCHECK_GE(decoded, 0);
      92   195260458 :   decoded = (decoded >> 1) ^ (-(decoded & 1));
      93             :   return decoded;
      94             : }
      95             : 
      96    97630229 : void DecodeEntry(ByteArray* bytes, int* index, PositionTableEntry* entry) {
      97             :   int tmp = DecodeInt<int>(bytes, index);
      98    97630229 :   if (tmp >= 0) {
      99    55252458 :     entry->is_statement = true;
     100    55252458 :     entry->code_offset = tmp;
     101             :   } else {
     102    42377771 :     entry->is_statement = false;
     103    42377771 :     entry->code_offset = -(tmp + 1);
     104             :   }
     105    97630229 :   entry->source_position = DecodeInt<int64_t>(bytes, index);
     106    97630229 : }
     107             : 
     108             : }  // namespace
     109             : 
     110     3457308 : SourcePositionTableBuilder::SourcePositionTableBuilder(
     111             :     Zone* zone, SourcePositionTableBuilder::RecordingMode mode)
     112             :     : mode_(mode),
     113             :       bytes_(zone),
     114             : #ifdef ENABLE_SLOW_DCHECKS
     115             :       raw_entries_(zone),
     116             : #endif
     117     3457308 :       previous_() {
     118     3457308 : }
     119             : 
     120    30046578 : void SourcePositionTableBuilder::AddPosition(size_t code_offset,
     121             :                                              SourcePosition source_position,
     122    30046578 :                                              bool is_statement) {
     123    60093218 :   if (Omit()) return;
     124             :   DCHECK(source_position.IsKnown());
     125    23946214 :   int offset = static_cast<int>(code_offset);
     126    23946214 :   AddEntry({offset, source_position.raw(), is_statement});
     127             : }
     128             : 
     129    23946159 : void SourcePositionTableBuilder::AddEntry(const PositionTableEntry& entry) {
     130    23946159 :   PositionTableEntry tmp(entry);
     131    23946159 :   SubtractFromEntry(tmp, previous_);
     132    23946159 :   EncodeEntry(bytes_, tmp);
     133    23946280 :   previous_ = entry;
     134             : #ifdef ENABLE_SLOW_DCHECKS
     135             :   raw_entries_.push_back(entry);
     136             : #endif
     137    23946280 : }
     138             : 
     139     3455394 : Handle<ByteArray> SourcePositionTableBuilder::ToSourcePositionTable(
     140             :     Isolate* isolate) {
     141     6076829 :   if (bytes_.empty()) return isolate->factory()->empty_byte_array();
     142             :   DCHECK(!Omit());
     143             : 
     144             :   Handle<ByteArray> table = isolate->factory()->NewByteArray(
     145     2621434 :       static_cast<int>(bytes_.size()), TENURED);
     146             : 
     147     2621435 :   MemCopy(table->GetDataStartAddress(), &*bytes_.begin(), bytes_.size());
     148             : 
     149             : #ifdef ENABLE_SLOW_DCHECKS
     150             :   // Brute force testing: Record all positions and decode
     151             :   // the entire table to verify they are identical.
     152             :   auto raw = raw_entries_.begin();
     153             :   for (SourcePositionTableIterator encoded(*table); !encoded.done();
     154             :        encoded.Advance(), raw++) {
     155             :     DCHECK(raw != raw_entries_.end());
     156             :     DCHECK_EQ(encoded.code_offset(), raw->code_offset);
     157             :     DCHECK_EQ(encoded.source_position().raw(), raw->source_position);
     158             :     DCHECK_EQ(encoded.is_statement(), raw->is_statement);
     159             :   }
     160             :   DCHECK(raw == raw_entries_.end());
     161             :   // No additional source positions after creating the table.
     162             :   mode_ = OMIT_SOURCE_POSITIONS;
     163             : #endif
     164     2621435 :   return table;
     165             : }
     166             : 
     167     3295463 : SourcePositionTableIterator::SourcePositionTableIterator(ByteArray* byte_array)
     168     6590926 :     : raw_table_(byte_array) {
     169     3295463 :   Advance();
     170     3295463 : }
     171             : 
     172      504910 : SourcePositionTableIterator::SourcePositionTableIterator(
     173             :     Handle<ByteArray> byte_array)
     174      504910 :     : table_(byte_array) {
     175      504910 :   Advance();
     176             :   // We can enable allocation because we keep the table in a handle.
     177             :   no_gc.Release();
     178      504909 : }
     179             : 
     180    99325325 : void SourcePositionTableIterator::Advance() {
     181    99325325 :   ByteArray* table = raw_table_ ? raw_table_ : *table_;
     182             :   DCHECK(!done());
     183             :   DCHECK(index_ >= 0 && index_ <= table->length());
     184   198650650 :   if (index_ >= table->length()) {
     185     1695096 :     index_ = kDone;
     186             :   } else {
     187             :     PositionTableEntry tmp;
     188    97630229 :     DecodeEntry(table, &index_, &tmp);
     189             :     AddAndSetEntry(current_, tmp);
     190             :   }
     191    99325324 : }
     192             : 
     193             : }  // namespace internal
     194             : }  // namespace v8

Generated by: LCOV version 1.10