• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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