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 3544013 : HandlerTable::HandlerTable(Code code)
17 3544013 : : HandlerTable(code->InstructionStart(), code->has_handler_table()
18 : ? code->handler_table_offset()
19 7689188 : : 0) {}
20 :
21 36225796 : HandlerTable::HandlerTable(BytecodeArray bytecode_array)
22 36225796 : : HandlerTable(bytecode_array->handler_table()) {}
23 :
24 2111459 : HandlerTable::HandlerTable(ByteArray byte_array)
25 38337255 : : number_of_entries_(byte_array->length() / kRangeEntrySize /
26 : sizeof(int32_t)),
27 : #ifdef DEBUG
28 : mode_(kRangeBasedEncoding),
29 : #endif
30 : raw_encoded_data_(
31 76674510 : reinterpret_cast<Address>(byte_array->GetDataStartAddress())) {
32 2111459 : }
33 :
34 : // TODO(jgruber,v8:8758): This constructor should eventually take the handler
35 : // table size in addition to the offset. That way the {HandlerTable} class
36 : // remains independent of how the offset/size is encoded in the various code
37 : // objects. This could even allow us to change the encoding to no longer expect
38 : // the "number of entries" in the beginning.
39 792 : HandlerTable::HandlerTable(Address instruction_start,
40 : size_t handler_table_offset)
41 : : number_of_entries_(0),
42 : #ifdef DEBUG
43 : mode_(kReturnAddressBasedEncoding),
44 : #endif
45 3544805 : raw_encoded_data_(instruction_start + handler_table_offset) {
46 3544805 : if (handler_table_offset > 0) {
47 601954 : number_of_entries_ = Memory<int32_t>(raw_encoded_data_);
48 601954 : raw_encoded_data_ += sizeof(int32_t);
49 : }
50 792 : }
51 :
52 1421800 : int HandlerTable::GetRangeStart(int index) const {
53 : DCHECK_EQ(kRangeBasedEncoding, mode_);
54 : DCHECK_LT(index, NumberOfRangeEntries());
55 11499527 : int offset = index * kRangeEntrySize + kRangeStartIndex;
56 22999054 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
57 : }
58 :
59 30485 : int HandlerTable::GetRangeEnd(int index) const {
60 : DCHECK_EQ(kRangeBasedEncoding, mode_);
61 : DCHECK_LT(index, NumberOfRangeEntries());
62 10108212 : int offset = index * kRangeEntrySize + kRangeEndIndex;
63 20216424 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
64 : }
65 :
66 30485 : int HandlerTable::GetRangeHandler(int index) const {
67 : DCHECK_EQ(kRangeBasedEncoding, mode_);
68 : DCHECK_LT(index, NumberOfRangeEntries());
69 10108212 : int offset = index * kRangeEntrySize + kRangeHandlerIndex;
70 10108212 : return HandlerOffsetField::decode(
71 20246909 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
72 : }
73 :
74 30150 : int HandlerTable::GetRangeData(int index) const {
75 : DCHECK_EQ(kRangeBasedEncoding, mode_);
76 : DCHECK_LT(index, NumberOfRangeEntries());
77 10107877 : int offset = index * kRangeEntrySize + kRangeDataIndex;
78 20215754 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
79 : }
80 :
81 0 : HandlerTable::CatchPrediction HandlerTable::GetRangePrediction(
82 : int index) const {
83 : DCHECK_EQ(kRangeBasedEncoding, mode_);
84 : DCHECK_LT(index, NumberOfRangeEntries());
85 0 : int offset = index * kRangeEntrySize + kRangeHandlerIndex;
86 0 : return HandlerPredictionField::decode(
87 0 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
88 : }
89 :
90 0 : int HandlerTable::GetReturnOffset(int index) const {
91 : DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
92 : DCHECK_LT(index, NumberOfReturnEntries());
93 1410196 : int offset = index * kReturnEntrySize + kReturnOffsetIndex;
94 2820392 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
95 : }
96 :
97 0 : int HandlerTable::GetReturnHandler(int index) const {
98 : DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
99 : DCHECK_LT(index, NumberOfReturnEntries());
100 499009 : int offset = index * kReturnEntrySize + kReturnHandlerIndex;
101 499009 : return HandlerOffsetField::decode(
102 998018 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
103 : }
104 :
105 146802 : void HandlerTable::SetRangeStart(int index, int value) {
106 146802 : int offset = index * kRangeEntrySize + kRangeStartIndex;
107 293604 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
108 146802 : }
109 :
110 146807 : void HandlerTable::SetRangeEnd(int index, int value) {
111 146807 : int offset = index * kRangeEntrySize + kRangeEndIndex;
112 293614 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
113 146807 : }
114 :
115 146804 : void HandlerTable::SetRangeHandler(int index, int handler_offset,
116 : CatchPrediction prediction) {
117 146804 : int value = HandlerOffsetField::encode(handler_offset) |
118 146804 : HandlerPredictionField::encode(prediction);
119 146804 : int offset = index * kRangeEntrySize + kRangeHandlerIndex;
120 293608 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
121 146804 : }
122 :
123 146806 : void HandlerTable::SetRangeData(int index, int value) {
124 146806 : int offset = index * kRangeEntrySize + kRangeDataIndex;
125 293612 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
126 146806 : }
127 :
128 : // static
129 2111467 : int HandlerTable::LengthForRange(int entries) {
130 2111467 : return entries * kRangeEntrySize * sizeof(int32_t);
131 : }
132 :
133 : // static
134 20521 : int HandlerTable::EmitReturnTableStart(Assembler* masm, int entries) {
135 20521 : masm->DataAlign(sizeof(int32_t)); // Make sure entries are aligned.
136 20522 : masm->RecordComment(";;; Exception handler table.");
137 : int table_start = masm->pc_offset();
138 20522 : masm->dd(entries);
139 20522 : return table_start;
140 : }
141 :
142 : // static
143 226727 : void HandlerTable::EmitReturnEntry(Assembler* masm, int offset, int handler) {
144 226727 : masm->dd(offset);
145 226727 : masm->dd(HandlerOffsetField::encode(handler));
146 226727 : }
147 :
148 15174030 : int HandlerTable::NumberOfRangeEntries() const {
149 : DCHECK_EQ(kRangeBasedEncoding, mode_);
150 46303589 : return number_of_entries_;
151 : }
152 :
153 0 : int HandlerTable::NumberOfReturnEntries() const {
154 : DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
155 4455992 : return number_of_entries_;
156 : }
157 :
158 21051832 : int HandlerTable::LookupRange(int pc_offset, int* data_out,
159 : CatchPrediction* prediction_out) {
160 : int innermost_handler = -1;
161 : #ifdef DEBUG
162 : // Assuming that ranges are well nested, we don't need to track the innermost
163 : // offsets. This is just to verify that the table is actually well nested.
164 : int innermost_start = std::numeric_limits<int>::min();
165 : int innermost_end = std::numeric_limits<int>::max();
166 : #endif
167 41207286 : for (int i = 0; i < NumberOfRangeEntries(); ++i) {
168 : int start_offset = GetRangeStart(i);
169 : int end_offset = GetRangeEnd(i);
170 : int handler_offset = GetRangeHandler(i);
171 : int handler_data = GetRangeData(i);
172 : CatchPrediction prediction = GetRangePrediction(i);
173 10077727 : if (pc_offset >= start_offset && pc_offset < end_offset) {
174 : DCHECK_GE(start_offset, innermost_start);
175 : DCHECK_LT(end_offset, innermost_end);
176 : innermost_handler = handler_offset;
177 : #ifdef DEBUG
178 : innermost_start = start_offset;
179 : innermost_end = end_offset;
180 : #endif
181 1441533 : if (data_out) *data_out = handler_data;
182 1441533 : if (prediction_out) *prediction_out = prediction;
183 : }
184 : }
185 21051832 : return innermost_handler;
186 : }
187 :
188 : // TODO(turbofan): Make sure table is sorted and use binary search.
189 3544805 : int HandlerTable::LookupReturn(int pc_offset) {
190 5367179 : for (int i = 0; i < NumberOfReturnEntries(); ++i) {
191 : int return_offset = GetReturnOffset(i);
192 1410196 : if (pc_offset == return_offset) {
193 499009 : return GetReturnHandler(i);
194 : }
195 : }
196 : return -1;
197 : }
198 :
199 : #ifdef ENABLE_DISASSEMBLER
200 :
201 : void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
202 : os << " from to hdlr (prediction, data)\n";
203 : for (int i = 0; i < NumberOfRangeEntries(); ++i) {
204 : int pc_start = GetRangeStart(i);
205 : int pc_end = GetRangeEnd(i);
206 : int handler_offset = GetRangeHandler(i);
207 : int handler_data = GetRangeData(i);
208 : CatchPrediction prediction = GetRangePrediction(i);
209 : os << " (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
210 : << ") -> " << std::setw(4) << handler_offset
211 : << " (prediction=" << prediction << ", data=" << handler_data << ")\n";
212 : }
213 : }
214 :
215 : void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
216 : os << " offset handler\n";
217 : for (int i = 0; i < NumberOfReturnEntries(); ++i) {
218 : int pc_offset = GetReturnOffset(i);
219 : int handler_offset = GetReturnHandler(i);
220 : os << std::hex << " " << std::setw(4) << pc_offset << " -> "
221 : << std::setw(4) << handler_offset << std::dec << "\n";
222 : }
223 : }
224 :
225 : #endif // ENABLE_DISASSEMBLER
226 :
227 : } // namespace internal
228 121996 : } // namespace v8
|