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