| // 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. |
| |
| #ifndef V8_CODEGEN_HANDLER_TABLE_H_ |
| #define V8_CODEGEN_HANDLER_TABLE_H_ |
| |
| #include "src/base/bit-field.h" |
| #include "src/common/assert-scope.h" |
| #include "src/common/globals.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| class Assembler; |
| class ByteArray; |
| class BytecodeArray; |
| |
| namespace wasm { |
| class WasmCode; |
| } // namespace wasm |
| |
| // 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. |
| DESUGARING, // The exception will be caught, but both the exception and |
| // the catching are part of a desugaring and should therefore |
| // not be visible to the user (we won't notify the debugger of |
| // such exceptions). |
| 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. |
| 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. |
| }; |
| |
| enum EncodingMode { kRangeBasedEncoding, kReturnAddressBasedEncoding }; |
| |
| // Constructors for the various encodings. |
| explicit HandlerTable(Code code); |
| explicit HandlerTable(ByteArray byte_array); |
| explicit HandlerTable(const wasm::WasmCode* code); |
| explicit HandlerTable(BytecodeArray bytecode_array); |
| HandlerTable(Address handler_table, int handler_table_size, |
| EncodingMode encoding_mode); |
| |
| // 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. |
| static int EmitReturnTableStart(Assembler* masm); |
| 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 |
| void HandlerTableRangePrint(std::ostream& os); // NOLINT |
| void HandlerTableReturnPrint(std::ostream& os); // NOLINT |
| #endif |
| |
| private: |
| // Getters for handler table based on ranges. |
| CatchPrediction GetRangePrediction(int index) const; |
| |
| // Gets entry size based on mode. |
| static int EntrySizeFromMode(EncodingMode mode); |
| |
| // 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. |
| const int number_of_entries_; |
| |
| #ifdef DEBUG |
| // The encoding mode of the table. Mostly useful for debugging to check that |
| // used accessors and constructors fit together. |
| const EncodingMode mode_; |
| #endif |
| |
| // 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_; |
| DISALLOW_HEAP_ALLOCATION(no_gc_) |
| |
| // 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. |
| using HandlerPredictionField = base::BitField<CatchPrediction, 0, 3>; |
| using HandlerOffsetField = base::BitField<int, 3, 29>; |
| }; |
| |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_CODEGEN_HANDLER_TABLE_H_ |