Home | History | Annotate | Download | only in src
      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 #ifndef V8_HANDLER_TABLE_H_
      6 #define V8_HANDLER_TABLE_H_
      7 
      8 #include "src/assert-scope.h"
      9 #include "src/globals.h"
     10 #include "src/utils.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 class Assembler;
     16 class ByteArray;
     17 class BytecodeArray;
     18 
     19 // HandlerTable is a byte array containing entries for exception handlers in
     20 // the code object it is associated with. The tables come in two flavors:
     21 // 1) Based on ranges: Used for unoptimized code. Stored in a {ByteArray} that
     22 //    is attached to each {BytecodeArray}. Contains one entry per exception
     23 //    handler and a range representing the try-block covered by that handler.
     24 //    Layout looks as follows:
     25 //      [ range-start , range-end , handler-offset , handler-data ]
     26 // 2) Based on return addresses: Used for turbofanned code. Stored directly in
     27 //    the instruction stream of the {Code} object. Contains one entry per
     28 //    call-site that could throw an exception. Layout looks as follows:
     29 //      [ return-address-offset , handler-offset ]
     30 class V8_EXPORT_PRIVATE HandlerTable {
     31  public:
     32   // Conservative prediction whether a given handler will locally catch an
     33   // exception or cause a re-throw to outside the code boundary. Since this is
     34   // undecidable it is merely an approximation (e.g. useful for debugger).
     35   enum CatchPrediction {
     36     UNCAUGHT,     // The handler will (likely) rethrow the exception.
     37     CAUGHT,       // The exception will be caught by the handler.
     38     PROMISE,      // The exception will be caught and cause a promise rejection.
     39     DESUGARING,   // The exception will be caught, but both the exception and
     40                   // the catching are part of a desugaring and should therefore
     41                   // not be visible to the user (we won't notify the debugger of
     42                   // such exceptions).
     43     ASYNC_AWAIT,  // The exception will be caught and cause a promise rejection
     44                   // in the desugaring of an async function, so special
     45                   // async/await handling in the debugger can take place.
     46   };
     47 
     48   // Constructors for the various encodings.
     49   explicit HandlerTable(Code* code);
     50   explicit HandlerTable(ByteArray* byte_array);
     51   explicit HandlerTable(BytecodeArray* bytecode_array);
     52   explicit HandlerTable(Address instruction_start, size_t handler_table_offset);
     53 
     54   // Getters for handler table based on ranges.
     55   int GetRangeStart(int index) const;
     56   int GetRangeEnd(int index) const;
     57   int GetRangeHandler(int index) const;
     58   int GetRangeData(int index) const;
     59 
     60   // Setters for handler table based on ranges.
     61   void SetRangeStart(int index, int value);
     62   void SetRangeEnd(int index, int value);
     63   void SetRangeHandler(int index, int offset, CatchPrediction pred);
     64   void SetRangeData(int index, int value);
     65 
     66   // Returns the required length of the underlying byte array.
     67   static int LengthForRange(int entries);
     68 
     69   // Emitters for handler table based on return addresses.
     70   static int EmitReturnTableStart(Assembler* masm, int entries);
     71   static void EmitReturnEntry(Assembler* masm, int offset, int handler);
     72 
     73   // Lookup handler in a table based on ranges. The {pc_offset} is an offset to
     74   // the start of the potentially throwing instruction (using return addresses
     75   // for this value would be invalid).
     76   int LookupRange(int pc_offset, int* data, CatchPrediction* prediction);
     77 
     78   // Lookup handler in a table based on return addresses.
     79   int LookupReturn(int pc_offset);
     80 
     81   // Returns the number of entries in the table.
     82   int NumberOfRangeEntries() const;
     83   int NumberOfReturnEntries() const;
     84 
     85 #ifdef ENABLE_DISASSEMBLER
     86   void HandlerTableRangePrint(std::ostream& os);   // NOLINT
     87   void HandlerTableReturnPrint(std::ostream& os);  // NOLINT
     88 #endif
     89 
     90  private:
     91   enum EncodingMode { kRangeBasedEncoding, kReturnAddressBasedEncoding };
     92 
     93   // Getters for handler table based on ranges.
     94   CatchPrediction GetRangePrediction(int index) const;
     95 
     96   // Getters for handler table based on return addresses.
     97   int GetReturnOffset(int index) const;
     98   int GetReturnHandler(int index) const;
     99 
    100   // Number of entries in the loaded handler table.
    101   int number_of_entries_;
    102 
    103 #ifdef DEBUG
    104   // The encoding mode of the table. Mostly useful for debugging to check that
    105   // used accessors and constructors fit together.
    106   EncodingMode mode_;
    107 #endif
    108 
    109   // Direct pointer into the encoded data. This pointer points into object on
    110   // the GC heap (either {ByteArray} or {Code}) and hence would become stale
    111   // during a collection. Hence we disallow any allocation.
    112   Address raw_encoded_data_;
    113   DisallowHeapAllocation no_gc_;
    114 
    115   // Layout description for handler table based on ranges.
    116   static const int kRangeStartIndex = 0;
    117   static const int kRangeEndIndex = 1;
    118   static const int kRangeHandlerIndex = 2;
    119   static const int kRangeDataIndex = 3;
    120   static const int kRangeEntrySize = 4;
    121 
    122   // Layout description for handler table based on return addresses.
    123   static const int kReturnOffsetIndex = 0;
    124   static const int kReturnHandlerIndex = 1;
    125   static const int kReturnEntrySize = 2;
    126 
    127   // Encoding of the {handler} field.
    128   class HandlerPredictionField : public BitField<CatchPrediction, 0, 3> {};
    129   class HandlerOffsetField : public BitField<int, 3, 29> {};
    130 };
    131 
    132 }  // namespace internal
    133 }  // namespace v8
    134 
    135 #endif  // V8_HANDLER_TABLE_H_
    136