| // 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_HANDLER_TABLE_H_ | |
| #define V8_HANDLER_TABLE_H_ | |
| #include "src/assert-scope.h" | |
| #include "src/globals.h" | |
| #include "src/utils.h" | |
| namespace v8 { | |
| namespace internal { | |
| class Assembler; | |
| class ByteArray; | |
| class BytecodeArray; | |
| // 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. | |
| }; | |
| // Constructors for the various encodings. | |
| explicit HandlerTable(Code* code); | |
| explicit HandlerTable(ByteArray* byte_array); | |
| explicit HandlerTable(BytecodeArray* bytecode_array); | |
| explicit HandlerTable(Address instruction_start, size_t handler_table_offset); | |
| // 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, int entries); | |
| 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: | |
| enum EncodingMode { kRangeBasedEncoding, kReturnAddressBasedEncoding }; | |
| // Getters for handler table based on ranges. | |
| CatchPrediction GetRangePrediction(int index) const; | |
| // 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. | |
| 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. | |
| EncodingMode mode_; | |
| #endif | |
| // Direct pointer into the encoded data. This pointer points into object on | |
| // the GC heap (either {ByteArray} or {Code}) and hence would become stale | |
| // during a collection. Hence we disallow any allocation. | |
| Address raw_encoded_data_; | |
| DisallowHeapAllocation 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. | |
| class HandlerPredictionField : public BitField<CatchPrediction, 0, 3> {}; | |
| class HandlerOffsetField : public BitField<int, 3, 29> {}; | |
| }; | |
| } // namespace internal | |
| } // namespace v8 | |
| #endif // V8_HANDLER_TABLE_H_ |