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