LCOV - code coverage report
Current view: top level - src - handler-table.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 76 83 91.6 %
Date: 2019-04-17 Functions: 19 23 82.6 %

          Line data    Source code
       1             : // Copyright 2018 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/handler-table.h"
       6             : 
       7             : #include <iomanip>
       8             : 
       9             : #include "src/assembler-inl.h"
      10             : #include "src/objects-inl.h"
      11             : #include "src/objects/code-inl.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : 
      16     3544013 : HandlerTable::HandlerTable(Code code)
      17     3544013 :     : HandlerTable(code->InstructionStart(), code->has_handler_table()
      18             :                                                  ? code->handler_table_offset()
      19     7689188 :                                                  : 0) {}
      20             : 
      21    36225796 : HandlerTable::HandlerTable(BytecodeArray bytecode_array)
      22    36225796 :     : HandlerTable(bytecode_array->handler_table()) {}
      23             : 
      24     2111459 : HandlerTable::HandlerTable(ByteArray byte_array)
      25    38337255 :     : number_of_entries_(byte_array->length() / kRangeEntrySize /
      26             :                          sizeof(int32_t)),
      27             : #ifdef DEBUG
      28             :       mode_(kRangeBasedEncoding),
      29             : #endif
      30             :       raw_encoded_data_(
      31    76674510 :           reinterpret_cast<Address>(byte_array->GetDataStartAddress())) {
      32     2111459 : }
      33             : 
      34             : // TODO(jgruber,v8:8758): This constructor should eventually take the handler
      35             : // table size in addition to the offset. That way the {HandlerTable} class
      36             : // remains independent of how the offset/size is encoded in the various code
      37             : // objects. This could even allow us to change the encoding to no longer expect
      38             : // the "number of entries" in the beginning.
      39         792 : HandlerTable::HandlerTable(Address instruction_start,
      40             :                            size_t handler_table_offset)
      41             :     : number_of_entries_(0),
      42             : #ifdef DEBUG
      43             :       mode_(kReturnAddressBasedEncoding),
      44             : #endif
      45     3544805 :       raw_encoded_data_(instruction_start + handler_table_offset) {
      46     3544805 :   if (handler_table_offset > 0) {
      47      601954 :     number_of_entries_ = Memory<int32_t>(raw_encoded_data_);
      48      601954 :     raw_encoded_data_ += sizeof(int32_t);
      49             :   }
      50         792 : }
      51             : 
      52     1421800 : int HandlerTable::GetRangeStart(int index) const {
      53             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
      54             :   DCHECK_LT(index, NumberOfRangeEntries());
      55    11499527 :   int offset = index * kRangeEntrySize + kRangeStartIndex;
      56    22999054 :   return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
      57             : }
      58             : 
      59       30485 : int HandlerTable::GetRangeEnd(int index) const {
      60             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
      61             :   DCHECK_LT(index, NumberOfRangeEntries());
      62    10108212 :   int offset = index * kRangeEntrySize + kRangeEndIndex;
      63    20216424 :   return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
      64             : }
      65             : 
      66       30485 : int HandlerTable::GetRangeHandler(int index) const {
      67             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
      68             :   DCHECK_LT(index, NumberOfRangeEntries());
      69    10108212 :   int offset = index * kRangeEntrySize + kRangeHandlerIndex;
      70    10108212 :   return HandlerOffsetField::decode(
      71    20246909 :       Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
      72             : }
      73             : 
      74       30150 : int HandlerTable::GetRangeData(int index) const {
      75             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
      76             :   DCHECK_LT(index, NumberOfRangeEntries());
      77    10107877 :   int offset = index * kRangeEntrySize + kRangeDataIndex;
      78    20215754 :   return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
      79             : }
      80             : 
      81           0 : HandlerTable::CatchPrediction HandlerTable::GetRangePrediction(
      82             :     int index) const {
      83             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
      84             :   DCHECK_LT(index, NumberOfRangeEntries());
      85           0 :   int offset = index * kRangeEntrySize + kRangeHandlerIndex;
      86           0 :   return HandlerPredictionField::decode(
      87           0 :       Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
      88             : }
      89             : 
      90           0 : int HandlerTable::GetReturnOffset(int index) const {
      91             :   DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
      92             :   DCHECK_LT(index, NumberOfReturnEntries());
      93     1410196 :   int offset = index * kReturnEntrySize + kReturnOffsetIndex;
      94     2820392 :   return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
      95             : }
      96             : 
      97           0 : int HandlerTable::GetReturnHandler(int index) const {
      98             :   DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
      99             :   DCHECK_LT(index, NumberOfReturnEntries());
     100      499009 :   int offset = index * kReturnEntrySize + kReturnHandlerIndex;
     101      499009 :   return HandlerOffsetField::decode(
     102      998018 :       Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
     103             : }
     104             : 
     105      146802 : void HandlerTable::SetRangeStart(int index, int value) {
     106      146802 :   int offset = index * kRangeEntrySize + kRangeStartIndex;
     107      293604 :   Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
     108      146802 : }
     109             : 
     110      146807 : void HandlerTable::SetRangeEnd(int index, int value) {
     111      146807 :   int offset = index * kRangeEntrySize + kRangeEndIndex;
     112      293614 :   Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
     113      146807 : }
     114             : 
     115      146804 : void HandlerTable::SetRangeHandler(int index, int handler_offset,
     116             :                                    CatchPrediction prediction) {
     117      146804 :   int value = HandlerOffsetField::encode(handler_offset) |
     118      146804 :               HandlerPredictionField::encode(prediction);
     119      146804 :   int offset = index * kRangeEntrySize + kRangeHandlerIndex;
     120      293608 :   Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
     121      146804 : }
     122             : 
     123      146806 : void HandlerTable::SetRangeData(int index, int value) {
     124      146806 :   int offset = index * kRangeEntrySize + kRangeDataIndex;
     125      293612 :   Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
     126      146806 : }
     127             : 
     128             : // static
     129     2111467 : int HandlerTable::LengthForRange(int entries) {
     130     2111467 :   return entries * kRangeEntrySize * sizeof(int32_t);
     131             : }
     132             : 
     133             : // static
     134       20521 : int HandlerTable::EmitReturnTableStart(Assembler* masm, int entries) {
     135       20521 :   masm->DataAlign(sizeof(int32_t));  // Make sure entries are aligned.
     136       20522 :   masm->RecordComment(";;; Exception handler table.");
     137             :   int table_start = masm->pc_offset();
     138       20522 :   masm->dd(entries);
     139       20522 :   return table_start;
     140             : }
     141             : 
     142             : // static
     143      226727 : void HandlerTable::EmitReturnEntry(Assembler* masm, int offset, int handler) {
     144      226727 :   masm->dd(offset);
     145      226727 :   masm->dd(HandlerOffsetField::encode(handler));
     146      226727 : }
     147             : 
     148    15174030 : int HandlerTable::NumberOfRangeEntries() const {
     149             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
     150    46303589 :   return number_of_entries_;
     151             : }
     152             : 
     153           0 : int HandlerTable::NumberOfReturnEntries() const {
     154             :   DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
     155     4455992 :   return number_of_entries_;
     156             : }
     157             : 
     158    21051832 : int HandlerTable::LookupRange(int pc_offset, int* data_out,
     159             :                               CatchPrediction* prediction_out) {
     160             :   int innermost_handler = -1;
     161             : #ifdef DEBUG
     162             :   // Assuming that ranges are well nested, we don't need to track the innermost
     163             :   // offsets. This is just to verify that the table is actually well nested.
     164             :   int innermost_start = std::numeric_limits<int>::min();
     165             :   int innermost_end = std::numeric_limits<int>::max();
     166             : #endif
     167    41207286 :   for (int i = 0; i < NumberOfRangeEntries(); ++i) {
     168             :     int start_offset = GetRangeStart(i);
     169             :     int end_offset = GetRangeEnd(i);
     170             :     int handler_offset = GetRangeHandler(i);
     171             :     int handler_data = GetRangeData(i);
     172             :     CatchPrediction prediction = GetRangePrediction(i);
     173    10077727 :     if (pc_offset >= start_offset && pc_offset < end_offset) {
     174             :       DCHECK_GE(start_offset, innermost_start);
     175             :       DCHECK_LT(end_offset, innermost_end);
     176             :       innermost_handler = handler_offset;
     177             : #ifdef DEBUG
     178             :       innermost_start = start_offset;
     179             :       innermost_end = end_offset;
     180             : #endif
     181     1441533 :       if (data_out) *data_out = handler_data;
     182     1441533 :       if (prediction_out) *prediction_out = prediction;
     183             :     }
     184             :   }
     185    21051832 :   return innermost_handler;
     186             : }
     187             : 
     188             : // TODO(turbofan): Make sure table is sorted and use binary search.
     189     3544805 : int HandlerTable::LookupReturn(int pc_offset) {
     190     5367179 :   for (int i = 0; i < NumberOfReturnEntries(); ++i) {
     191             :     int return_offset = GetReturnOffset(i);
     192     1410196 :     if (pc_offset == return_offset) {
     193      499009 :       return GetReturnHandler(i);
     194             :     }
     195             :   }
     196             :   return -1;
     197             : }
     198             : 
     199             : #ifdef ENABLE_DISASSEMBLER
     200             : 
     201             : void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
     202             :   os << "   from   to       hdlr (prediction,   data)\n";
     203             :   for (int i = 0; i < NumberOfRangeEntries(); ++i) {
     204             :     int pc_start = GetRangeStart(i);
     205             :     int pc_end = GetRangeEnd(i);
     206             :     int handler_offset = GetRangeHandler(i);
     207             :     int handler_data = GetRangeData(i);
     208             :     CatchPrediction prediction = GetRangePrediction(i);
     209             :     os << "  (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
     210             :        << ")  ->  " << std::setw(4) << handler_offset
     211             :        << " (prediction=" << prediction << ", data=" << handler_data << ")\n";
     212             :   }
     213             : }
     214             : 
     215             : void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
     216             :   os << "  offset   handler\n";
     217             :   for (int i = 0; i < NumberOfReturnEntries(); ++i) {
     218             :     int pc_offset = GetReturnOffset(i);
     219             :     int handler_offset = GetReturnHandler(i);
     220             :     os << std::hex << "    " << std::setw(4) << pc_offset << "  ->  "
     221             :        << std::setw(4) << handler_offset << std::dec << "\n";
     222             :   }
     223             : }
     224             : 
     225             : #endif  // ENABLE_DISASSEMBLER
     226             : 
     227             : }  // namespace internal
     228      121996 : }  // namespace v8

Generated by: LCOV version 1.10