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 3564892 : HandlerTable::HandlerTable(Code code)
17 : : HandlerTable(code->InstructionStart() + code->handler_table_offset(),
18 10694676 : code->handler_table_size()) {}
19 :
20 36237712 : HandlerTable::HandlerTable(BytecodeArray bytecode_array)
21 36237712 : : HandlerTable(bytecode_array->handler_table()) {}
22 :
23 2112663 : HandlerTable::HandlerTable(ByteArray byte_array)
24 38350375 : : number_of_entries_(byte_array->length() / kRangeEntrySize /
25 : sizeof(int32_t)),
26 : #ifdef DEBUG
27 : mode_(kRangeBasedEncoding),
28 : #endif
29 : raw_encoded_data_(
30 76700750 : reinterpret_cast<Address>(byte_array->GetDataStartAddress())) {
31 : DCHECK_EQ(0, byte_array->length() % (kRangeEntrySize * sizeof(int32_t)));
32 2112663 : }
33 :
34 792 : HandlerTable::HandlerTable(Address handler_table, int handler_table_size)
35 3565684 : : number_of_entries_(handler_table_size / kReturnEntrySize /
36 : sizeof(int32_t)),
37 : #ifdef DEBUG
38 : mode_(kReturnAddressBasedEncoding),
39 : #endif
40 3565684 : raw_encoded_data_(handler_table) {
41 : DCHECK_EQ(0, handler_table_size % (kReturnEntrySize * sizeof(int32_t)));
42 792 : }
43 :
44 1423009 : int HandlerTable::GetRangeStart(int index) const {
45 : DCHECK_EQ(kRangeBasedEncoding, mode_);
46 : DCHECK_LT(index, NumberOfRangeEntries());
47 11501027 : int offset = index * kRangeEntrySize + kRangeStartIndex;
48 23002054 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
49 : }
50 :
51 30508 : int HandlerTable::GetRangeEnd(int index) const {
52 : DCHECK_EQ(kRangeBasedEncoding, mode_);
53 : DCHECK_LT(index, NumberOfRangeEntries());
54 10108526 : int offset = index * kRangeEntrySize + kRangeEndIndex;
55 20217052 : return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
56 : }
57 :
58 30508 : int HandlerTable::GetRangeHandler(int index) const {
59 : DCHECK_EQ(kRangeBasedEncoding, mode_);
60 : DCHECK_LT(index, NumberOfRangeEntries());
61 10108526 : int offset = index * kRangeEntrySize + kRangeHandlerIndex;
62 10108526 : return HandlerOffsetField::decode(
63 20247560 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
64 : }
65 :
66 30173 : int HandlerTable::GetRangeData(int index) const {
67 : DCHECK_EQ(kRangeBasedEncoding, mode_);
68 : DCHECK_LT(index, NumberOfRangeEntries());
69 10108191 : int offset = index * kRangeEntrySize + kRangeDataIndex;
70 20216382 : 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 1411944 : int offset = index * kReturnEntrySize + kReturnOffsetIndex;
86 2823888 : 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 498493 : int offset = index * kReturnEntrySize + kReturnHandlerIndex;
93 498493 : return HandlerOffsetField::decode(
94 996986 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
95 : }
96 :
97 146809 : void HandlerTable::SetRangeStart(int index, int value) {
98 146809 : int offset = index * kRangeEntrySize + kRangeStartIndex;
99 293618 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
100 146809 : }
101 :
102 146811 : void HandlerTable::SetRangeEnd(int index, int value) {
103 146811 : int offset = index * kRangeEntrySize + kRangeEndIndex;
104 293622 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
105 146811 : }
106 :
107 146811 : void HandlerTable::SetRangeHandler(int index, int handler_offset,
108 : CatchPrediction prediction) {
109 146811 : int value = HandlerOffsetField::encode(handler_offset) |
110 146811 : HandlerPredictionField::encode(prediction);
111 146811 : int offset = index * kRangeEntrySize + kRangeHandlerIndex;
112 293622 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
113 146811 : }
114 :
115 146812 : void HandlerTable::SetRangeData(int index, int value) {
116 146812 : int offset = index * kRangeEntrySize + kRangeDataIndex;
117 293624 : Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
118 146812 : }
119 :
120 : // static
121 2112669 : int HandlerTable::LengthForRange(int entries) {
122 2112669 : return entries * kRangeEntrySize * sizeof(int32_t);
123 : }
124 :
125 : // static
126 20539 : int HandlerTable::EmitReturnTableStart(Assembler* masm) {
127 20539 : masm->DataAlign(sizeof(int32_t)); // Make sure entries are aligned.
128 20541 : masm->RecordComment(";;; Exception handler table.");
129 : int table_start = masm->pc_offset();
130 20542 : return table_start;
131 : }
132 :
133 : // static
134 226783 : void HandlerTable::EmitReturnEntry(Assembler* masm, int offset, int handler) {
135 226783 : masm->dd(offset);
136 226783 : masm->dd(HandlerOffsetField::encode(handler));
137 226784 : }
138 :
139 15197645 : int HandlerTable::NumberOfRangeEntries() const {
140 : DCHECK_EQ(kRangeBasedEncoding, mode_);
141 46315759 : return number_of_entries_;
142 : }
143 :
144 0 : int HandlerTable::NumberOfReturnEntries() const {
145 : DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
146 4479135 : return number_of_entries_;
147 : }
148 :
149 21040096 : 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 41196132 : 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 10078018 : 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 1440693 : if (data_out) *data_out = handler_data;
173 1440693 : if (prediction_out) *prediction_out = prediction;
174 : }
175 : }
176 21040096 : return innermost_handler;
177 : }
178 :
179 : // TODO(turbofan): Make sure table is sorted and use binary search.
180 3565684 : int HandlerTable::LookupReturn(int pc_offset) {
181 5392586 : for (int i = 0; i < NumberOfReturnEntries(); ++i) {
182 : int return_offset = GetReturnOffset(i);
183 1411944 : if (pc_offset == return_offset) {
184 498493 : 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 122028 : } // namespace v8
|