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 3533693 : HandlerTable::HandlerTable(Code code)
17 : : HandlerTable(code->InstructionStart() + code->handler_table_offset(),
18 10601079 : code->handler_table_size()) {}
19 :
20 36244281 : HandlerTable::HandlerTable(BytecodeArray bytecode_array)
21 36244281 : : HandlerTable(bytecode_array->handler_table()) {}
22 :
23 2112569 : HandlerTable::HandlerTable(ByteArray byte_array)
24 38356850 : : number_of_entries_(byte_array->length() / kRangeEntrySize /
25 : sizeof(int32_t)),
26 : #ifdef DEBUG
27 : mode_(kRangeBasedEncoding),
28 : #endif
29 : raw_encoded_data_(
30 76713700 : reinterpret_cast<Address>(byte_array->GetDataStartAddress())) {
31 : DCHECK_EQ(0, byte_array->length() % (kRangeEntrySize * sizeof(int32_t)));
32 2112569 : }
33 :
34 792 : HandlerTable::HandlerTable(Address handler_table, int handler_table_size)
35 3534485 : : number_of_entries_(handler_table_size / kReturnEntrySize /
36 : sizeof(int32_t)),
37 : #ifdef DEBUG
38 : mode_(kReturnAddressBasedEncoding),
39 : #endif
40 3534485 : raw_encoded_data_(handler_table) {
41 : DCHECK_EQ(0, handler_table_size % (kReturnEntrySize * sizeof(int32_t)));
42 792 : }
43 :
44 1423695 : int HandlerTable::GetRangeStart(int index) const {
45 : DCHECK_EQ(kRangeBasedEncoding, mode_);
46 : DCHECK_LT(index, NumberOfRangeEntries());
47 11501925 : int offset = index * kRangeEntrySize + kRangeStartIndex;
48 23003850 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
49 : }
50 :
51 30531 : int HandlerTable::GetRangeEnd(int index) const {
52 : DCHECK_EQ(kRangeBasedEncoding, mode_);
53 : DCHECK_LT(index, NumberOfRangeEntries());
54 10108761 : int offset = index * kRangeEntrySize + kRangeEndIndex;
55 20217522 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
56 : }
57 :
58 30531 : int HandlerTable::GetRangeHandler(int index) const {
59 : DCHECK_EQ(kRangeBasedEncoding, mode_);
60 : DCHECK_LT(index, NumberOfRangeEntries());
61 10108761 : int offset = index * kRangeEntrySize + kRangeHandlerIndex;
62 10108761 : return HandlerOffsetField::decode(
63 20248053 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
64 : }
65 :
66 30196 : int HandlerTable::GetRangeData(int index) const {
67 : DCHECK_EQ(kRangeBasedEncoding, mode_);
68 : DCHECK_LT(index, NumberOfRangeEntries());
69 10108426 : int offset = index * kRangeEntrySize + kRangeDataIndex;
70 20216852 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
71 : }
72 :
73 0 : HandlerTable::CatchPrediction HandlerTable::GetRangePrediction(
74 : int index) const {
75 : DCHECK_EQ(kRangeBasedEncoding, mode_);
76 : DCHECK_LT(index, NumberOfRangeEntries());
77 0 : int offset = index * kRangeEntrySize + kRangeHandlerIndex;
78 0 : return HandlerPredictionField::decode(
79 0 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
80 : }
81 :
82 0 : int HandlerTable::GetReturnOffset(int index) const {
83 : DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
84 : DCHECK_LT(index, NumberOfReturnEntries());
85 1422402 : int offset = index * kReturnEntrySize + kReturnOffsetIndex;
86 2844804 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
87 : }
88 :
89 0 : int HandlerTable::GetReturnHandler(int index) const {
90 : DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
91 : DCHECK_LT(index, NumberOfReturnEntries());
92 498494 : int offset = index * kReturnEntrySize + kReturnHandlerIndex;
93 498494 : return HandlerOffsetField::decode(
94 996988 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
95 : }
96 :
97 147038 : void HandlerTable::SetRangeStart(int index, int value) {
98 147038 : int offset = index * kRangeEntrySize + kRangeStartIndex;
99 294076 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
100 147038 : }
101 :
102 147038 : void HandlerTable::SetRangeEnd(int index, int value) {
103 147038 : int offset = index * kRangeEntrySize + kRangeEndIndex;
104 294076 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
105 147038 : }
106 :
107 147040 : void HandlerTable::SetRangeHandler(int index, int handler_offset,
108 : CatchPrediction prediction) {
109 147040 : int value = HandlerOffsetField::encode(handler_offset) |
110 147040 : HandlerPredictionField::encode(prediction);
111 147040 : int offset = index * kRangeEntrySize + kRangeHandlerIndex;
112 294080 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
113 147040 : }
114 :
115 147038 : void HandlerTable::SetRangeData(int index, int value) {
116 147038 : int offset = index * kRangeEntrySize + kRangeDataIndex;
117 294076 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
118 147038 : }
119 :
120 : // static
121 2112568 : int HandlerTable::LengthForRange(int entries) {
122 2112568 : return entries * kRangeEntrySize * sizeof(int32_t);
123 : }
124 :
125 : // static
126 20540 : int HandlerTable::EmitReturnTableStart(Assembler* masm) {
127 20540 : masm->DataAlign(sizeof(int32_t)); // Make sure entries are aligned.
128 20540 : masm->RecordComment(";;; Exception handler table.");
129 : int table_start = masm->pc_offset();
130 20541 : return table_start;
131 : }
132 :
133 : // static
134 227171 : void HandlerTable::EmitReturnEntry(Assembler* masm, int offset, int handler) {
135 227171 : masm->dd(offset);
136 227171 : masm->dd(HandlerOffsetField::encode(handler));
137 227171 : }
138 :
139 15186394 : int HandlerTable::NumberOfRangeEntries() const {
140 : DCHECK_EQ(kRangeBasedEncoding, mode_);
141 46322549 : return number_of_entries_;
142 : }
143 :
144 0 : int HandlerTable::NumberOfReturnEntries() const {
145 : DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
146 4458393 : return number_of_entries_;
147 : }
148 :
149 21057925 : int HandlerTable::LookupRange(int pc_offset, int* data_out,
150 : CatchPrediction* prediction_out) {
151 : int innermost_handler = -1;
152 : #ifdef DEBUG
153 : // Assuming that ranges are well nested, we don't need to track the innermost
154 : // offsets. This is just to verify that the table is actually well nested.
155 : int innermost_start = std::numeric_limits<int>::min();
156 : int innermost_end = std::numeric_limits<int>::max();
157 : #endif
158 41214385 : for (int i = 0; i < NumberOfRangeEntries(); ++i) {
159 : int start_offset = GetRangeStart(i);
160 : int end_offset = GetRangeEnd(i);
161 : int handler_offset = GetRangeHandler(i);
162 : int handler_data = GetRangeData(i);
163 : CatchPrediction prediction = GetRangePrediction(i);
164 10078230 : if (pc_offset >= start_offset && pc_offset < end_offset) {
165 : DCHECK_GE(start_offset, innermost_start);
166 : DCHECK_LT(end_offset, innermost_end);
167 : innermost_handler = handler_offset;
168 : #ifdef DEBUG
169 : innermost_start = start_offset;
170 : innermost_end = end_offset;
171 : #endif
172 1441335 : if (data_out) *data_out = handler_data;
173 1441335 : if (prediction_out) *prediction_out = prediction;
174 : }
175 : }
176 21057925 : return innermost_handler;
177 : }
178 :
179 : // TODO(turbofan): Make sure table is sorted and use binary search.
180 3534485 : int HandlerTable::LookupReturn(int pc_offset) {
181 5382301 : for (int i = 0; i < NumberOfReturnEntries(); ++i) {
182 : int return_offset = GetReturnOffset(i);
183 1422402 : if (pc_offset == return_offset) {
184 498494 : return GetReturnHandler(i);
185 : }
186 : }
187 : return -1;
188 : }
189 :
190 : #ifdef ENABLE_DISASSEMBLER
191 :
192 : void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
193 : os << " from to hdlr (prediction, data)\n";
194 : for (int i = 0; i < NumberOfRangeEntries(); ++i) {
195 : int pc_start = GetRangeStart(i);
196 : int pc_end = GetRangeEnd(i);
197 : int handler_offset = GetRangeHandler(i);
198 : int handler_data = GetRangeData(i);
199 : CatchPrediction prediction = GetRangePrediction(i);
200 : os << " (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
201 : << ") -> " << std::setw(4) << handler_offset
202 : << " (prediction=" << prediction << ", data=" << handler_data << ")\n";
203 : }
204 : }
205 :
206 : void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
207 : os << " offset handler\n";
208 : for (int i = 0; i < NumberOfReturnEntries(); ++i) {
209 : int pc_offset = GetReturnOffset(i);
210 : int handler_offset = GetReturnHandler(i);
211 : os << std::hex << " " << std::setw(4) << pc_offset << " -> "
212 : << std::setw(4) << handler_offset << std::dec << "\n";
213 : }
214 : }
215 :
216 : #endif // ENABLE_DISASSEMBLER
217 :
218 : } // namespace internal
219 122036 : } // namespace v8
|