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 DESUGARING, // The exception will be caught, but both the exception and 44 // the catching are part of a desugaring and should therefore 45 // not be visible to the user (we won't notify the debugger of 46 // such exceptions). 47 ASYNC_AWAIT, // The exception will be caught and cause a promise rejection 48 // in the desugaring of an async function, so special 49 // async/await handling in the debugger can take place. 50 UNCAUGHT_ASYNC_AWAIT, // The exception will be caught and cause a promise 51 // rejection in the desugaring of an async REPL 52 // script. The corresponding message object needs to 53 // be kept alive on the Isolate though. 54 }; 55 56 enum EncodingMode { kRangeBasedEncoding, kReturnAddressBasedEncoding }; 57 58 // Constructors for the various encodings. 59 explicit HandlerTable(Code code); 60 explicit HandlerTable(ByteArray byte_array); 61 explicit HandlerTable(const wasm::WasmCode* code); 62 explicit HandlerTable(BytecodeArray bytecode_array); 63 HandlerTable(Address handler_table, int handler_table_size, 64 EncodingMode encoding_mode); 65 66 // Getters for handler table based on ranges. 67 int GetRangeStart(int index) const; 68 int GetRangeEnd(int index) const; 69 int GetRangeHandler(int index) const; 70 int GetRangeData(int index) const; 71 72 // Setters for handler table based on ranges. 73 void SetRangeStart(int index, int value); 74 void SetRangeEnd(int index, int value); 75 void SetRangeHandler(int index, int offset, CatchPrediction pred); 76 void SetRangeData(int index, int value); 77 78 // Returns the required length of the underlying byte array. 79 static int LengthForRange(int entries); 80 81 // Emitters for handler table based on return addresses. 82 static int EmitReturnTableStart(Assembler* masm); 83 static void EmitReturnEntry(Assembler* masm, int offset, int handler); 84 85 // Lookup handler in a table based on ranges. The {pc_offset} is an offset to 86 // the start of the potentially throwing instruction (using return addresses 87 // for this value would be invalid). 88 int LookupRange(int pc_offset, int* data, CatchPrediction* prediction); 89 90 // Lookup handler in a table based on return addresses. 91 int LookupReturn(int pc_offset); 92 93 // Returns the number of entries in the table. 94 int NumberOfRangeEntries() const; 95 int NumberOfReturnEntries() const; 96 97 #ifdef ENABLE_DISASSEMBLER 98 void HandlerTableRangePrint(std::ostream& os); // NOLINT 99 void HandlerTableReturnPrint(std::ostream& os); // NOLINT 100 #endif 101 102 private: 103 // Getters for handler table based on ranges. 104 CatchPrediction GetRangePrediction(int index) const; 105 106 // Gets entry size based on mode. 107 static int EntrySizeFromMode(EncodingMode mode); 108 109 // Getters for handler table based on return addresses. 110 int GetReturnOffset(int index) const; 111 int GetReturnHandler(int index) const; 112 113 // Number of entries in the loaded handler table. 114 const int number_of_entries_; 115 116 #ifdef DEBUG 117 // The encoding mode of the table. Mostly useful for debugging to check that 118 // used accessors and constructors fit together. 119 const EncodingMode mode_; 120 #endif 121 122 // Direct pointer into the encoded data. This pointer potentially points into 123 // objects on the GC heap (either {ByteArray} or {Code}) and could become 124 // stale during a collection. Hence we disallow any allocation. 125 const Address raw_encoded_data_; 126 DISALLOW_HEAP_ALLOCATION(no_gc_) 127 128 // Layout description for handler table based on ranges. 129 static const int kRangeStartIndex = 0; 130 static const int kRangeEndIndex = 1; 131 static const int kRangeHandlerIndex = 2; 132 static const int kRangeDataIndex = 3; 133 static const int kRangeEntrySize = 4; 134 135 // Layout description for handler table based on return addresses. 136 static const int kReturnOffsetIndex = 0; 137 static const int kReturnHandlerIndex = 1; 138 static const int kReturnEntrySize = 2; 139 140 // Encoding of the {handler} field. 141 using HandlerPredictionField = base::BitField<CatchPrediction, 0, 3>; 142 using HandlerOffsetField = base::BitField<int, 3, 29>; 143 }; 144 145 } // namespace internal 146 } // namespace v8 147 148 #endif // V8_CODEGEN_HANDLER_TABLE_H_ 149