• 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     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