LCOV - code coverage report
Current view: top level - src - handler-table.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 72 79 91.1 %
Date: 2019-04-19 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     3533693 : HandlerTable::HandlerTable(Code code)
      17             :     : HandlerTable(code->InstructionStart() + code->handler_table_offset(),
      18    10601079 :                    code->handler_table_size()) {}
      19             : 
      20    36244281 : HandlerTable::HandlerTable(BytecodeArray bytecode_array)
      21    36244281 :     : HandlerTable(bytecode_array->handler_table()) {}
      22             : 
      23     2112569 : HandlerTable::HandlerTable(ByteArray byte_array)
      24    38356850 :     : number_of_entries_(byte_array->length() / kRangeEntrySize /
      25             :                          sizeof(int32_t)),
      26             : #ifdef DEBUG
      27             :       mode_(kRangeBasedEncoding),
      28             : #endif
      29             :       raw_encoded_data_(
      30    76713700 :           reinterpret_cast<Address>(byte_array->GetDataStartAddress())) {
      31             :   DCHECK_EQ(0, byte_array->length() % (kRangeEntrySize * sizeof(int32_t)));
      32     2112569 : }
      33             : 
      34         792 : HandlerTable::HandlerTable(Address handler_table, int handler_table_size)
      35     3534485 :     : number_of_entries_(handler_table_size / kReturnEntrySize /
      36             :                          sizeof(int32_t)),
      37             : #ifdef DEBUG
      38             :       mode_(kReturnAddressBasedEncoding),
      39             : #endif
      40     3534485 :       raw_encoded_data_(handler_table) {
      41             :   DCHECK_EQ(0, handler_table_size % (kReturnEntrySize * sizeof(int32_t)));
      42         792 : }
      43             : 
      44     1423695 : int HandlerTable::GetRangeStart(int index) const {
      45             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
      46             :   DCHECK_LT(index, NumberOfRangeEntries());
      47    11501925 :   int offset = index * kRangeEntrySize + kRangeStartIndex;
      48    23003850 :   return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
      49             : }
      50             : 
      51       30531 : int HandlerTable::GetRangeEnd(int index) const {
      52             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
      53             :   DCHECK_LT(index, NumberOfRangeEntries());
      54    10108761 :   int offset = index * kRangeEntrySize + kRangeEndIndex;
      55    20217522 :   return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
      56             : }
      57             : 
      58       30531 : int HandlerTable::GetRangeHandler(int index) const {
      59             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
      60             :   DCHECK_LT(index, NumberOfRangeEntries());
      61    10108761 :   int offset = index * kRangeEntrySize + kRangeHandlerIndex;
      62    10108761 :   return HandlerOffsetField::decode(
      63    20248053 :       Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
      64             : }
      65             : 
      66       30196 : int HandlerTable::GetRangeData(int index) const {
      67             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
      68             :   DCHECK_LT(index, NumberOfRangeEntries());
      69    10108426 :   int offset = index * kRangeEntrySize + kRangeDataIndex;
      70    20216852 :   return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
      71             : }
      72             : 
      73           0 : HandlerTable::CatchPrediction HandlerTable::GetRangePrediction(
      74             :     int index) const {
      75             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
      76             :   DCHECK_LT(index, NumberOfRangeEntries());
      77           0 :   int offset = index * kRangeEntrySize + kRangeHandlerIndex;
      78           0 :   return HandlerPredictionField::decode(
      79           0 :       Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
      80             : }
      81             : 
      82           0 : int HandlerTable::GetReturnOffset(int index) const {
      83             :   DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
      84             :   DCHECK_LT(index, NumberOfReturnEntries());
      85     1422402 :   int offset = index * kReturnEntrySize + kReturnOffsetIndex;
      86     2844804 :   return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
      87             : }
      88             : 
      89           0 : int HandlerTable::GetReturnHandler(int index) const {
      90             :   DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
      91             :   DCHECK_LT(index, NumberOfReturnEntries());
      92      498494 :   int offset = index * kReturnEntrySize + kReturnHandlerIndex;
      93      498494 :   return HandlerOffsetField::decode(
      94      996988 :       Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
      95             : }
      96             : 
      97      147038 : void HandlerTable::SetRangeStart(int index, int value) {
      98      147038 :   int offset = index * kRangeEntrySize + kRangeStartIndex;
      99      294076 :   Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
     100      147038 : }
     101             : 
     102      147038 : void HandlerTable::SetRangeEnd(int index, int value) {
     103      147038 :   int offset = index * kRangeEntrySize + kRangeEndIndex;
     104      294076 :   Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
     105      147038 : }
     106             : 
     107      147040 : void HandlerTable::SetRangeHandler(int index, int handler_offset,
     108             :                                    CatchPrediction prediction) {
     109      147040 :   int value = HandlerOffsetField::encode(handler_offset) |
     110      147040 :               HandlerPredictionField::encode(prediction);
     111      147040 :   int offset = index * kRangeEntrySize + kRangeHandlerIndex;
     112      294080 :   Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
     113      147040 : }
     114             : 
     115      147038 : void HandlerTable::SetRangeData(int index, int value) {
     116      147038 :   int offset = index * kRangeEntrySize + kRangeDataIndex;
     117      294076 :   Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
     118      147038 : }
     119             : 
     120             : // static
     121     2112568 : int HandlerTable::LengthForRange(int entries) {
     122     2112568 :   return entries * kRangeEntrySize * sizeof(int32_t);
     123             : }
     124             : 
     125             : // static
     126       20540 : int HandlerTable::EmitReturnTableStart(Assembler* masm) {
     127       20540 :   masm->DataAlign(sizeof(int32_t));  // Make sure entries are aligned.
     128       20540 :   masm->RecordComment(";;; Exception handler table.");
     129             :   int table_start = masm->pc_offset();
     130       20541 :   return table_start;
     131             : }
     132             : 
     133             : // static
     134      227171 : void HandlerTable::EmitReturnEntry(Assembler* masm, int offset, int handler) {
     135      227171 :   masm->dd(offset);
     136      227171 :   masm->dd(HandlerOffsetField::encode(handler));
     137      227171 : }
     138             : 
     139    15186394 : int HandlerTable::NumberOfRangeEntries() const {
     140             :   DCHECK_EQ(kRangeBasedEncoding, mode_);
     141    46322549 :   return number_of_entries_;
     142             : }
     143             : 
     144           0 : int HandlerTable::NumberOfReturnEntries() const {
     145             :   DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
     146     4458393 :   return number_of_entries_;
     147             : }
     148             : 
     149    21057925 : int HandlerTable::LookupRange(int pc_offset, int* data_out,
     150             :                               CatchPrediction* prediction_out) {
     151             :   int innermost_handler = -1;
     152             : #ifdef DEBUG
     153             :   // Assuming that ranges are well nested, we don't need to track the innermost
     154             :   // offsets. This is just to verify that the table is actually well nested.
     155             :   int innermost_start = std::numeric_limits<int>::min();
     156             :   int innermost_end = std::numeric_limits<int>::max();
     157             : #endif
     158    41214385 :   for (int i = 0; i < NumberOfRangeEntries(); ++i) {
     159             :     int start_offset = GetRangeStart(i);
     160             :     int end_offset = GetRangeEnd(i);
     161             :     int handler_offset = GetRangeHandler(i);
     162             :     int handler_data = GetRangeData(i);
     163             :     CatchPrediction prediction = GetRangePrediction(i);
     164    10078230 :     if (pc_offset >= start_offset && pc_offset < end_offset) {
     165             :       DCHECK_GE(start_offset, innermost_start);
     166             :       DCHECK_LT(end_offset, innermost_end);
     167             :       innermost_handler = handler_offset;
     168             : #ifdef DEBUG
     169             :       innermost_start = start_offset;
     170             :       innermost_end = end_offset;
     171             : #endif
     172     1441335 :       if (data_out) *data_out = handler_data;
     173     1441335 :       if (prediction_out) *prediction_out = prediction;
     174             :     }
     175             :   }
     176    21057925 :   return innermost_handler;
     177             : }
     178             : 
     179             : // TODO(turbofan): Make sure table is sorted and use binary search.
     180     3534485 : int HandlerTable::LookupReturn(int pc_offset) {
     181     5382301 :   for (int i = 0; i < NumberOfReturnEntries(); ++i) {
     182             :     int return_offset = GetReturnOffset(i);
     183     1422402 :     if (pc_offset == return_offset) {
     184      498494 :       return GetReturnHandler(i);
     185             :     }
     186             :   }
     187             :   return -1;
     188             : }
     189             : 
     190             : #ifdef ENABLE_DISASSEMBLER
     191             : 
     192             : void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
     193             :   os << "   from   to       hdlr (prediction,   data)\n";
     194             :   for (int i = 0; i < NumberOfRangeEntries(); ++i) {
     195             :     int pc_start = GetRangeStart(i);
     196             :     int pc_end = GetRangeEnd(i);
     197             :     int handler_offset = GetRangeHandler(i);
     198             :     int handler_data = GetRangeData(i);
     199             :     CatchPrediction prediction = GetRangePrediction(i);
     200             :     os << "  (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
     201             :        << ")  ->  " << std::setw(4) << handler_offset
     202             :        << " (prediction=" << prediction << ", data=" << handler_data << ")\n";
     203             :   }
     204             : }
     205             : 
     206             : void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
     207             :   os << "  offset   handler\n";
     208             :   for (int i = 0; i < NumberOfReturnEntries(); ++i) {
     209             :     int pc_offset = GetReturnOffset(i);
     210             :     int handler_offset = GetReturnHandler(i);
     211             :     os << std::hex << "    " << std::setw(4) << pc_offset << "  ->  "
     212             :        << std::setw(4) << handler_offset << std::dec << "\n";
     213             :   }
     214             : }
     215             : 
     216             : #endif  // ENABLE_DISASSEMBLER
     217             : 
     218             : }  // namespace internal
     219      122036 : }  // namespace v8

Generated by: LCOV version 1.10