V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
handler-table.cc
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 HandlerTable::HandlerTable(Code code)
17  : HandlerTable(code->InstructionStart(), code->handler_table_offset()) {}
18 
19 HandlerTable::HandlerTable(BytecodeArray bytecode_array)
20  : HandlerTable(bytecode_array->handler_table()) {}
21 
22 HandlerTable::HandlerTable(ByteArray byte_array)
23  : number_of_entries_(byte_array->length() / kRangeEntrySize /
24  sizeof(int32_t)),
25 #ifdef DEBUG
26  mode_(kRangeBasedEncoding),
27 #endif
28  raw_encoded_data_(
29  reinterpret_cast<Address>(byte_array->GetDataStartAddress())) {
30 }
31 
32 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  raw_encoded_data_(instruction_start + handler_table_offset) {
39  if (handler_table_offset > 0) {
40  number_of_entries_ = Memory<int32_t>(raw_encoded_data_);
41  raw_encoded_data_ += sizeof(int32_t);
42  }
43 }
44 
45 int HandlerTable::GetRangeStart(int index) const {
46  DCHECK_EQ(kRangeBasedEncoding, mode_);
47  DCHECK_LT(index, NumberOfRangeEntries());
48  int offset = index * kRangeEntrySize + kRangeStartIndex;
49  return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
50 }
51 
52 int HandlerTable::GetRangeEnd(int index) const {
53  DCHECK_EQ(kRangeBasedEncoding, mode_);
54  DCHECK_LT(index, NumberOfRangeEntries());
55  int offset = index * kRangeEntrySize + kRangeEndIndex;
56  return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
57 }
58 
59 int HandlerTable::GetRangeHandler(int index) const {
60  DCHECK_EQ(kRangeBasedEncoding, mode_);
61  DCHECK_LT(index, NumberOfRangeEntries());
62  int offset = index * kRangeEntrySize + kRangeHandlerIndex;
63  return HandlerOffsetField::decode(
64  Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
65 }
66 
67 int HandlerTable::GetRangeData(int index) const {
68  DCHECK_EQ(kRangeBasedEncoding, mode_);
69  DCHECK_LT(index, NumberOfRangeEntries());
70  int offset = index * kRangeEntrySize + kRangeDataIndex;
71  return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
72 }
73 
74 HandlerTable::CatchPrediction HandlerTable::GetRangePrediction(
75  int index) const {
76  DCHECK_EQ(kRangeBasedEncoding, mode_);
77  DCHECK_LT(index, NumberOfRangeEntries());
78  int offset = index * kRangeEntrySize + kRangeHandlerIndex;
79  return HandlerPredictionField::decode(
80  Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
81 }
82 
83 int HandlerTable::GetReturnOffset(int index) const {
84  DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
85  DCHECK_LT(index, NumberOfReturnEntries());
86  int offset = index * kReturnEntrySize + kReturnOffsetIndex;
87  return Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t));
88 }
89 
90 int HandlerTable::GetReturnHandler(int index) const {
91  DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
92  DCHECK_LT(index, NumberOfReturnEntries());
93  int offset = index * kReturnEntrySize + kReturnHandlerIndex;
94  return HandlerOffsetField::decode(
95  Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)));
96 }
97 
98 void HandlerTable::SetRangeStart(int index, int value) {
99  int offset = index * kRangeEntrySize + kRangeStartIndex;
100  Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
101 }
102 
103 void HandlerTable::SetRangeEnd(int index, int value) {
104  int offset = index * kRangeEntrySize + kRangeEndIndex;
105  Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
106 }
107 
108 void HandlerTable::SetRangeHandler(int index, int handler_offset,
109  CatchPrediction prediction) {
110  int value = HandlerOffsetField::encode(handler_offset) |
111  HandlerPredictionField::encode(prediction);
112  int offset = index * kRangeEntrySize + kRangeHandlerIndex;
113  Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
114 }
115 
116 void HandlerTable::SetRangeData(int index, int value) {
117  int offset = index * kRangeEntrySize + kRangeDataIndex;
118  Memory<int32_t>(raw_encoded_data_ + offset * sizeof(int32_t)) = value;
119 }
120 
121 // static
122 int HandlerTable::LengthForRange(int entries) {
123  return entries * kRangeEntrySize * sizeof(int32_t);
124 }
125 
126 // static
127 int HandlerTable::EmitReturnTableStart(Assembler* masm, int entries) {
128  masm->DataAlign(sizeof(int32_t)); // Make sure entries are aligned.
129  masm->RecordComment(";;; Exception handler table.");
130  int table_start = masm->pc_offset();
131  masm->dd(entries);
132  return table_start;
133 }
134 
135 // static
136 void HandlerTable::EmitReturnEntry(Assembler* masm, int offset, int handler) {
137  masm->dd(offset);
138  masm->dd(HandlerOffsetField::encode(handler));
139 }
140 
141 int HandlerTable::NumberOfRangeEntries() const {
142  DCHECK_EQ(kRangeBasedEncoding, mode_);
143  return number_of_entries_;
144 }
145 
146 int HandlerTable::NumberOfReturnEntries() const {
147  DCHECK_EQ(kReturnAddressBasedEncoding, mode_);
148  return number_of_entries_;
149 }
150 
151 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  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  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  if (data_out) *data_out = handler_data;
175  if (prediction_out) *prediction_out = prediction;
176  }
177  }
178  return innermost_handler;
179 }
180 
181 // TODO(turbofan): Make sure table is sorted and use binary search.
182 int HandlerTable::LookupReturn(int pc_offset) {
183  for (int i = 0; i < NumberOfReturnEntries(); ++i) {
184  int return_offset = GetReturnOffset(i);
185  if (pc_offset == return_offset) {
186  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 } // namespace v8
Definition: libplatform.h:13