Line data Source code
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 : #include "src/handler-table.h"
6 :
7 : #include <iomanip>
8 :
9 : #include "src/assembler-inl.h"
10 : #include "src/objects-inl.h"
11 : #include "src/objects/code-inl.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 3595984 : HandlerTable::HandlerTable(Code code)
17 7191968 : : HandlerTable(code->InstructionStart(), code->handler_table_offset()) {}
18 :
19 35865116 : HandlerTable::HandlerTable(BytecodeArray bytecode_array)
20 35865116 : : HandlerTable(bytecode_array->handler_table()) {}
21 :
22 37970924 : HandlerTable::HandlerTable(ByteArray byte_array)
23 37970938 : : number_of_entries_(byte_array->length() / kRangeEntrySize /
24 : sizeof(int32_t)),
25 : #ifdef DEBUG
26 : mode_(kRangeBasedEncoding),
27 : #endif
28 : raw_encoded_data_(
29 75941876 : reinterpret_cast<Address>(byte_array->GetDataStartAddress())) {
30 37970938 : }
31 :
32 792 : HandlerTable::HandlerTable(Address instruction_start,
33 : size_t handler_table_offset)
34 : : number_of_entries_(0),
35 : #ifdef DEBUG
36 : mode_(kReturnAddressBasedEncoding),
37 : #endif
38 3596776 : raw_encoded_data_(instruction_start + handler_table_offset) {
39 3596776 : if (handler_table_offset > 0) {
40 619330 : number_of_entries_ = Memory<int32_t>(raw_encoded_data_);
41 619330 : raw_encoded_data_ += sizeof(int32_t);
42 : }
43 792 : }
44 :
45 1342141 : int HandlerTable::GetRangeStart(int index) const {
46 : DCHECK_EQ(kRangeBasedEncoding, mode_);
47 : DCHECK_LT(index, NumberOfRangeEntries());
48 11183474 : int offset = index * kRangeEntrySize + kRangeStartIndex;
49 22366948 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
50 : }
51 :
52 29825 : int HandlerTable::GetRangeEnd(int index) const {
53 : DCHECK_EQ(kRangeBasedEncoding, mode_);
54 : DCHECK_LT(index, NumberOfRangeEntries());
55 9871158 : int offset = index * kRangeEntrySize + kRangeEndIndex;
56 19742316 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
57 : }
58 :
59 29825 : int HandlerTable::GetRangeHandler(int index) const {
60 : DCHECK_EQ(kRangeBasedEncoding, mode_);
61 : DCHECK_LT(index, NumberOfRangeEntries());
62 9871158 : int offset = index * kRangeEntrySize + kRangeHandlerIndex;
63 : return HandlerOffsetField::decode(
64 19772141 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
65 : }
66 :
67 29490 : int HandlerTable::GetRangeData(int index) const {
68 : DCHECK_EQ(kRangeBasedEncoding, mode_);
69 : DCHECK_LT(index, NumberOfRangeEntries());
70 9870823 : int offset = index * kRangeEntrySize + kRangeDataIndex;
71 19741646 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
72 : }
73 :
74 0 : HandlerTable::CatchPrediction HandlerTable::GetRangePrediction(
75 : int index) const {
76 : DCHECK_EQ(kRangeBasedEncoding, mode_);
77 : DCHECK_LT(index, NumberOfRangeEntries());
78 0 : int offset = index * kRangeEntrySize + kRangeHandlerIndex;
79 : return HandlerPredictionField::decode(
80 0 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
81 : }
82 :
83 0 : int HandlerTable::GetReturnOffset(int index) const {
84 : DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
85 : DCHECK_LT(index, NumberOfReturnEntries());
86 1344183 : int offset = index * kReturnEntrySize + kReturnOffsetIndex;
87 2688366 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
88 : }
89 :
90 0 : int HandlerTable::GetReturnHandler(int index) const {
91 : DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
92 : DCHECK_LT(index, NumberOfReturnEntries());
93 518355 : int offset = index * kReturnEntrySize + kReturnHandlerIndex;
94 : return HandlerOffsetField::decode(
95 1036710 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
96 : }
97 :
98 147032 : void HandlerTable::SetRangeStart(int index, int value) {
99 147032 : int offset = index * kRangeEntrySize + kRangeStartIndex;
100 294064 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
101 147032 : }
102 :
103 147033 : void HandlerTable::SetRangeEnd(int index, int value) {
104 147033 : int offset = index * kRangeEntrySize + kRangeEndIndex;
105 294066 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
106 147033 : }
107 :
108 147035 : void HandlerTable::SetRangeHandler(int index, int handler_offset,
109 : CatchPrediction prediction) {
110 147035 : int value = HandlerOffsetField::encode(handler_offset) |
111 147035 : HandlerPredictionField::encode(prediction);
112 147035 : int offset = index * kRangeEntrySize + kRangeHandlerIndex;
113 294070 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
114 147035 : }
115 :
116 147036 : void HandlerTable::SetRangeData(int index, int value) {
117 147036 : int offset = index * kRangeEntrySize + kRangeDataIndex;
118 294072 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
119 147036 : }
120 :
121 : // static
122 2105786 : int HandlerTable::LengthForRange(int entries) {
123 2105786 : return entries * kRangeEntrySize * sizeof(int32_t);
124 : }
125 :
126 : // static
127 19881 : int HandlerTable::EmitReturnTableStart(Assembler* masm, int entries) {
128 19881 : masm->DataAlign(sizeof(int32_t)); // Make sure entries are aligned.
129 19881 : masm->RecordComment(";;; Exception handler table.");
130 : int table_start = masm->pc_offset();
131 19881 : masm->dd(entries);
132 19881 : return table_start;
133 : }
134 :
135 : // static
136 189558 : void HandlerTable::EmitReturnEntry(Assembler* masm, int offset, int handler) {
137 189558 : masm->dd(offset);
138 189559 : masm->dd(HandlerOffsetField::encode(handler));
139 189560 : }
140 :
141 15556352 : int HandlerTable::NumberOfRangeEntries() const {
142 : DCHECK_EQ(kRangeBasedEncoding, mode_);
143 45706470 : return number_of_entries_;
144 : }
145 :
146 0 : int HandlerTable::NumberOfReturnEntries() const {
147 : DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
148 4422604 : return number_of_entries_;
149 : }
150 :
151 20308785 : int HandlerTable::LookupRange(int pc_offset, int* data_out,
152 : CatchPrediction* prediction_out) {
153 : int innermost_handler = -1;
154 : #ifdef DEBUG
155 : // Assuming that ranges are well nested, we don't need to track the innermost
156 : // offsets. This is just to verify that the table is actually well nested.
157 : int innermost_start = std::numeric_limits<int>::min();
158 : int innermost_end = std::numeric_limits<int>::max();
159 : #endif
160 60300236 : for (int i = 0; i < NumberOfRangeEntries(); ++i) {
161 : int start_offset = GetRangeStart(i);
162 : int end_offset = GetRangeEnd(i);
163 : int handler_offset = GetRangeHandler(i);
164 : int handler_data = GetRangeData(i);
165 : CatchPrediction prediction = GetRangePrediction(i);
166 9841333 : if (pc_offset >= start_offset && pc_offset < end_offset) {
167 : DCHECK_GE(start_offset, innermost_start);
168 : DCHECK_LT(end_offset, innermost_end);
169 : innermost_handler = handler_offset;
170 : #ifdef DEBUG
171 : innermost_start = start_offset;
172 : innermost_end = end_offset;
173 : #endif
174 1410842 : if (data_out) *data_out = handler_data;
175 1410842 : if (prediction_out) *prediction_out = prediction;
176 : }
177 : }
178 20308785 : return innermost_handler;
179 : }
180 :
181 : // TODO(turbofan): Make sure table is sorted and use binary search.
182 3596776 : int HandlerTable::LookupReturn(int pc_offset) {
183 8845208 : for (int i = 0; i < NumberOfReturnEntries(); ++i) {
184 : int return_offset = GetReturnOffset(i);
185 1344183 : if (pc_offset == return_offset) {
186 518355 : return GetReturnHandler(i);
187 : }
188 : }
189 : return -1;
190 : }
191 :
192 : #ifdef ENABLE_DISASSEMBLER
193 :
194 : void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
195 : os << " from to hdlr (prediction, data)\n";
196 : for (int i = 0; i < NumberOfRangeEntries(); ++i) {
197 : int pc_start = GetRangeStart(i);
198 : int pc_end = GetRangeEnd(i);
199 : int handler_offset = GetRangeHandler(i);
200 : int handler_data = GetRangeData(i);
201 : CatchPrediction prediction = GetRangePrediction(i);
202 : os << " (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
203 : << ") -> " << std::setw(4) << handler_offset
204 : << " (prediction=" << prediction << ", data=" << handler_data << ")\n";
205 : }
206 : }
207 :
208 : void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
209 : os << " offset handler\n";
210 : for (int i = 0; i < NumberOfReturnEntries(); ++i) {
211 : int pc_offset = GetReturnOffset(i);
212 : int handler_offset = GetReturnHandler(i);
213 : os << std::hex << " " << std::setw(4) << pc_offset << " -> "
214 : << std::setw(4) << handler_offset << std::dec << "\n";
215 : }
216 : }
217 :
218 : #endif // ENABLE_DISASSEMBLER
219 :
220 : } // namespace internal
221 183867 : } // namespace v8
|