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_CODEGEN_HANDLER_TABLE_H_ 6 #define V8_CODEGEN_HANDLER_TABLE_H_ 7 8 #include "src/base/bit-field.h" 9 #include "src/common/assert-scope.h" 10 #include "src/common/globals.h" 11 12 namespace v8 { 13 namespace internal { 14 15 class Assembler; 16 class ByteArray; 17 class BytecodeArray; 18 19 namespace wasm { 20 class WasmCode; 21 } // namespace wasm 22 23 // HandlerTable is a byte array containing entries for exception handlers in 24 // the code object it is associated with. The tables come in two flavors: 25 // 1) Based on ranges: Used for unoptimized code. Stored in a {ByteArray} that 26 // is attached to each {BytecodeArray}. Contains one entry per exception 27 // handler and a range representing the try-block covered by that handler. 28 // Layout looks as follows: 29 // [ range-start , range-end , handler-offset , handler-data ] 30 // 2) Based on return addresses: Used for turbofanned code. Stored directly in 31 // the instruction stream of the {Code} object. Contains one entry per 32 // call-site that could throw an exception. Layout looks as follows: 33 // [ return-address-offset , handler-offset ] 34 class V8_EXPORT_PRIVATE HandlerTable { 35 public: 36 // Conservative prediction whether a given handler will locally catch an 37 // exception or cause a re-throw to outside the code boundary. Since this is 38 // undecidable it is merely an approximation (e.g. useful for debugger). 39 enum CatchPrediction { 40 UNCAUGHT, // The handler will (likely) rethrow the exception. 41 CAUGHT, // The exception will be caught by the handler. 42 PROMISE, // The exception will be caught and cause a promise rejection. 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 UNCAUGHT_ASYNC_AWAIT, // The exception will be caught and cause a promise 47 // rejection in the desugaring of an async REPL 48 // script. The corresponding message object needs to 49 // be kept alive on the Isolate though. 50 }; 51 52 enum EncodingMode { kRangeBasedEncoding, kReturnAddressBasedEncoding }; 53 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 HandlerTable(Address handler_table, int handler_table_size, 62 EncodingMode encoding_mode); 63 64 // Getters for handler table based on ranges. 65 int GetRangeStart(int index) const; 66 int GetRangeEnd(int index) const; 67 int GetRangeHandler(int index) const; 68 int GetRangeData(int index) const; 69 70 // Setters for handler table based on ranges. 71 void SetRangeStart(int index, int value); 72 void SetRangeEnd(int index, int value); 73 void SetRangeHandler(int index, int offset, CatchPrediction pred); 74 void SetRangeData(int index, int value); 75 76 // Returns the required length of the underlying byte array. 77 static int LengthForRange(int entries); 78 79 // Emitters for handler table based on return addresses. 80 static int EmitReturnTableStart(Assembler* masm); 81 static void EmitReturnEntry(Assembler* masm, int offset, int handler); 82 83 // Lookup handler in a table based on ranges. The {pc_offset} is an offset to 84 // the start of the potentially throwing instruction (using return addresses 85 // for this value would be invalid). 86 int LookupRange(int pc_offset, int* data, CatchPrediction* prediction); 87 88 // Lookup handler in a table based on return addresses. 89 int LookupReturn(int pc_offset); 90 91 // Returns the number of entries in the table. 92 int NumberOfRangeEntries() const; 93 int NumberOfReturnEntries() const; 94 95 #ifdef ENABLE_DISASSEMBLER 96 void HandlerTableRangePrint(std::ostream& os); 97 void HandlerTableReturnPrint(std::ostream& os); 98 #endif 99 100 private: 101 // Getters for handler table based on ranges. 102 CatchPrediction GetRangePrediction(int index) const; 103 104 // Gets entry size based on mode. 105 static int EntrySizeFromMode(EncodingMode mode); 106 107 // Getters for handler table based on return addresses. 108 int GetReturnOffset(int index) const; 109 int GetReturnHandler(int index) const; 110 111 // Number of entries in the loaded handler table. 112 const int number_of_entries_; 113 114 #ifdef DEBUG 115 // The encoding mode of the table. Mostly useful for debugging to check that 116 // used accessors and constructors fit together. 117 const EncodingMode mode_; 118 #endif 119 120 // Direct pointer into the encoded data. This pointer potentially points into 121 // objects on the GC heap (either {ByteArray} or {Code}) and could become 122 // stale during a collection. Hence we disallow any allocation. 123 const Address raw_encoded_data_; 124 DISALLOW_GARBAGE_COLLECTION(no_gc_) 125 126 // Layout description for handler table based on ranges. 127 static const int kRangeStartIndex = 0; 128 static const int kRangeEndIndex = 1; 129 static const int kRangeHandlerIndex = 2; 130 static const int kRangeDataIndex = 3; 131 static const int kRangeEntrySize = 4; 132 133 // Layout description for handler table based on return addresses. 134 static const int kReturnOffsetIndex = 0; 135 static const int kReturnHandlerIndex = 1; 136 static const int kReturnEntrySize = 2; 137 138 // Encoding of the {handler} field. 139 using HandlerPredictionField = base::BitField<CatchPrediction, 0, 3>; 140 using HandlerOffsetField = base::BitField<int, 3, 29>; 141 }; 142 143 } // namespace internal 144 } // namespace v8 145 146 #endif // V8_CODEGEN_HANDLER_TABLE_H_ 147