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
12namespace v8 {
13namespace internal {
14
15class Assembler;
16class ByteArray;
17class 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 ]
30class 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 DISALLOW_HEAP_ALLOCATION(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