LCOV - code coverage report
Current view: top level - src - source-position-table.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 61 61 100.0 %
Date: 2017-04-26 Functions: 10 10 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/log.h"
       8             : #include "src/objects-inl.h"
       9             : #include "src/objects.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14             : // We'll use a simple encoding scheme to record the source positions.
      15             : // Conceptually, each position consists of:
      16             : // - code_offset: An integer index into the BytecodeArray or code.
      17             : // - source_position: An integer index into the source string.
      18             : // - position type: Each position is either a statement or an expression.
      19             : //
      20             : // The basic idea for the encoding is to use a variable-length integer coding,
      21             : // where each byte contains 7 bits of payload data, and 1 'more' bit that
      22             : // determines whether additional bytes follow. Additionally:
      23             : // - we record the difference from the previous position,
      24             : // - we just stuff one bit for the type into the code offset,
      25             : // - we write least-significant bits first,
      26             : // - we use zig-zag encoding to encode both positive and negative numbers.
      27             : 
      28             : namespace {
      29             : 
      30             : // Each byte is encoded as MoreBit | ValueBits.
      31             : class MoreBit : public BitField8<bool, 7, 1> {};
      32             : class ValueBits : public BitField8<unsigned, 0, 7> {};
      33             : 
      34             : // Helper: Add the offsets from 'other' to 'value'. Also set is_statement.
      35             : void AddAndSetEntry(PositionTableEntry& value,
      36             :                     const PositionTableEntry& other) {
      37   219655669 :   value.code_offset += other.code_offset;
      38   219655669 :   value.source_position += other.source_position;
      39   219655669 :   value.is_statement = other.is_statement;
      40             : }
      41             : 
      42             : // Helper: Substract the offsets from 'other' from 'value'.
      43             : void SubtractFromEntry(PositionTableEntry& value,
      44             :                        const PositionTableEntry& other) {
      45    53139435 :   value.code_offset -= other.code_offset;
      46    53139435 :   value.source_position -= other.source_position;
      47             : }
      48             : 
      49             : // Helper: Encode an integer.
      50             : template <typename T>
      51   106278878 : void EncodeInt(ZoneVector<byte>& bytes, T value) {
      52             :   // Zig-zag encoding.
      53             :   static const int kShift = sizeof(T) * kBitsPerByte - 1;
      54   106278878 :   value = ((value << 1) ^ (value >> kShift));
      55             :   DCHECK_GE(value, 0);
      56   106278878 :   auto encoded = static_cast<typename std::make_unsigned<T>::type>(value);
      57             :   bool more;
      58   115416591 :   do {
      59   115416584 :     more = encoded > ValueBits::kMax;
      60             :     byte current =
      61   230833168 :         MoreBit::encode(more) | ValueBits::encode(encoded & ValueBits::kMask);
      62   115416584 :     bytes.push_back(current);
      63   115416591 :     encoded >>= ValueBits::kSize;
      64             :   } while (more);
      65   106278885 : }
      66             : 
      67             : // Encode a PositionTableEntry.
      68    53139464 : void EncodeEntry(ZoneVector<byte>& bytes, const PositionTableEntry& entry) {
      69             :   // We only accept ascending code offsets.
      70             :   DCHECK(entry.code_offset >= 0);
      71             :   // Since code_offset is not negative, we use sign to encode is_statement.
      72             :   EncodeInt(bytes,
      73    53139464 :             entry.is_statement ? entry.code_offset : -entry.code_offset - 1);
      74    53139452 :   EncodeInt(bytes, entry.source_position);
      75    53139428 : }
      76             : 
      77             : // Helper: Decode an integer.
      78             : template <typename T>
      79             : T DecodeInt(ByteArray* bytes, int* index) {
      80             :   byte current;
      81             :   int shift = 0;
      82             :   T decoded = 0;
      83             :   bool more;
      84   449063557 :   do {
      85   449063557 :     current = bytes->get((*index)++);
      86   449063557 :     decoded |= static_cast<typename std::make_unsigned<T>::type>(
      87             :                    ValueBits::decode(current))
      88             :                << shift;
      89             :     more = MoreBit::decode(current);
      90   449063557 :     shift += ValueBits::kSize;
      91             :   } while (more);
      92             :   DCHECK_GE(decoded, 0);
      93   439311342 :   decoded = (decoded >> 1) ^ (-(decoded & 1));
      94             :   return decoded;
      95             : }
      96             : 
      97   219655671 : void DecodeEntry(ByteArray* bytes, int* index, PositionTableEntry* entry) {
      98             :   int tmp = DecodeInt<int>(bytes, index);
      99   219655671 :   if (tmp >= 0) {
     100    92516975 :     entry->is_statement = true;
     101    92516975 :     entry->code_offset = tmp;
     102             :   } else {
     103   127138696 :     entry->is_statement = false;
     104   127138696 :     entry->code_offset = -(tmp + 1);
     105             :   }
     106   219655671 :   entry->source_position = DecodeInt<int64_t>(bytes, index);
     107   219655671 : }
     108             : 
     109             : }  // namespace
     110             : 
     111     4378297 : SourcePositionTableBuilder::SourcePositionTableBuilder(
     112             :     Zone* zone, SourcePositionTableBuilder::RecordingMode mode)
     113             :     : mode_(mode),
     114             :       bytes_(zone),
     115             : #ifdef ENABLE_SLOW_DCHECKS
     116             :       raw_entries_(zone),
     117             : #endif
     118     4378297 :       previous_() {
     119     4378297 : }
     120             : 
     121    71170833 : void SourcePositionTableBuilder::AddPosition(size_t code_offset,
     122             :                                              SourcePosition source_position,
     123    71170833 :                                              bool is_statement) {
     124   142341666 :   if (Omit()) return;
     125             :   DCHECK(source_position.IsKnown());
     126    53139427 :   int offset = static_cast<int>(code_offset);
     127    53139427 :   AddEntry({offset, source_position.raw(), is_statement});
     128             : }
     129             : 
     130    53139435 : void SourcePositionTableBuilder::AddEntry(const PositionTableEntry& entry) {
     131    53139435 :   PositionTableEntry tmp(entry);
     132    53139435 :   SubtractFromEntry(tmp, previous_);
     133    53139435 :   EncodeEntry(bytes_, tmp);
     134    53139430 :   previous_ = entry;
     135             : #ifdef ENABLE_SLOW_DCHECKS
     136             :   raw_entries_.push_back(entry);
     137             : #endif
     138    53139430 : }
     139             : 
     140     4377176 : Handle<ByteArray> SourcePositionTableBuilder::ToSourcePositionTable(
     141     3261467 :     Isolate* isolate, Handle<AbstractCode> code) {
     142     7638643 :   if (bytes_.empty()) return isolate->factory()->empty_byte_array();
     143             :   DCHECK(!Omit());
     144             : 
     145             :   Handle<ByteArray> table = isolate->factory()->NewByteArray(
     146     3261463 :       static_cast<int>(bytes_.size()), TENURED);
     147             : 
     148     3261467 :   MemCopy(table->GetDataStartAddress(), &*bytes_.begin(), bytes_.size());
     149             : 
     150     3261816 :   LOG_CODE_EVENT(isolate, CodeLinePosInfoRecordEvent(*code, *table));
     151             : 
     152             : #ifdef ENABLE_SLOW_DCHECKS
     153             :   // Brute force testing: Record all positions and decode
     154             :   // the entire table to verify they are identical.
     155             :   auto raw = raw_entries_.begin();
     156             :   for (SourcePositionTableIterator encoded(*table); !encoded.done();
     157             :        encoded.Advance(), raw++) {
     158             :     DCHECK(raw != raw_entries_.end());
     159             :     DCHECK_EQ(encoded.code_offset(), raw->code_offset);
     160             :     DCHECK_EQ(encoded.source_position().raw(), raw->source_position);
     161             :     DCHECK_EQ(encoded.is_statement(), raw->is_statement);
     162             :   }
     163             :   DCHECK(raw == raw_entries_.end());
     164             :   // No additional source positions after creating the table.
     165             :   mode_ = OMIT_SOURCE_POSITIONS;
     166             : #endif
     167     3261463 :   return table;
     168             : }
     169             : 
     170     5215074 : SourcePositionTableIterator::SourcePositionTableIterator(ByteArray* byte_array)
     171     5215074 :     : table_(byte_array), index_(0), current_() {
     172     5215074 :   Advance();
     173     5215073 : }
     174             : 
     175   221982629 : void SourcePositionTableIterator::Advance() {
     176             :   DCHECK(!done());
     177             :   DCHECK(index_ >= 0 && index_ <= table_->length());
     178   443965258 :   if (index_ >= table_->length()) {
     179     2326956 :     index_ = kDone;
     180             :   } else {
     181             :     PositionTableEntry tmp;
     182   219655673 :     DecodeEntry(table_, &index_, &tmp);
     183             :     AddAndSetEntry(current_, tmp);
     184             :   }
     185   221982625 : }
     186             : 
     187             : }  // namespace internal
     188             : }  // namespace v8

Generated by: LCOV version 1.10