handler-table.h 5.62 KB
Newer Older
1 2 3 4
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef V8_CODEGEN_HANDLER_TABLE_H_
#define V8_CODEGEN_HANDLER_TABLE_H_
7

8
#include "src/base/bit-field.h"
9 10
#include "src/common/assert-scope.h"
#include "src/common/globals.h"
11 12 13 14 15 16 17 18

namespace v8 {
namespace internal {

class Assembler;
class ByteArray;
class BytecodeArray;

19 20
namespace wasm {
class WasmCode;
21
}  // namespace wasm
22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
// HandlerTable is a byte array containing entries for exception handlers in
// the code object it is associated with. The tables come in two flavors:
// 1) Based on ranges: Used for unoptimized code. Stored in a {ByteArray} that
//    is attached to each {BytecodeArray}. Contains one entry per exception
//    handler and a range representing the try-block covered by that handler.
//    Layout looks as follows:
//      [ range-start , range-end , handler-offset , handler-data ]
// 2) Based on return addresses: Used for turbofanned code. Stored directly in
//    the instruction stream of the {Code} object. Contains one entry per
//    call-site that could throw an exception. Layout looks as follows:
//      [ return-address-offset , handler-offset ]
class V8_EXPORT_PRIVATE HandlerTable {
 public:
  // Conservative prediction whether a given handler will locally catch an
  // exception or cause a re-throw to outside the code boundary. Since this is
  // undecidable it is merely an approximation (e.g. useful for debugger).
  enum CatchPrediction {
    UNCAUGHT,     // The handler will (likely) rethrow the exception.
    CAUGHT,       // The exception will be caught by the handler.
    PROMISE,      // The exception will be caught and cause a promise rejection.
    ASYNC_AWAIT,  // The exception will be caught and cause a promise rejection
                  // in the desugaring of an async function, so special
                  // async/await handling in the debugger can take place.
46 47 48 49
    UNCAUGHT_ASYNC_AWAIT,  // The exception will be caught and cause a promise
                           // rejection in the desugaring of an async REPL
                           // script. The corresponding message object needs to
                           // be kept alive on the Isolate though.
50 51
  };

52 53
  enum EncodingMode { kRangeBasedEncoding, kReturnAddressBasedEncoding };

54
  // Constructors for the various encodings.
55
  explicit HandlerTable(Code code);
56
  explicit HandlerTable(ByteArray byte_array);
57
#if V8_ENABLE_WEBASSEMBLY
58
  explicit HandlerTable(const wasm::WasmCode* code);
59
#endif  // V8_ENABLE_WEBASSEMBLY
60
  explicit HandlerTable(BytecodeArray bytecode_array);
61 62
  HandlerTable(Address handler_table, int handler_table_size,
               EncodingMode encoding_mode);
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

  // Getters for handler table based on ranges.
  int GetRangeStart(int index) const;
  int GetRangeEnd(int index) const;
  int GetRangeHandler(int index) const;
  int GetRangeData(int index) const;

  // Setters for handler table based on ranges.
  void SetRangeStart(int index, int value);
  void SetRangeEnd(int index, int value);
  void SetRangeHandler(int index, int offset, CatchPrediction pred);
  void SetRangeData(int index, int value);

  // Returns the required length of the underlying byte array.
  static int LengthForRange(int entries);

  // Emitters for handler table based on return addresses.
80
  static int EmitReturnTableStart(Assembler* masm);
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  static void EmitReturnEntry(Assembler* masm, int offset, int handler);

  // Lookup handler in a table based on ranges. The {pc_offset} is an offset to
  // the start of the potentially throwing instruction (using return addresses
  // for this value would be invalid).
  int LookupRange(int pc_offset, int* data, CatchPrediction* prediction);

  // Lookup handler in a table based on return addresses.
  int LookupReturn(int pc_offset);

  // Returns the number of entries in the table.
  int NumberOfRangeEntries() const;
  int NumberOfReturnEntries() const;

#ifdef ENABLE_DISASSEMBLER
96 97
  void HandlerTableRangePrint(std::ostream& os);
  void HandlerTableReturnPrint(std::ostream& os);
98 99 100 101 102 103
#endif

 private:
  // Getters for handler table based on ranges.
  CatchPrediction GetRangePrediction(int index) const;

104 105 106
  // Gets entry size based on mode.
  static int EntrySizeFromMode(EncodingMode mode);

107 108 109 110 111
  // Getters for handler table based on return addresses.
  int GetReturnOffset(int index) const;
  int GetReturnHandler(int index) const;

  // Number of entries in the loaded handler table.
112
  const int number_of_entries_;
113 114 115 116

#ifdef DEBUG
  // The encoding mode of the table. Mostly useful for debugging to check that
  // used accessors and constructors fit together.
117
  const EncodingMode mode_;
118 119
#endif

120 121 122 123
  // Direct pointer into the encoded data. This pointer potentially points into
  // objects on the GC heap (either {ByteArray} or {Code}) and could become
  // stale during a collection. Hence we disallow any allocation.
  const Address raw_encoded_data_;
124
  DISALLOW_GARBAGE_COLLECTION(no_gc_)
125 126 127 128 129 130 131 132 133 134 135 136 137 138

  // Layout description for handler table based on ranges.
  static const int kRangeStartIndex = 0;
  static const int kRangeEndIndex = 1;
  static const int kRangeHandlerIndex = 2;
  static const int kRangeDataIndex = 3;
  static const int kRangeEntrySize = 4;

  // Layout description for handler table based on return addresses.
  static const int kReturnOffsetIndex = 0;
  static const int kReturnHandlerIndex = 1;
  static const int kReturnEntrySize = 2;

  // Encoding of the {handler} field.
139 140
  using HandlerPredictionField = base::BitField<CatchPrediction, 0, 3>;
  using HandlerOffsetField = base::BitField<int, 3, 29>;
141 142 143 144 145
};

}  // namespace internal
}  // namespace v8

146
#endif  // V8_CODEGEN_HANDLER_TABLE_H_