forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandler-table.h
More file actions
160 lines (131 loc) Β· 6.08 KB
/
handler-table.h
File metadata and controls
160 lines (131 loc) Β· 6.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// 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_CODEGEN_HANDLER_TABLE_H_
#define V8_CODEGEN_HANDLER_TABLE_H_
#include "src/base/bit-field.h"
#include "src/common/assert-scope.h"
#include "src/common/globals.h"
namespace v8 {
namespace internal {
class Assembler;
class TrustedByteArray;
class BytecodeArray;
class InstructionStream;
class Code;
namespace wasm {
class WasmCode;
} // namespace wasm
// 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
// {TrustedByteArray} 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 {InstructionStream} 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.
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.
UNCAUGHT_ASYNC_AWAIT, // The exception will be caught and cause a promise
// rejection in the desugaring of an async REPL
// script. The corresponding message object needs to
// be kept alive on the Isolate though.
};
enum EncodingMode { kRangeBasedEncoding, kReturnAddressBasedEncoding };
// Constructors for the various encodings.
explicit HandlerTable(Tagged<InstructionStream> code);
explicit HandlerTable(Tagged<Code> code);
explicit HandlerTable(Tagged<TrustedByteArray> byte_array);
#if V8_ENABLE_WEBASSEMBLY
explicit HandlerTable(const wasm::WasmCode* code);
#endif // V8_ENABLE_WEBASSEMBLY
explicit HandlerTable(Tagged<BytecodeArray> bytecode_array);
HandlerTable(Address handler_table, int handler_table_size,
EncodingMode encoding_mode);
// 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);
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 LookupHandlerIndexForRange(int pc_offset) const;
// 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);
void HandlerTableReturnPrint(std::ostream& os);
#endif
bool HandlerWasUsed(int index) const;
void MarkHandlerUsed(int index);
// Getters for handler table based on ranges.
CatchPrediction GetRangePrediction(int index) const;
static const int kNoHandlerFound = -1;
private:
// Gets entry size based on mode.
static int EntrySizeFromMode(EncodingMode mode);
int GetRangeHandlerBitfield(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.
const 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.
const EncodingMode mode_;
#endif
// Direct pointer into the encoded data. This pointer potentially points into
// objects on the GC heap (either {TrustedByteArray} or {InstructionStream})
// and could become stale during a collection. Hence we disallow any
// allocation.
const Address raw_encoded_data_;
DISALLOW_GARBAGE_COLLECTION(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.
using HandlerPredictionField = base::BitField<CatchPrediction, 0, 3>;
using HandlerWasUsedField = HandlerPredictionField::Next<bool, 1>;
using HandlerOffsetField = HandlerWasUsedField::Next<int, 28>;
public:
static const int kLazyDeopt = HandlerOffsetField::kMax;
};
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_HANDLER_TABLE_H_