OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecode-array-builder.h" | 5 #include "src/interpreter/bytecode-array-builder.h" |
6 #include "src/compiler.h" | 6 #include "src/compiler.h" |
7 | 7 |
8 namespace v8 { | 8 namespace v8 { |
9 namespace internal { | 9 namespace internal { |
10 namespace interpreter { | 10 namespace interpreter { |
(...skipping 13 matching lines...) Expand all Loading... |
24 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); | 24 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); |
25 return Bytecodes::FromByte( | 25 return Bytecodes::FromByte( |
26 array_builder_.bytecodes()->at(previous_bytecode_start_)); | 26 array_builder_.bytecodes()->at(previous_bytecode_start_)); |
27 } | 27 } |
28 | 28 |
29 // Returns the operand at operand_index for the previous bytecode in the | 29 // Returns the operand at operand_index for the previous bytecode in the |
30 // same basic block. | 30 // same basic block. |
31 MUST_USE_RESULT uint32_t GetOperand(int operand_index) const { | 31 MUST_USE_RESULT uint32_t GetOperand(int operand_index) const { |
32 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); | 32 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); |
33 Bytecode bytecode = GetBytecode(); | 33 Bytecode bytecode = GetBytecode(); |
| 34 int prefix_offset = 0; |
| 35 int operand_scale = Bytecodes::GetPrefixBytecodeScale(bytecode); |
| 36 if (operand_scale > 1) { |
| 37 prefix_offset = 1; |
| 38 bytecode = Bytecodes::FromByte(array_builder_.bytecodes()->at( |
| 39 previous_bytecode_start_ + prefix_offset)); |
| 40 } |
34 DCHECK_GE(operand_index, 0); | 41 DCHECK_GE(operand_index, 0); |
35 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); | 42 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); |
36 size_t operand_offset = | 43 size_t operand_offset = |
37 previous_bytecode_start_ + | 44 previous_bytecode_start_ + prefix_offset + |
38 Bytecodes::GetOperandOffset(bytecode, operand_index); | 45 Bytecodes::GetOperandOffset(bytecode, operand_index, operand_scale); |
39 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); | 46 OperandSize size = |
| 47 Bytecodes::GetOperandSize(bytecode, operand_index, operand_scale); |
40 switch (size) { | 48 switch (size) { |
41 case OperandSize::kNone: | 49 case OperandSize::kNone: |
42 UNREACHABLE(); | 50 UNREACHABLE(); |
43 break; | 51 break; |
44 case OperandSize::kByte: | 52 case OperandSize::kByte: |
45 return static_cast<uint32_t>( | 53 return static_cast<uint32_t>( |
46 array_builder_.bytecodes()->at(operand_offset)); | 54 array_builder_.bytecodes()->at(operand_offset)); |
47 case OperandSize::kShort: | 55 case OperandSize::kShort: { |
48 uint16_t operand = | 56 uint16_t operand = |
49 (array_builder_.bytecodes()->at(operand_offset) << 8) + | 57 (array_builder_.bytecodes()->at(operand_offset) << 8) + |
50 array_builder_.bytecodes()->at(operand_offset + 1); | 58 array_builder_.bytecodes()->at(operand_offset + 1); |
51 return static_cast<uint32_t>(operand); | 59 return static_cast<uint32_t>(operand); |
| 60 } |
| 61 case OperandSize::kQuad: { |
| 62 return ((array_builder_.bytecodes()->at(operand_offset + 0) << 24) + |
| 63 (array_builder_.bytecodes()->at(operand_offset + 1) << 16) + |
| 64 (array_builder_.bytecodes()->at(operand_offset + 2) << 8) + |
| 65 array_builder_.bytecodes()->at(operand_offset + 3)); |
| 66 } |
52 } | 67 } |
53 return 0; | 68 return 0; |
54 } | 69 } |
55 | 70 |
56 Handle<Object> GetConstantForIndexOperand(int operand_index) const { | 71 Handle<Object> GetConstantForIndexOperand(int operand_index) const { |
57 return array_builder_.constant_array_builder()->At( | 72 return array_builder_.constant_array_builder()->At( |
58 GetOperand(operand_index)); | 73 GetOperand(operand_index)); |
59 } | 74 } |
60 | 75 |
61 private: | 76 private: |
(...skipping 14 matching lines...) Expand all Loading... |
76 constant_array_builder_(isolate, zone), | 91 constant_array_builder_(isolate, zone), |
77 handler_table_builder_(isolate, zone), | 92 handler_table_builder_(isolate, zone), |
78 source_position_table_builder_(isolate, zone), | 93 source_position_table_builder_(isolate, zone), |
79 last_block_end_(0), | 94 last_block_end_(0), |
80 last_bytecode_start_(~0), | 95 last_bytecode_start_(~0), |
81 exit_seen_in_block_(false), | 96 exit_seen_in_block_(false), |
82 unbound_jumps_(0), | 97 unbound_jumps_(0), |
83 parameter_count_(parameter_count), | 98 parameter_count_(parameter_count), |
84 local_register_count_(locals_count), | 99 local_register_count_(locals_count), |
85 context_register_count_(context_count), | 100 context_register_count_(context_count), |
86 temporary_allocator_(zone, fixed_register_count()), | 101 temporary_allocator_(zone, fixed_register_count()) { |
87 register_translator_(this) { | |
88 DCHECK_GE(parameter_count_, 0); | 102 DCHECK_GE(parameter_count_, 0); |
89 DCHECK_GE(context_register_count_, 0); | 103 DCHECK_GE(context_register_count_, 0); |
90 DCHECK_GE(local_register_count_, 0); | 104 DCHECK_GE(local_register_count_, 0); |
91 return_position_ = | 105 return_position_ = |
92 literal ? std::max(literal->start_position(), literal->end_position() - 1) | 106 literal ? std::max(literal->start_position(), literal->end_position() - 1) |
93 : RelocInfo::kNoPosition; | 107 : RelocInfo::kNoPosition; |
94 LOG_CODE_EVENT(isolate_, CodeStartLinePosInfoRecordEvent( | 108 LOG_CODE_EVENT(isolate_, CodeStartLinePosInfoRecordEvent( |
95 source_position_table_builder())); | 109 source_position_table_builder())); |
96 } | 110 } |
97 | 111 |
(...skipping 20 matching lines...) Expand all Loading... |
118 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const { | 132 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const { |
119 return reg.is_parameter() || reg.index() < locals_count(); | 133 return reg.is_parameter() || reg.index() < locals_count(); |
120 } | 134 } |
121 | 135 |
122 | 136 |
123 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { | 137 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { |
124 DCHECK_EQ(bytecode_generated_, false); | 138 DCHECK_EQ(bytecode_generated_, false); |
125 DCHECK(exit_seen_in_block_); | 139 DCHECK(exit_seen_in_block_); |
126 | 140 |
127 int bytecode_size = static_cast<int>(bytecodes_.size()); | 141 int bytecode_size = static_cast<int>(bytecodes_.size()); |
128 int register_count = | 142 int register_count = fixed_and_temporary_register_count(); |
129 fixed_and_temporary_register_count() + translation_register_count(); | |
130 int frame_size = register_count * kPointerSize; | 143 int frame_size = register_count * kPointerSize; |
131 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray(); | 144 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray(); |
132 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable(); | 145 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable(); |
133 Handle<ByteArray> source_position_table = | 146 Handle<ByteArray> source_position_table = |
134 source_position_table_builder()->ToSourcePositionTable(); | 147 source_position_table_builder()->ToSourcePositionTable(); |
135 Handle<BytecodeArray> bytecode_array = isolate_->factory()->NewBytecodeArray( | 148 Handle<BytecodeArray> bytecode_array = isolate_->factory()->NewBytecodeArray( |
136 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(), | 149 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(), |
137 constant_pool); | 150 constant_pool); |
138 bytecode_array->set_handler_table(*handler_table); | 151 bytecode_array->set_handler_table(*handler_table); |
139 bytecode_array->set_source_position_table(*source_position_table); | 152 bytecode_array->set_source_position_table(*source_position_table); |
140 | 153 |
141 void* line_info = source_position_table_builder()->DetachJITHandlerData(); | 154 void* line_info = source_position_table_builder()->DetachJITHandlerData(); |
142 LOG_CODE_EVENT(isolate_, CodeEndLinePosInfoRecordEvent( | 155 LOG_CODE_EVENT(isolate_, CodeEndLinePosInfoRecordEvent( |
143 AbstractCode::cast(*bytecode_array), line_info)); | 156 AbstractCode::cast(*bytecode_array), line_info)); |
144 | 157 |
145 bytecode_generated_ = true; | 158 bytecode_generated_ = true; |
146 return bytecode_array; | 159 return bytecode_array; |
147 } | 160 } |
148 | 161 |
149 | |
150 template <size_t N> | 162 template <size_t N> |
151 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { | 163 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t (&operands)[N], |
| 164 int operand_scale) { |
152 // Don't output dead code. | 165 // Don't output dead code. |
153 if (exit_seen_in_block_) return; | 166 if (exit_seen_in_block_) return; |
154 | 167 |
155 int operand_count = static_cast<int>(N); | 168 int operand_count = static_cast<int>(N); |
156 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count); | 169 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count); |
157 | 170 |
158 int register_operand_count = Bytecodes::NumberOfRegisterOperands(bytecode); | 171 last_bytecode_start_ = bytecodes()->size(); |
159 if (register_operand_count > 0) { | 172 |
160 register_translator()->TranslateInputRegisters(bytecode, operands, | 173 // Emit prefix if scaling is active. |
161 operand_count); | 174 switch (operand_scale) { |
| 175 case 4: |
| 176 bytecodes()->push_back(Bytecodes::ToByte(Bytecode::kExtraWide)); |
| 177 break; |
| 178 case 2: |
| 179 bytecodes()->push_back(Bytecodes::ToByte(Bytecode::kWide)); |
| 180 break; |
| 181 case 1: |
| 182 break; |
| 183 default: |
| 184 UNREACHABLE(); |
| 185 break; |
162 } | 186 } |
163 | 187 |
164 last_bytecode_start_ = bytecodes()->size(); | 188 // Emit bytecode. |
165 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | 189 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
| 190 |
| 191 // Emit operands. |
166 for (int i = 0; i < operand_count; i++) { | 192 for (int i = 0; i < operand_count; i++) { |
167 DCHECK(OperandIsValid(bytecode, i, operands[i])); | 193 DCHECK(OperandIsValid(bytecode, i, operand_scale, operands[i])); |
168 switch (Bytecodes::GetOperandSize(bytecode, i)) { | 194 switch (Bytecodes::GetOperandSize(bytecode, i, operand_scale)) { |
169 case OperandSize::kNone: | 195 case OperandSize::kNone: |
170 UNREACHABLE(); | 196 UNREACHABLE(); |
171 break; | 197 break; |
172 case OperandSize::kByte: | 198 case OperandSize::kByte: |
173 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); | 199 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); |
174 break; | 200 break; |
175 case OperandSize::kShort: { | 201 case OperandSize::kShort: { |
176 uint8_t operand_bytes[2]; | 202 uint8_t operand_bytes[2]; |
177 WriteUnalignedUInt16(operand_bytes, operands[i]); | 203 WriteUnalignedUInt16(operand_bytes, operands[i]); |
178 bytecodes()->insert(bytecodes()->end(), operand_bytes, | 204 bytecodes()->insert(bytecodes()->end(), operand_bytes, |
179 operand_bytes + 2); | 205 operand_bytes + 2); |
180 break; | 206 break; |
181 } | 207 } |
| 208 case OperandSize::kQuad: { |
| 209 uint8_t operand_bytes[4]; |
| 210 WriteUnalignedUInt32(operand_bytes, operands[i]); |
| 211 bytecodes()->insert(bytecodes()->end(), operand_bytes, |
| 212 operand_bytes + 4); |
| 213 break; |
| 214 } |
182 } | 215 } |
183 } | 216 } |
184 | |
185 if (register_operand_count > 0) { | |
186 register_translator()->TranslateOutputRegisters(); | |
187 } | |
188 } | 217 } |
189 | 218 |
190 | |
191 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | |
192 uint32_t operand1, uint32_t operand2, | |
193 uint32_t operand3) { | |
194 uint32_t operands[] = {operand0, operand1, operand2, operand3}; | |
195 Output(bytecode, operands); | |
196 } | |
197 | |
198 | |
199 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | |
200 uint32_t operand1, uint32_t operand2) { | |
201 uint32_t operands[] = {operand0, operand1, operand2}; | |
202 Output(bytecode, operands); | |
203 } | |
204 | |
205 | |
206 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | |
207 uint32_t operand1) { | |
208 uint32_t operands[] = {operand0, operand1}; | |
209 Output(bytecode, operands); | |
210 } | |
211 | |
212 | |
213 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { | |
214 uint32_t operands[] = {operand0}; | |
215 Output(bytecode, operands); | |
216 } | |
217 | |
218 | |
219 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | 219 void BytecodeArrayBuilder::Output(Bytecode bytecode) { |
220 // Don't output dead code. | 220 // Don't output dead code. |
221 if (exit_seen_in_block_) return; | 221 if (exit_seen_in_block_) return; |
222 | 222 |
223 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); | 223 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); |
224 last_bytecode_start_ = bytecodes()->size(); | 224 last_bytecode_start_ = bytecodes()->size(); |
225 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | 225 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
226 } | 226 } |
227 | 227 |
| 228 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, int operand_scale, |
| 229 uint32_t operand0, uint32_t operand1, |
| 230 uint32_t operand2, uint32_t operand3) { |
| 231 uint32_t operands[] = {operand0, operand1, operand2, operand3}; |
| 232 Output(bytecode, operands, operand_scale); |
| 233 } |
| 234 |
| 235 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, int operand_scale, |
| 236 uint32_t operand0, uint32_t operand1, |
| 237 uint32_t operand2) { |
| 238 uint32_t operands[] = {operand0, operand1, operand2}; |
| 239 Output(bytecode, operands, operand_scale); |
| 240 } |
| 241 |
| 242 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, int operand_scale, |
| 243 uint32_t operand0, uint32_t operand1) { |
| 244 uint32_t operands[] = {operand0, operand1}; |
| 245 Output(bytecode, operands, operand_scale); |
| 246 } |
| 247 |
| 248 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, int operand_scale, |
| 249 uint32_t operand0) { |
| 250 uint32_t operands[] = {operand0}; |
| 251 Output(bytecode, operands, operand_scale); |
| 252 } |
| 253 |
228 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | 254 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
229 Register reg) { | 255 Register reg) { |
230 Output(BytecodeForBinaryOperation(op), reg.ToRawOperand()); | 256 int operand_scale = OperandScale(SizeForRegisterOperand(reg)); |
| 257 OutputScaled(BytecodeForBinaryOperation(op), operand_scale, |
| 258 reg.ToRawOperand()); |
231 return *this; | 259 return *this; |
232 } | 260 } |
233 | 261 |
234 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op) { | 262 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op) { |
235 Output(BytecodeForCountOperation(op)); | 263 Output(BytecodeForCountOperation(op)); |
236 return *this; | 264 return *this; |
237 } | 265 } |
238 | 266 |
239 | 267 |
240 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { | 268 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { |
241 Output(Bytecode::kLogicalNot); | 269 Output(Bytecode::kLogicalNot); |
242 return *this; | 270 return *this; |
243 } | 271 } |
244 | 272 |
245 | 273 |
246 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { | 274 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { |
247 Output(Bytecode::kTypeOf); | 275 Output(Bytecode::kTypeOf); |
248 return *this; | 276 return *this; |
249 } | 277 } |
250 | 278 |
251 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op, | 279 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op, |
252 Register reg) { | 280 Register reg) { |
253 Output(BytecodeForCompareOperation(op), reg.ToRawOperand()); | 281 int operand_scale = OperandScale(SizeForRegisterOperand(reg)); |
| 282 OutputScaled(BytecodeForCompareOperation(op), operand_scale, |
| 283 reg.ToRawOperand()); |
254 return *this; | 284 return *this; |
255 } | 285 } |
256 | 286 |
257 | 287 |
258 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( | 288 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( |
259 v8::internal::Smi* smi) { | 289 v8::internal::Smi* smi) { |
260 int32_t raw_smi = smi->value(); | 290 int32_t raw_smi = smi->value(); |
261 if (raw_smi == 0) { | 291 if (raw_smi == 0) { |
262 Output(Bytecode::kLdaZero); | 292 Output(Bytecode::kLdaZero); |
263 } else if (raw_smi >= -128 && raw_smi <= 127) { | |
264 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi)); | |
265 } else { | 293 } else { |
266 LoadLiteral(Handle<Object>(smi, isolate_)); | 294 OperandSize operand_size = SizeForSignedOperand(raw_smi); |
| 295 int operand_scale = OperandScale(operand_size); |
| 296 OutputScaled(Bytecode::kLdaSmi, operand_scale, |
| 297 SignedOperand(raw_smi, operand_size)); |
267 } | 298 } |
268 return *this; | 299 return *this; |
269 } | 300 } |
270 | 301 |
271 | 302 |
272 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { | 303 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { |
273 size_t entry = GetConstantPoolEntry(object); | 304 size_t entry = GetConstantPoolEntry(object); |
274 if (FitsInIdx8Operand(entry)) { | 305 int operand_scale = OperandScale(SizeForUnsignedOperand(entry)); |
275 Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry)); | 306 OutputScaled(Bytecode::kLdaConstant, operand_scale, UnsignedOperand(entry)); |
276 } else if (FitsInIdx16Operand(entry)) { | |
277 Output(Bytecode::kLdaConstantWide, static_cast<uint16_t>(entry)); | |
278 } else { | |
279 UNIMPLEMENTED(); | |
280 } | |
281 return *this; | 307 return *this; |
282 } | 308 } |
283 | 309 |
284 | 310 |
285 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { | 311 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { |
286 Output(Bytecode::kLdaUndefined); | 312 Output(Bytecode::kLdaUndefined); |
287 return *this; | 313 return *this; |
288 } | 314 } |
289 | 315 |
290 | 316 |
(...skipping 26 matching lines...) Expand all Loading... |
317 LoadTrue(); | 343 LoadTrue(); |
318 } else { | 344 } else { |
319 LoadFalse(); | 345 LoadFalse(); |
320 } | 346 } |
321 return *this; | 347 return *this; |
322 } | 348 } |
323 | 349 |
324 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( | 350 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( |
325 Register reg) { | 351 Register reg) { |
326 if (!IsRegisterInAccumulator(reg)) { | 352 if (!IsRegisterInAccumulator(reg)) { |
327 Output(Bytecode::kLdar, reg.ToRawOperand()); | 353 int operand_scale = OperandScale(SizeForRegisterOperand(reg)); |
| 354 OutputScaled(Bytecode::kLdar, operand_scale, reg.ToRawOperand()); |
328 } | 355 } |
329 return *this; | 356 return *this; |
330 } | 357 } |
331 | 358 |
332 | 359 |
333 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( | 360 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( |
334 Register reg) { | 361 Register reg) { |
335 if (!IsRegisterInAccumulator(reg)) { | 362 if (!IsRegisterInAccumulator(reg)) { |
336 Output(Bytecode::kStar, reg.ToRawOperand()); | 363 int operand_scale = OperandScale(SizeForRegisterOperand(reg)); |
| 364 OutputScaled(Bytecode::kStar, operand_scale, reg.ToRawOperand()); |
337 } | 365 } |
338 return *this; | 366 return *this; |
339 } | 367 } |
340 | 368 |
341 | 369 |
342 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, | 370 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
343 Register to) { | 371 Register to) { |
344 DCHECK(from != to); | 372 DCHECK(from != to); |
345 if (FitsInReg8Operand(from) && FitsInReg8Operand(to)) { | 373 int operand_scale = |
346 Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand()); | 374 OperandScale(SizeForRegisterOperand(from), SizeForRegisterOperand(to)); |
347 } else if (FitsInReg16Operand(from) && FitsInReg16Operand(to)) { | 375 OutputScaled(Bytecode::kMov, operand_scale, from.ToRawOperand(), |
348 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); | 376 to.ToRawOperand()); |
349 } else { | |
350 UNIMPLEMENTED(); | |
351 } | |
352 return *this; | 377 return *this; |
353 } | 378 } |
354 | 379 |
355 void BytecodeArrayBuilder::MoveRegisterUntranslated(Register from, | |
356 Register to) { | |
357 // Move bytecodes modify the stack. Checking validity is an | |
358 // essential mitigation against corrupting the stack. | |
359 if (FitsInReg8OperandUntranslated(from)) { | |
360 CHECK(RegisterIsValid(from, OperandType::kReg8) && | |
361 RegisterIsValid(to, OperandType::kReg16)); | |
362 } else if (FitsInReg8OperandUntranslated(to)) { | |
363 CHECK(RegisterIsValid(from, OperandType::kReg16) && | |
364 RegisterIsValid(to, OperandType::kReg8)); | |
365 } else { | |
366 UNIMPLEMENTED(); | |
367 } | |
368 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); | |
369 } | |
370 | |
371 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( | 380 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( |
372 const Handle<String> name, int feedback_slot, TypeofMode typeof_mode) { | 381 const Handle<String> name, int feedback_slot, TypeofMode typeof_mode) { |
373 // TODO(rmcilroy): Potentially store typeof information in an | 382 // TODO(rmcilroy): Potentially store typeof information in an |
374 // operand rather than having extra bytecodes. | 383 // operand rather than having extra bytecodes. |
375 Bytecode bytecode = BytecodeForLoadGlobal(typeof_mode); | 384 Bytecode bytecode = BytecodeForLoadGlobal(typeof_mode); |
376 size_t name_index = GetConstantPoolEntry(name); | 385 size_t name_index = GetConstantPoolEntry(name); |
377 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 386 int operand_scale = OperandScale(SizeForUnsignedOperand(name_index), |
378 Output(bytecode, static_cast<uint8_t>(name_index), | 387 SizeForUnsignedOperand(feedback_slot)); |
379 static_cast<uint8_t>(feedback_slot)); | 388 OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index), |
380 } else if (FitsInIdx16Operand(name_index) && | 389 UnsignedOperand(feedback_slot)); |
381 FitsInIdx16Operand(feedback_slot)) { | |
382 Output(BytecodeForWideOperands(bytecode), static_cast<uint16_t>(name_index), | |
383 static_cast<uint16_t>(feedback_slot)); | |
384 } else { | |
385 UNIMPLEMENTED(); | |
386 } | |
387 return *this; | 390 return *this; |
388 } | 391 } |
389 | 392 |
390 | |
391 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( | 393 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( |
392 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { | 394 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { |
393 Bytecode bytecode = BytecodeForStoreGlobal(language_mode); | 395 Bytecode bytecode = BytecodeForStoreGlobal(language_mode); |
394 size_t name_index = GetConstantPoolEntry(name); | 396 size_t name_index = GetConstantPoolEntry(name); |
395 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 397 int operand_scale = OperandScale(SizeForUnsignedOperand(name_index), |
396 Output(bytecode, static_cast<uint8_t>(name_index), | 398 SizeForUnsignedOperand(feedback_slot)); |
397 static_cast<uint8_t>(feedback_slot)); | 399 OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index), |
398 } else if (FitsInIdx16Operand(name_index) && | 400 UnsignedOperand(feedback_slot)); |
399 FitsInIdx16Operand(feedback_slot)) { | |
400 Output(BytecodeForWideOperands(bytecode), static_cast<uint16_t>(name_index), | |
401 static_cast<uint16_t>(feedback_slot)); | |
402 } else { | |
403 UNIMPLEMENTED(); | |
404 } | |
405 return *this; | 401 return *this; |
406 } | 402 } |
407 | 403 |
408 | 404 |
409 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, | 405 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, |
410 int slot_index) { | 406 int slot_index) { |
411 DCHECK(slot_index >= 0); | 407 int operand_scale = OperandScale(SizeForRegisterOperand(context), |
412 if (FitsInIdx8Operand(slot_index)) { | 408 SizeForUnsignedOperand(slot_index)); |
413 Output(Bytecode::kLdaContextSlot, context.ToRawOperand(), | 409 OutputScaled(Bytecode::kLdaContextSlot, operand_scale, context.ToRawOperand(), |
414 static_cast<uint8_t>(slot_index)); | 410 UnsignedOperand(slot_index)); |
415 } else if (FitsInIdx16Operand(slot_index)) { | |
416 Output(Bytecode::kLdaContextSlotWide, context.ToRawOperand(), | |
417 static_cast<uint16_t>(slot_index)); | |
418 } else { | |
419 UNIMPLEMENTED(); | |
420 } | |
421 return *this; | 411 return *this; |
422 } | 412 } |
423 | 413 |
424 | 414 |
425 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, | 415 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, |
426 int slot_index) { | 416 int slot_index) { |
427 DCHECK(slot_index >= 0); | 417 int operand_scale = OperandScale(SizeForRegisterOperand(context), |
428 if (FitsInIdx8Operand(slot_index)) { | 418 SizeForUnsignedOperand(slot_index)); |
429 Output(Bytecode::kStaContextSlot, context.ToRawOperand(), | 419 OutputScaled(Bytecode::kStaContextSlot, operand_scale, context.ToRawOperand(), |
430 static_cast<uint8_t>(slot_index)); | 420 UnsignedOperand(slot_index)); |
431 } else if (FitsInIdx16Operand(slot_index)) { | |
432 Output(Bytecode::kStaContextSlotWide, context.ToRawOperand(), | |
433 static_cast<uint16_t>(slot_index)); | |
434 } else { | |
435 UNIMPLEMENTED(); | |
436 } | |
437 return *this; | 421 return *this; |
438 } | 422 } |
439 | 423 |
440 | |
441 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( | 424 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( |
442 const Handle<String> name, TypeofMode typeof_mode) { | 425 const Handle<String> name, TypeofMode typeof_mode) { |
443 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | 426 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) |
444 ? Bytecode::kLdaLookupSlotInsideTypeof | 427 ? Bytecode::kLdaLookupSlotInsideTypeof |
445 : Bytecode::kLdaLookupSlot; | 428 : Bytecode::kLdaLookupSlot; |
446 size_t name_index = GetConstantPoolEntry(name); | 429 size_t name_index = GetConstantPoolEntry(name); |
447 if (FitsInIdx8Operand(name_index)) { | 430 int operand_scale = OperandScale(SizeForUnsignedOperand(name_index)); |
448 Output(bytecode, static_cast<uint8_t>(name_index)); | 431 OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index)); |
449 } else if (FitsInIdx16Operand(name_index)) { | |
450 Output(BytecodeForWideOperands(bytecode), | |
451 static_cast<uint16_t>(name_index)); | |
452 } else { | |
453 UNIMPLEMENTED(); | |
454 } | |
455 return *this; | 432 return *this; |
456 } | 433 } |
457 | 434 |
458 | |
459 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( | 435 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( |
460 const Handle<String> name, LanguageMode language_mode) { | 436 const Handle<String> name, LanguageMode language_mode) { |
461 Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode); | 437 Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode); |
462 size_t name_index = GetConstantPoolEntry(name); | 438 size_t name_index = GetConstantPoolEntry(name); |
463 if (FitsInIdx8Operand(name_index)) { | 439 int operand_scale = OperandScale(SizeForUnsignedOperand(name_index)); |
464 Output(bytecode, static_cast<uint8_t>(name_index)); | 440 OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index)); |
465 } else if (FitsInIdx16Operand(name_index)) { | |
466 Output(BytecodeForWideOperands(bytecode), | |
467 static_cast<uint16_t>(name_index)); | |
468 } else { | |
469 UNIMPLEMENTED(); | |
470 } | |
471 return *this; | 441 return *this; |
472 } | 442 } |
473 | 443 |
474 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( | 444 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
475 Register object, const Handle<Name> name, int feedback_slot) { | 445 Register object, const Handle<Name> name, int feedback_slot) { |
476 size_t name_index = GetConstantPoolEntry(name); | 446 size_t name_index = GetConstantPoolEntry(name); |
477 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 447 int operand_scale = OperandScale(SizeForRegisterOperand(object), |
478 Output(Bytecode::kLoadIC, object.ToRawOperand(), | 448 SizeForUnsignedOperand(name_index), |
479 static_cast<uint8_t>(name_index), | 449 SizeForUnsignedOperand(feedback_slot)); |
480 static_cast<uint8_t>(feedback_slot)); | 450 OutputScaled(Bytecode::kLoadIC, operand_scale, object.ToRawOperand(), |
481 } else if (FitsInIdx16Operand(name_index) && | 451 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); |
482 FitsInIdx16Operand(feedback_slot)) { | |
483 Output(Bytecode::kLoadICWide, object.ToRawOperand(), | |
484 static_cast<uint16_t>(name_index), | |
485 static_cast<uint16_t>(feedback_slot)); | |
486 } else { | |
487 UNIMPLEMENTED(); | |
488 } | |
489 return *this; | 452 return *this; |
490 } | 453 } |
491 | 454 |
492 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( | 455 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
493 Register object, int feedback_slot) { | 456 Register object, int feedback_slot) { |
494 if (FitsInIdx8Operand(feedback_slot)) { | 457 int operand_scale = OperandScale(SizeForRegisterOperand(object), |
495 Output(Bytecode::kKeyedLoadIC, object.ToRawOperand(), | 458 SizeForUnsignedOperand(feedback_slot)); |
496 static_cast<uint8_t>(feedback_slot)); | 459 OutputScaled(Bytecode::kKeyedLoadIC, operand_scale, object.ToRawOperand(), |
497 } else if (FitsInIdx16Operand(feedback_slot)) { | 460 UnsignedOperand(feedback_slot)); |
498 Output(Bytecode::kKeyedLoadICWide, object.ToRawOperand(), | |
499 static_cast<uint16_t>(feedback_slot)); | |
500 } else { | |
501 UNIMPLEMENTED(); | |
502 } | |
503 return *this; | 461 return *this; |
504 } | 462 } |
505 | 463 |
506 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( | 464 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
507 Register object, const Handle<Name> name, int feedback_slot, | 465 Register object, const Handle<Name> name, int feedback_slot, |
508 LanguageMode language_mode) { | 466 LanguageMode language_mode) { |
509 Bytecode bytecode = BytecodeForStoreIC(language_mode); | 467 Bytecode bytecode = BytecodeForStoreIC(language_mode); |
510 size_t name_index = GetConstantPoolEntry(name); | 468 size_t name_index = GetConstantPoolEntry(name); |
511 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 469 int operand_scale = OperandScale(SizeForRegisterOperand(object), |
512 Output(bytecode, object.ToRawOperand(), static_cast<uint8_t>(name_index), | 470 SizeForUnsignedOperand(name_index), |
513 static_cast<uint8_t>(feedback_slot)); | 471 SizeForUnsignedOperand(feedback_slot)); |
514 } else if (FitsInIdx16Operand(name_index) && | 472 OutputScaled(bytecode, operand_scale, object.ToRawOperand(), |
515 FitsInIdx16Operand(feedback_slot)) { | 473 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); |
516 Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), | |
517 static_cast<uint16_t>(name_index), | |
518 static_cast<uint16_t>(feedback_slot)); | |
519 } else { | |
520 UNIMPLEMENTED(); | |
521 } | |
522 return *this; | 474 return *this; |
523 } | 475 } |
524 | 476 |
525 | 477 |
526 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( | 478 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
527 Register object, Register key, int feedback_slot, | 479 Register object, Register key, int feedback_slot, |
528 LanguageMode language_mode) { | 480 LanguageMode language_mode) { |
529 Bytecode bytecode = BytecodeForKeyedStoreIC(language_mode); | 481 Bytecode bytecode = BytecodeForKeyedStoreIC(language_mode); |
530 if (FitsInIdx8Operand(feedback_slot)) { | 482 int operand_scale = |
531 Output(bytecode, object.ToRawOperand(), key.ToRawOperand(), | 483 OperandScale(SizeForRegisterOperand(object), SizeForRegisterOperand(key), |
532 static_cast<uint8_t>(feedback_slot)); | 484 SizeForUnsignedOperand(feedback_slot)); |
533 } else if (FitsInIdx16Operand(feedback_slot)) { | 485 OutputScaled(bytecode, operand_scale, object.ToRawOperand(), |
534 Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), | 486 key.ToRawOperand(), UnsignedOperand(feedback_slot)); |
535 key.ToRawOperand(), static_cast<uint16_t>(feedback_slot)); | |
536 } else { | |
537 UNIMPLEMENTED(); | |
538 } | |
539 return *this; | 487 return *this; |
540 } | 488 } |
541 | 489 |
542 | 490 |
543 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure( | 491 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure( |
544 Handle<SharedFunctionInfo> shared_info, PretenureFlag tenured) { | 492 Handle<SharedFunctionInfo> shared_info, PretenureFlag tenured) { |
545 size_t entry = GetConstantPoolEntry(shared_info); | 493 size_t entry = GetConstantPoolEntry(shared_info); |
546 DCHECK(FitsInImm8Operand(tenured)); | 494 int operand_scale = OperandScale(SizeForUnsignedOperand(entry)); |
547 if (FitsInIdx8Operand(entry)) { | 495 OutputScaled(Bytecode::kCreateClosure, operand_scale, UnsignedOperand(entry), |
548 Output(Bytecode::kCreateClosure, static_cast<uint8_t>(entry), | 496 UnsignedOperand(static_cast<size_t>(tenured))); |
549 static_cast<uint8_t>(tenured)); | |
550 } else if (FitsInIdx16Operand(entry)) { | |
551 Output(Bytecode::kCreateClosureWide, static_cast<uint16_t>(entry), | |
552 static_cast<uint8_t>(tenured)); | |
553 } else { | |
554 UNIMPLEMENTED(); | |
555 } | |
556 return *this; | 497 return *this; |
557 } | 498 } |
558 | 499 |
559 | 500 |
560 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( | 501 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( |
561 CreateArgumentsType type) { | 502 CreateArgumentsType type) { |
562 // TODO(rmcilroy): Consider passing the type as a bytecode operand rather | 503 // TODO(rmcilroy): Consider passing the type as a bytecode operand rather |
563 // than having two different bytecodes once we have better support for | 504 // than having two different bytecodes once we have better support for |
564 // branches in the InterpreterAssembler. | 505 // branches in the InterpreterAssembler. |
565 Bytecode bytecode = BytecodeForCreateArguments(type); | 506 Bytecode bytecode = BytecodeForCreateArguments(type); |
566 Output(bytecode); | 507 Output(bytecode); |
567 return *this; | 508 return *this; |
568 } | 509 } |
569 | 510 |
570 | 511 |
571 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( | 512 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( |
572 Handle<String> pattern, int literal_index, int flags) { | 513 Handle<String> pattern, int literal_index, int flags) { |
573 DCHECK(FitsInImm8Operand(flags)); // Flags should fit in 8 bits. | |
574 size_t pattern_entry = GetConstantPoolEntry(pattern); | 514 size_t pattern_entry = GetConstantPoolEntry(pattern); |
575 if (FitsInIdx8Operand(literal_index) && FitsInIdx8Operand(pattern_entry)) { | 515 int operand_scale = OperandScale(SizeForUnsignedOperand(pattern_entry), |
576 Output(Bytecode::kCreateRegExpLiteral, static_cast<uint8_t>(pattern_entry), | 516 SizeForUnsignedOperand(literal_index), |
577 static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags)); | 517 SizeForUnsignedOperand(flags)); |
578 } else if (FitsInIdx16Operand(literal_index) && | 518 OutputScaled(Bytecode::kCreateRegExpLiteral, operand_scale, |
579 FitsInIdx16Operand(pattern_entry)) { | 519 UnsignedOperand(pattern_entry), UnsignedOperand(literal_index), |
580 Output(Bytecode::kCreateRegExpLiteralWide, | 520 UnsignedOperand(flags)); |
581 static_cast<uint16_t>(pattern_entry), | |
582 static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags)); | |
583 } else { | |
584 UNIMPLEMENTED(); | |
585 } | |
586 return *this; | 521 return *this; |
587 } | 522 } |
588 | 523 |
589 | 524 |
590 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral( | 525 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral( |
591 Handle<FixedArray> constant_elements, int literal_index, int flags) { | 526 Handle<FixedArray> constant_elements, int literal_index, int flags) { |
592 DCHECK(FitsInImm8Operand(flags)); // Flags should fit in 8 bits. | |
593 size_t constant_elements_entry = GetConstantPoolEntry(constant_elements); | 527 size_t constant_elements_entry = GetConstantPoolEntry(constant_elements); |
594 if (FitsInIdx8Operand(literal_index) && | 528 int operand_scale = OperandScale( |
595 FitsInIdx8Operand(constant_elements_entry)) { | 529 SizeForUnsignedOperand(constant_elements_entry), |
596 Output(Bytecode::kCreateArrayLiteral, | 530 SizeForUnsignedOperand(literal_index), SizeForUnsignedOperand(flags)); |
597 static_cast<uint8_t>(constant_elements_entry), | 531 OutputScaled(Bytecode::kCreateArrayLiteral, operand_scale, |
598 static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags)); | 532 UnsignedOperand(constant_elements_entry), |
599 } else if (FitsInIdx16Operand(literal_index) && | 533 UnsignedOperand(literal_index), UnsignedOperand(flags)); |
600 FitsInIdx16Operand(constant_elements_entry)) { | |
601 Output(Bytecode::kCreateArrayLiteralWide, | |
602 static_cast<uint16_t>(constant_elements_entry), | |
603 static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags)); | |
604 } else { | |
605 UNIMPLEMENTED(); | |
606 } | |
607 return *this; | 534 return *this; |
608 } | 535 } |
609 | 536 |
610 | 537 |
611 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral( | 538 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral( |
612 Handle<FixedArray> constant_properties, int literal_index, int flags) { | 539 Handle<FixedArray> constant_properties, int literal_index, int flags) { |
613 DCHECK(FitsInImm8Operand(flags)); // Flags should fit in 8 bits. | |
614 size_t constant_properties_entry = GetConstantPoolEntry(constant_properties); | 540 size_t constant_properties_entry = GetConstantPoolEntry(constant_properties); |
615 if (FitsInIdx8Operand(literal_index) && | 541 int operand_scale = OperandScale( |
616 FitsInIdx8Operand(constant_properties_entry)) { | 542 SizeForUnsignedOperand(constant_properties_entry), |
617 Output(Bytecode::kCreateObjectLiteral, | 543 SizeForUnsignedOperand(literal_index), SizeForUnsignedOperand(flags)); |
618 static_cast<uint8_t>(constant_properties_entry), | 544 OutputScaled(Bytecode::kCreateObjectLiteral, operand_scale, |
619 static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags)); | 545 UnsignedOperand(constant_properties_entry), |
620 } else if (FitsInIdx16Operand(literal_index) && | 546 UnsignedOperand(literal_index), UnsignedOperand(flags)); |
621 FitsInIdx16Operand(constant_properties_entry)) { | |
622 Output(Bytecode::kCreateObjectLiteralWide, | |
623 static_cast<uint16_t>(constant_properties_entry), | |
624 static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags)); | |
625 } else { | |
626 UNIMPLEMENTED(); | |
627 } | |
628 return *this; | 547 return *this; |
629 } | 548 } |
630 | 549 |
631 | 550 |
632 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { | 551 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { |
633 Output(Bytecode::kPushContext, context.ToRawOperand()); | 552 int operand_scale = OperandScale(SizeForRegisterOperand(context)); |
| 553 OutputScaled(Bytecode::kPushContext, operand_scale, context.ToRawOperand()); |
634 return *this; | 554 return *this; |
635 } | 555 } |
636 | 556 |
637 | 557 |
638 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { | 558 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { |
639 Output(Bytecode::kPopContext, context.ToRawOperand()); | 559 int operand_scale = OperandScale(SizeForRegisterOperand(context)); |
| 560 OutputScaled(Bytecode::kPopContext, operand_scale, context.ToRawOperand()); |
640 return *this; | 561 return *this; |
641 } | 562 } |
642 | 563 |
643 | 564 |
644 bool BytecodeArrayBuilder::NeedToBooleanCast() { | 565 bool BytecodeArrayBuilder::NeedToBooleanCast() { |
645 if (!LastBytecodeInSameBlock()) { | 566 if (!LastBytecodeInSameBlock()) { |
646 return true; | 567 return true; |
647 } | 568 } |
648 PreviousBytecodeHelper previous_bytecode(*this); | 569 PreviousBytecodeHelper previous_bytecode(*this); |
649 switch (previous_bytecode.GetBytecode()) { | 570 switch (previous_bytecode.GetBytecode()) { |
(...skipping 24 matching lines...) Expand all Loading... |
674 } | 595 } |
675 | 596 |
676 | 597 |
677 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { | 598 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { |
678 if (LastBytecodeInSameBlock()) { | 599 if (LastBytecodeInSameBlock()) { |
679 PreviousBytecodeHelper previous_bytecode(*this); | 600 PreviousBytecodeHelper previous_bytecode(*this); |
680 switch (previous_bytecode.GetBytecode()) { | 601 switch (previous_bytecode.GetBytecode()) { |
681 case Bytecode::kToName: | 602 case Bytecode::kToName: |
682 case Bytecode::kTypeOf: | 603 case Bytecode::kTypeOf: |
683 return *this; | 604 return *this; |
684 case Bytecode::kLdaConstantWide: | |
685 case Bytecode::kLdaConstant: { | 605 case Bytecode::kLdaConstant: { |
686 Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0); | 606 Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0); |
687 if (object->IsName()) return *this; | 607 if (object->IsName()) return *this; |
688 break; | 608 break; |
689 } | 609 } |
690 default: | 610 default: |
691 break; | 611 break; |
692 } | 612 } |
693 } | 613 } |
694 Output(Bytecode::kToName); | 614 Output(Bytecode::kToName); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 case Bytecode::kJumpIfNull: | 667 case Bytecode::kJumpIfNull: |
748 return Bytecode::kJumpIfNullConstant; | 668 return Bytecode::kJumpIfNullConstant; |
749 case Bytecode::kJumpIfUndefined: | 669 case Bytecode::kJumpIfUndefined: |
750 return Bytecode::kJumpIfUndefinedConstant; | 670 return Bytecode::kJumpIfUndefinedConstant; |
751 default: | 671 default: |
752 UNREACHABLE(); | 672 UNREACHABLE(); |
753 return static_cast<Bytecode>(-1); | 673 return static_cast<Bytecode>(-1); |
754 } | 674 } |
755 } | 675 } |
756 | 676 |
757 | |
758 // static | |
759 Bytecode BytecodeArrayBuilder::GetJumpWithConstantWideOperand( | |
760 Bytecode jump_bytecode) { | |
761 switch (jump_bytecode) { | |
762 case Bytecode::kJump: | |
763 return Bytecode::kJumpConstantWide; | |
764 case Bytecode::kJumpIfTrue: | |
765 return Bytecode::kJumpIfTrueConstantWide; | |
766 case Bytecode::kJumpIfFalse: | |
767 return Bytecode::kJumpIfFalseConstantWide; | |
768 case Bytecode::kJumpIfToBooleanTrue: | |
769 return Bytecode::kJumpIfToBooleanTrueConstantWide; | |
770 case Bytecode::kJumpIfToBooleanFalse: | |
771 return Bytecode::kJumpIfToBooleanFalseConstantWide; | |
772 case Bytecode::kJumpIfNotHole: | |
773 return Bytecode::kJumpIfNotHoleConstantWide; | |
774 case Bytecode::kJumpIfNull: | |
775 return Bytecode::kJumpIfNullConstantWide; | |
776 case Bytecode::kJumpIfUndefined: | |
777 return Bytecode::kJumpIfUndefinedConstantWide; | |
778 default: | |
779 UNREACHABLE(); | |
780 return static_cast<Bytecode>(-1); | |
781 } | |
782 } | |
783 | |
784 | |
785 // static | 677 // static |
786 Bytecode BytecodeArrayBuilder::GetJumpWithToBoolean(Bytecode jump_bytecode) { | 678 Bytecode BytecodeArrayBuilder::GetJumpWithToBoolean(Bytecode jump_bytecode) { |
787 switch (jump_bytecode) { | 679 switch (jump_bytecode) { |
788 case Bytecode::kJump: | 680 case Bytecode::kJump: |
789 case Bytecode::kJumpIfNull: | 681 case Bytecode::kJumpIfNull: |
790 case Bytecode::kJumpIfUndefined: | 682 case Bytecode::kJumpIfUndefined: |
791 case Bytecode::kJumpIfNotHole: | 683 case Bytecode::kJumpIfNotHole: |
792 return jump_bytecode; | 684 return jump_bytecode; |
793 case Bytecode::kJumpIfTrue: | 685 case Bytecode::kJumpIfTrue: |
794 return Bytecode::kJumpIfToBooleanTrue; | 686 return Bytecode::kJumpIfToBooleanTrue; |
795 case Bytecode::kJumpIfFalse: | 687 case Bytecode::kJumpIfFalse: |
796 return Bytecode::kJumpIfToBooleanFalse; | 688 return Bytecode::kJumpIfToBooleanFalse; |
797 default: | 689 default: |
798 UNREACHABLE(); | 690 UNREACHABLE(); |
799 } | 691 } |
800 return static_cast<Bytecode>(-1); | 692 return static_cast<Bytecode>(-1); |
801 } | 693 } |
802 | 694 |
803 | 695 |
804 void BytecodeArrayBuilder::PatchIndirectJumpWith8BitOperand( | 696 void BytecodeArrayBuilder::PatchIndirectJumpWith8BitOperand( |
805 const ZoneVector<uint8_t>::iterator& jump_location, int delta) { | 697 const ZoneVector<uint8_t>::iterator& jump_location, int delta) { |
806 Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); | 698 Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); |
807 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); | 699 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); |
808 ZoneVector<uint8_t>::iterator operand_location = jump_location + 1; | 700 ZoneVector<uint8_t>::iterator operand_location = jump_location + 1; |
809 DCHECK_EQ(*operand_location, 0); | 701 DCHECK_EQ(*operand_location, 0); |
810 if (FitsInImm8Operand(delta)) { | 702 if (SizeForSignedOperand(delta) == OperandSize::kByte) { |
811 // The jump fits within the range of an Imm8 operand, so cancel | 703 // The jump fits within the range of an Imm operand, so cancel |
812 // the reservation and jump directly. | 704 // the reservation and jump directly. |
813 constant_array_builder()->DiscardReservedEntry(OperandSize::kByte); | 705 constant_array_builder()->DiscardReservedEntry(OperandSize::kByte); |
814 *operand_location = static_cast<uint8_t>(delta); | 706 *operand_location = static_cast<uint8_t>(delta); |
815 } else { | 707 } else { |
816 // The jump does not fit within the range of an Imm8 operand, so | 708 // The jump does not fit within the range of an Imm operand, so |
817 // commit reservation putting the offset into the constant pool, | 709 // commit reservation putting the offset into the constant pool, |
818 // and update the jump instruction and operand. | 710 // and update the jump instruction and operand. |
819 size_t entry = constant_array_builder()->CommitReservedEntry( | 711 size_t entry = constant_array_builder()->CommitReservedEntry( |
820 OperandSize::kByte, handle(Smi::FromInt(delta), isolate())); | 712 OperandSize::kByte, handle(Smi::FromInt(delta), isolate())); |
821 DCHECK(FitsInIdx8Operand(entry)); | 713 DCHECK(SizeForUnsignedOperand(entry) == OperandSize::kByte); |
822 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); | 714 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); |
823 *jump_location = Bytecodes::ToByte(jump_bytecode); | 715 *jump_location = Bytecodes::ToByte(jump_bytecode); |
824 *operand_location = static_cast<uint8_t>(entry); | 716 *operand_location = static_cast<uint8_t>(entry); |
825 } | 717 } |
826 } | 718 } |
827 | 719 |
828 | |
829 void BytecodeArrayBuilder::PatchIndirectJumpWith16BitOperand( | 720 void BytecodeArrayBuilder::PatchIndirectJumpWith16BitOperand( |
830 const ZoneVector<uint8_t>::iterator& jump_location, int delta) { | 721 const ZoneVector<uint8_t>::iterator& jump_location, int delta) { |
831 DCHECK(Bytecodes::IsJumpConstantWide(Bytecodes::FromByte(*jump_location))); | 722 Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); |
| 723 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); |
832 ZoneVector<uint8_t>::iterator operand_location = jump_location + 1; | 724 ZoneVector<uint8_t>::iterator operand_location = jump_location + 1; |
833 size_t entry = constant_array_builder()->CommitReservedEntry( | |
834 OperandSize::kShort, handle(Smi::FromInt(delta), isolate())); | |
835 DCHECK(FitsInIdx16Operand(entry)); | |
836 uint8_t operand_bytes[2]; | 725 uint8_t operand_bytes[2]; |
837 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry)); | 726 if (SizeForSignedOperand(delta) <= OperandSize::kShort) { |
| 727 constant_array_builder()->DiscardReservedEntry(OperandSize::kShort); |
| 728 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(delta)); |
| 729 } else { |
| 730 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); |
| 731 *jump_location = Bytecodes::ToByte(jump_bytecode); |
| 732 size_t entry = constant_array_builder()->CommitReservedEntry( |
| 733 OperandSize::kShort, handle(Smi::FromInt(delta), isolate())); |
| 734 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry)); |
| 735 } |
838 DCHECK(*operand_location == 0 && *(operand_location + 1) == 0); | 736 DCHECK(*operand_location == 0 && *(operand_location + 1) == 0); |
839 *operand_location++ = operand_bytes[0]; | 737 *operand_location++ = operand_bytes[0]; |
840 *operand_location = operand_bytes[1]; | 738 *operand_location = operand_bytes[1]; |
841 } | 739 } |
842 | 740 |
| 741 void BytecodeArrayBuilder::PatchIndirectJumpWith32BitOperand( |
| 742 const ZoneVector<uint8_t>::iterator& jump_location, int delta) { |
| 743 DCHECK(Bytecodes::IsJumpImmediate(Bytecodes::FromByte(*jump_location))); |
| 744 constant_array_builder()->DiscardReservedEntry(OperandSize::kQuad); |
| 745 ZoneVector<uint8_t>::iterator operand_location = jump_location + 1; |
| 746 uint8_t operand_bytes[4]; |
| 747 WriteUnalignedUInt32(operand_bytes, static_cast<uint32_t>(delta)); |
| 748 DCHECK(*operand_location == 0 && *(operand_location + 1) == 0 && |
| 749 *(operand_location + 2) == 0 && *(operand_location + 3) == 0); |
| 750 *operand_location++ = operand_bytes[0]; |
| 751 *operand_location++ = operand_bytes[1]; |
| 752 *operand_location++ = operand_bytes[2]; |
| 753 *operand_location = operand_bytes[3]; |
| 754 } |
843 | 755 |
844 void BytecodeArrayBuilder::PatchJump( | 756 void BytecodeArrayBuilder::PatchJump( |
845 const ZoneVector<uint8_t>::iterator& jump_target, | 757 const ZoneVector<uint8_t>::iterator& jump_target, |
846 const ZoneVector<uint8_t>::iterator& jump_location) { | 758 const ZoneVector<uint8_t>::iterator& jump_location) { |
| 759 int delta = static_cast<int>(jump_target - jump_location); |
847 Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); | 760 Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); |
848 int delta = static_cast<int>(jump_target - jump_location); | 761 int operand_scale = Bytecodes::GetPrefixBytecodeScale(jump_bytecode); |
| 762 int prefix_offset = 0; |
| 763 if (operand_scale > 1) { |
| 764 delta -= 1; |
| 765 prefix_offset = 1; |
| 766 jump_bytecode = Bytecodes::FromByte(*(jump_location + prefix_offset)); |
| 767 } |
| 768 |
849 DCHECK(Bytecodes::IsJump(jump_bytecode)); | 769 DCHECK(Bytecodes::IsJump(jump_bytecode)); |
850 switch (Bytecodes::GetOperandSize(jump_bytecode, 0)) { | 770 switch (operand_scale) { |
851 case OperandSize::kByte: | 771 case 1: |
852 PatchIndirectJumpWith8BitOperand(jump_location, delta); | 772 PatchIndirectJumpWith8BitOperand(jump_location, delta); |
853 break; | 773 break; |
854 case OperandSize::kShort: | 774 case 2: |
855 PatchIndirectJumpWith16BitOperand(jump_location, delta); | 775 PatchIndirectJumpWith16BitOperand(jump_location + prefix_offset, delta); |
856 break; | 776 break; |
857 case OperandSize::kNone: | 777 case 4: |
| 778 PatchIndirectJumpWith32BitOperand(jump_location + prefix_offset, delta); |
| 779 break; |
| 780 default: |
858 UNREACHABLE(); | 781 UNREACHABLE(); |
859 } | 782 } |
860 unbound_jumps_--; | 783 unbound_jumps_--; |
861 } | 784 } |
862 | 785 |
863 | 786 |
864 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, | 787 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, |
865 BytecodeLabel* label) { | 788 BytecodeLabel* label) { |
866 // Don't emit dead code. | 789 // Don't emit dead code. |
867 if (exit_seen_in_block_) return *this; | 790 if (exit_seen_in_block_) return *this; |
868 | 791 |
869 // Check if the value in accumulator is boolean, if not choose an | 792 // Check if the value in accumulator is boolean, if not choose an |
870 // appropriate JumpIfToBoolean bytecode. | 793 // appropriate JumpIfToBoolean bytecode. |
871 if (NeedToBooleanCast()) { | 794 if (NeedToBooleanCast()) { |
872 jump_bytecode = GetJumpWithToBoolean(jump_bytecode); | 795 jump_bytecode = GetJumpWithToBoolean(jump_bytecode); |
873 } | 796 } |
874 | 797 |
875 if (label->is_bound()) { | 798 if (label->is_bound()) { |
876 // Label has been bound already so this is a backwards jump. | 799 // Label has been bound already so this is a backwards jump. |
877 CHECK_GE(bytecodes()->size(), label->offset()); | 800 CHECK_GE(bytecodes()->size(), label->offset()); |
878 CHECK_LE(bytecodes()->size(), static_cast<size_t>(kMaxInt)); | 801 CHECK_LE(bytecodes()->size(), static_cast<size_t>(kMaxInt)); |
879 size_t abs_delta = bytecodes()->size() - label->offset(); | 802 size_t abs_delta = bytecodes()->size() - label->offset(); |
880 int delta = -static_cast<int>(abs_delta); | 803 int delta = -static_cast<int>(abs_delta); |
881 | 804 OperandSize operand_size = SizeForSignedOperand(delta); |
882 if (FitsInImm8Operand(delta)) { | 805 if (operand_size > OperandSize::kByte) { |
883 Output(jump_bytecode, static_cast<uint8_t>(delta)); | 806 // Adjust for scaling byte prefix for wide jump offset. |
884 } else { | 807 DCHECK_LE(delta, 0); |
885 size_t entry = | 808 delta -= 1; |
886 GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); | |
887 if (FitsInIdx8Operand(entry)) { | |
888 Output(GetJumpWithConstantOperand(jump_bytecode), | |
889 static_cast<uint8_t>(entry)); | |
890 } else if (FitsInIdx16Operand(entry)) { | |
891 Output(GetJumpWithConstantWideOperand(jump_bytecode), | |
892 static_cast<uint16_t>(entry)); | |
893 } else { | |
894 UNREACHABLE(); | |
895 } | |
896 } | 809 } |
| 810 OutputScaled(jump_bytecode, static_cast<int>(operand_size), |
| 811 SignedOperand(delta, operand_size)); |
897 } else { | 812 } else { |
898 // The label has not yet been bound so this is a forward reference | 813 // The label has not yet been bound so this is a forward reference |
899 // that will be patched when the label is bound. We create a | 814 // that will be patched when the label is bound. We create a |
900 // reservation in the constant pool so the jump can be patched | 815 // reservation in the constant pool so the jump can be patched |
901 // when the label is bound. The reservation means the maximum size | 816 // when the label is bound. The reservation means the maximum size |
902 // of the operand for the constant is known and the jump can | 817 // of the operand for the constant is known and the jump can |
903 // be emitted into the bytecode stream with space for the operand. | 818 // be emitted into the bytecode stream with space for the operand. |
904 label->set_referrer(bytecodes()->size()); | 819 label->set_referrer(bytecodes()->size()); |
905 unbound_jumps_++; | 820 unbound_jumps_++; |
906 OperandSize reserved_operand_size = | 821 OperandSize reserved_operand_size = |
907 constant_array_builder()->CreateReservedEntry(); | 822 constant_array_builder()->CreateReservedEntry(); |
908 switch (reserved_operand_size) { | 823 OutputScaled(jump_bytecode, static_cast<int>(reserved_operand_size), 0); |
909 case OperandSize::kByte: | |
910 Output(jump_bytecode, 0); | |
911 break; | |
912 case OperandSize::kShort: | |
913 Output(GetJumpWithConstantWideOperand(jump_bytecode), 0); | |
914 break; | |
915 case OperandSize::kNone: | |
916 UNREACHABLE(); | |
917 } | |
918 } | 824 } |
919 LeaveBasicBlock(); | 825 LeaveBasicBlock(); |
920 return *this; | 826 return *this; |
921 } | 827 } |
922 | 828 |
923 | 829 |
924 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { | 830 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { |
925 return OutputJump(Bytecode::kJump, label); | 831 return OutputJump(Bytecode::kJump, label); |
926 } | 832 } |
927 | 833 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
977 return *this; | 883 return *this; |
978 } | 884 } |
979 | 885 |
980 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { | 886 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { |
981 Output(Bytecode::kDebugger); | 887 Output(Bytecode::kDebugger); |
982 return *this; | 888 return *this; |
983 } | 889 } |
984 | 890 |
985 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( | 891 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( |
986 Register cache_info_triple) { | 892 Register cache_info_triple) { |
987 if (FitsInReg8Operand(cache_info_triple)) { | 893 int operand_scale = OperandScale(SizeForRegisterOperand(cache_info_triple)); |
988 Output(Bytecode::kForInPrepare, cache_info_triple.ToRawOperand()); | 894 OutputScaled(Bytecode::kForInPrepare, operand_scale, |
989 } else if (FitsInReg16Operand(cache_info_triple)) { | 895 cache_info_triple.ToRawOperand()); |
990 Output(Bytecode::kForInPrepareWide, cache_info_triple.ToRawOperand()); | |
991 } else { | |
992 UNIMPLEMENTED(); | |
993 } | |
994 return *this; | 896 return *this; |
995 } | 897 } |
996 | 898 |
997 | |
998 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index, | 899 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index, |
999 Register cache_length) { | 900 Register cache_length) { |
1000 Output(Bytecode::kForInDone, index.ToRawOperand(), | 901 int operand_scale = OperandScale(SizeForRegisterOperand(index), |
1001 cache_length.ToRawOperand()); | 902 SizeForRegisterOperand(cache_length)); |
| 903 OutputScaled(Bytecode::kForInDone, operand_scale, index.ToRawOperand(), |
| 904 cache_length.ToRawOperand()); |
1002 return *this; | 905 return *this; |
1003 } | 906 } |
1004 | 907 |
1005 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( | 908 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( |
1006 Register receiver, Register index, Register cache_type_array_pair, | 909 Register receiver, Register index, Register cache_type_array_pair, |
1007 int feedback_slot) { | 910 int feedback_slot) { |
1008 if (FitsInReg8Operand(receiver) && FitsInReg8Operand(index) && | 911 int operand_scale = OperandScale( |
1009 FitsInReg8Operand(cache_type_array_pair) && | 912 SizeForRegisterOperand(receiver), SizeForRegisterOperand(index), |
1010 FitsInIdx8Operand(feedback_slot)) { | 913 SizeForRegisterOperand(cache_type_array_pair), |
1011 Output(Bytecode::kForInNext, receiver.ToRawOperand(), index.ToRawOperand(), | 914 SizeForUnsignedOperand(feedback_slot)); |
1012 cache_type_array_pair.ToRawOperand(), | 915 OutputScaled(Bytecode::kForInNext, operand_scale, receiver.ToRawOperand(), |
1013 static_cast<uint8_t>(feedback_slot)); | 916 index.ToRawOperand(), cache_type_array_pair.ToRawOperand(), |
1014 } else if (FitsInReg16Operand(receiver) && FitsInReg16Operand(index) && | 917 UnsignedOperand(feedback_slot)); |
1015 FitsInReg16Operand(cache_type_array_pair) && | |
1016 FitsInIdx16Operand(feedback_slot)) { | |
1017 Output(Bytecode::kForInNextWide, receiver.ToRawOperand(), | |
1018 index.ToRawOperand(), cache_type_array_pair.ToRawOperand(), | |
1019 static_cast<uint16_t>(feedback_slot)); | |
1020 } else { | |
1021 UNIMPLEMENTED(); | |
1022 } | |
1023 return *this; | 918 return *this; |
1024 } | 919 } |
1025 | 920 |
1026 | 921 |
1027 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { | 922 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { |
1028 Output(Bytecode::kForInStep, index.ToRawOperand()); | 923 int operand_scale = OperandScale(SizeForRegisterOperand(index)); |
| 924 OutputScaled(Bytecode::kForInStep, operand_scale, index.ToRawOperand()); |
1029 return *this; | 925 return *this; |
1030 } | 926 } |
1031 | 927 |
1032 | 928 |
1033 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(int handler_id, | 929 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(int handler_id, |
1034 bool will_catch) { | 930 bool will_catch) { |
1035 handler_table_builder()->SetHandlerTarget(handler_id, bytecodes()->size()); | 931 handler_table_builder()->SetHandlerTarget(handler_id, bytecodes()->size()); |
1036 handler_table_builder()->SetPrediction(handler_id, will_catch); | 932 handler_table_builder()->SetPrediction(handler_id, will_catch); |
1037 return *this; | 933 return *this; |
1038 } | 934 } |
(...skipping 25 matching lines...) Expand all Loading... |
1064 } | 960 } |
1065 DCHECK(exit_seen_in_block_); | 961 DCHECK(exit_seen_in_block_); |
1066 } | 962 } |
1067 | 963 |
1068 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 964 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
1069 Register receiver_args, | 965 Register receiver_args, |
1070 size_t receiver_args_count, | 966 size_t receiver_args_count, |
1071 int feedback_slot, | 967 int feedback_slot, |
1072 TailCallMode tail_call_mode) { | 968 TailCallMode tail_call_mode) { |
1073 Bytecode bytecode = BytecodeForCall(tail_call_mode); | 969 Bytecode bytecode = BytecodeForCall(tail_call_mode); |
1074 if (FitsInReg8Operand(callable) && FitsInReg8Operand(receiver_args) && | 970 int operand_scale = OperandScale(SizeForRegisterOperand(callable), |
1075 FitsInIdx8Operand(receiver_args_count) && | 971 SizeForRegisterOperand(receiver_args), |
1076 FitsInIdx8Operand(feedback_slot)) { | 972 SizeForUnsignedOperand(receiver_args_count), |
1077 Output(bytecode, callable.ToRawOperand(), receiver_args.ToRawOperand(), | 973 SizeForUnsignedOperand(feedback_slot)); |
1078 static_cast<uint8_t>(receiver_args_count), | 974 OutputScaled(bytecode, operand_scale, callable.ToRawOperand(), |
1079 static_cast<uint8_t>(feedback_slot)); | 975 receiver_args.ToRawOperand(), |
1080 } else if (FitsInReg16Operand(callable) && | 976 UnsignedOperand(receiver_args_count), |
1081 FitsInReg16Operand(receiver_args) && | 977 UnsignedOperand(feedback_slot)); |
1082 FitsInIdx16Operand(receiver_args_count) && | |
1083 FitsInIdx16Operand(feedback_slot)) { | |
1084 bytecode = BytecodeForWideOperands(bytecode); | |
1085 Output(bytecode, callable.ToRawOperand(), receiver_args.ToRawOperand(), | |
1086 static_cast<uint16_t>(receiver_args_count), | |
1087 static_cast<uint16_t>(feedback_slot)); | |
1088 } else { | |
1089 UNIMPLEMENTED(); | |
1090 } | |
1091 return *this; | 978 return *this; |
1092 } | 979 } |
1093 | 980 |
1094 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 981 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
1095 Register first_arg, | 982 Register first_arg, |
1096 size_t arg_count) { | 983 size_t arg_count) { |
1097 if (!first_arg.is_valid()) { | 984 if (!first_arg.is_valid()) { |
1098 DCHECK_EQ(0u, arg_count); | 985 DCHECK_EQ(0u, arg_count); |
1099 first_arg = Register(0); | 986 first_arg = Register(0); |
1100 } | 987 } |
1101 if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) && | 988 int operand_scale = OperandScale(SizeForRegisterOperand(constructor), |
1102 FitsInIdx8Operand(arg_count)) { | 989 SizeForRegisterOperand(first_arg), |
1103 Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(), | 990 SizeForUnsignedOperand(arg_count)); |
1104 static_cast<uint8_t>(arg_count)); | 991 OutputScaled(Bytecode::kNew, operand_scale, constructor.ToRawOperand(), |
1105 } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) && | 992 first_arg.ToRawOperand(), UnsignedOperand(arg_count)); |
1106 FitsInIdx16Operand(arg_count)) { | |
1107 Output(Bytecode::kNewWide, constructor.ToRawOperand(), | |
1108 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); | |
1109 } else { | |
1110 UNIMPLEMENTED(); | |
1111 } | |
1112 return *this; | 993 return *this; |
1113 } | 994 } |
1114 | 995 |
1115 | 996 |
1116 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( | 997 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
1117 Runtime::FunctionId function_id, Register first_arg, size_t arg_count) { | 998 Runtime::FunctionId function_id, Register first_arg, size_t arg_count) { |
1118 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); | 999 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); |
1119 DCHECK(FitsInIdx16Operand(function_id)); | 1000 DCHECK(SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
1120 if (!first_arg.is_valid()) { | 1001 if (!first_arg.is_valid()) { |
1121 DCHECK_EQ(0u, arg_count); | 1002 DCHECK_EQ(0u, arg_count); |
1122 first_arg = Register(0); | 1003 first_arg = Register(0); |
1123 } | 1004 } |
1124 if (FitsInReg8Operand(first_arg) && FitsInIdx8Operand(arg_count)) { | 1005 int operand_scale = OperandScale(SizeForRegisterOperand(first_arg), |
1125 Output(Bytecode::kCallRuntime, static_cast<uint16_t>(function_id), | 1006 SizeForUnsignedOperand(arg_count)); |
1126 first_arg.ToRawOperand(), static_cast<uint8_t>(arg_count)); | 1007 OutputScaled(Bytecode::kCallRuntime, operand_scale, |
1127 } else if (FitsInReg16Operand(first_arg) && FitsInIdx16Operand(arg_count)) { | 1008 static_cast<uint16_t>(function_id), first_arg.ToRawOperand(), |
1128 Output(Bytecode::kCallRuntimeWide, static_cast<uint16_t>(function_id), | 1009 UnsignedOperand(arg_count)); |
1129 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); | |
1130 } else { | |
1131 UNIMPLEMENTED(); | |
1132 } | |
1133 return *this; | 1010 return *this; |
1134 } | 1011 } |
1135 | 1012 |
1136 | 1013 |
1137 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( | 1014 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
1138 Runtime::FunctionId function_id, Register first_arg, size_t arg_count, | 1015 Runtime::FunctionId function_id, Register first_arg, size_t arg_count, |
1139 Register first_return) { | 1016 Register first_return) { |
1140 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); | 1017 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); |
1141 DCHECK(FitsInIdx16Operand(function_id)); | 1018 DCHECK(SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
1142 if (!first_arg.is_valid()) { | 1019 if (!first_arg.is_valid()) { |
1143 DCHECK_EQ(0u, arg_count); | 1020 DCHECK_EQ(0u, arg_count); |
1144 first_arg = Register(0); | 1021 first_arg = Register(0); |
1145 } | 1022 } |
1146 if (FitsInReg8Operand(first_arg) && FitsInIdx8Operand(arg_count) && | 1023 int operand_scale = OperandScale(SizeForRegisterOperand(first_arg), |
1147 FitsInReg8Operand(first_return)) { | 1024 SizeForUnsignedOperand(arg_count), |
1148 Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id), | 1025 SizeForRegisterOperand(first_return)); |
1149 first_arg.ToRawOperand(), static_cast<uint8_t>(arg_count), | 1026 OutputScaled(Bytecode::kCallRuntimeForPair, operand_scale, |
1150 first_return.ToRawOperand()); | 1027 static_cast<uint16_t>(function_id), first_arg.ToRawOperand(), |
1151 } else if (FitsInReg16Operand(first_arg) && FitsInIdx16Operand(arg_count) && | 1028 UnsignedOperand(arg_count), first_return.ToRawOperand()); |
1152 FitsInReg16Operand(first_return)) { | |
1153 Output(Bytecode::kCallRuntimeForPairWide, | |
1154 static_cast<uint16_t>(function_id), first_arg.ToRawOperand(), | |
1155 static_cast<uint16_t>(arg_count), first_return.ToRawOperand()); | |
1156 } else { | |
1157 UNIMPLEMENTED(); | |
1158 } | |
1159 return *this; | 1029 return *this; |
1160 } | 1030 } |
1161 | 1031 |
1162 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( | 1032 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( |
1163 int context_index, Register receiver_args, size_t receiver_args_count) { | 1033 int context_index, Register receiver_args, size_t receiver_args_count) { |
1164 DCHECK(FitsInIdx16Operand(context_index)); | 1034 int operand_scale = OperandScale(SizeForUnsignedOperand(context_index), |
1165 if (FitsInReg8Operand(receiver_args) && | 1035 SizeForRegisterOperand(receiver_args), |
1166 FitsInIdx8Operand(receiver_args_count)) { | 1036 SizeForUnsignedOperand(receiver_args_count)); |
1167 Output(Bytecode::kCallJSRuntime, static_cast<uint16_t>(context_index), | 1037 OutputScaled(Bytecode::kCallJSRuntime, operand_scale, |
1168 receiver_args.ToRawOperand(), | 1038 UnsignedOperand(context_index), receiver_args.ToRawOperand(), |
1169 static_cast<uint8_t>(receiver_args_count)); | 1039 UnsignedOperand(receiver_args_count)); |
1170 } else if (FitsInReg16Operand(receiver_args) && | |
1171 FitsInIdx16Operand(receiver_args_count)) { | |
1172 Output(Bytecode::kCallJSRuntimeWide, static_cast<uint16_t>(context_index), | |
1173 receiver_args.ToRawOperand(), | |
1174 static_cast<uint16_t>(receiver_args_count)); | |
1175 } else { | |
1176 UNIMPLEMENTED(); | |
1177 } | |
1178 return *this; | 1040 return *this; |
1179 } | 1041 } |
1180 | 1042 |
1181 | 1043 |
1182 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, | 1044 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
1183 LanguageMode language_mode) { | 1045 LanguageMode language_mode) { |
1184 Output(BytecodeForDelete(language_mode), object.ToRawOperand()); | 1046 int operand_scale = OperandScale(SizeForRegisterOperand(object)); |
| 1047 OutputScaled(BytecodeForDelete(language_mode), operand_scale, |
| 1048 object.ToRawOperand()); |
1185 return *this; | 1049 return *this; |
1186 } | 1050 } |
1187 | 1051 |
1188 | 1052 |
1189 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 1053 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
1190 return constant_array_builder()->Insert(object); | 1054 return constant_array_builder()->Insert(object); |
1191 } | 1055 } |
1192 | 1056 |
1193 void BytecodeArrayBuilder::SetReturnPosition() { | 1057 void BytecodeArrayBuilder::SetReturnPosition() { |
1194 if (return_position_ == RelocInfo::kNoPosition) return; | 1058 if (return_position_ == RelocInfo::kNoPosition) return; |
(...skipping 21 matching lines...) Expand all Loading... |
1216 if (exit_seen_in_block_) return; | 1080 if (exit_seen_in_block_) return; |
1217 source_position_table_builder_.AddStatementPosition(bytecodes_.size(), | 1081 source_position_table_builder_.AddStatementPosition(bytecodes_.size(), |
1218 expr->position()); | 1082 expr->position()); |
1219 } | 1083 } |
1220 | 1084 |
1221 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { | 1085 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { |
1222 return temporary_register_allocator()->RegisterIsLive(reg); | 1086 return temporary_register_allocator()->RegisterIsLive(reg); |
1223 } | 1087 } |
1224 | 1088 |
1225 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, | 1089 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, |
| 1090 int operand_scale, |
1226 uint32_t operand_value) const { | 1091 uint32_t operand_value) const { |
| 1092 OperandSize operand_size = |
| 1093 Bytecodes::GetOperandSize(bytecode, operand_index, operand_scale); |
1227 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); | 1094 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); |
1228 switch (operand_type) { | 1095 switch (operand_type) { |
1229 case OperandType::kNone: | 1096 case OperandType::kNone: |
1230 return false; | 1097 return false; |
1231 case OperandType::kRegCount16: { | 1098 case OperandType::kRegCount: { |
1232 // Expect kRegCount16 is part of a range previous operand is a | |
1233 // valid operand to start a range. | |
1234 if (operand_index > 0) { | 1099 if (operand_index > 0) { |
1235 OperandType previous_operand_type = | 1100 OperandType previous_operand_type = |
1236 Bytecodes::GetOperandType(bytecode, operand_index - 1); | 1101 Bytecodes::GetOperandType(bytecode, operand_index - 1); |
1237 return ((previous_operand_type == OperandType::kMaybeReg16 || | 1102 if (previous_operand_type != OperandType::kMaybeReg && |
1238 previous_operand_type == OperandType::kReg16) && | 1103 previous_operand_type != OperandType::kReg) { |
1239 static_cast<uint16_t>(operand_value) == operand_value); | 1104 return false; |
1240 } else { | 1105 } |
1241 return false; | |
1242 } | 1106 } |
| 1107 } // Fall-through |
| 1108 case OperandType::kFlag8: |
| 1109 case OperandType::kIdx: |
| 1110 case OperandType::kRuntimeId: |
| 1111 case OperandType::kImm: { |
| 1112 size_t unsigned_value = static_cast<size_t>(operand_value); |
| 1113 return SizeForUnsignedOperand(unsigned_value) <= operand_size; |
1243 } | 1114 } |
1244 case OperandType::kRegCount8: { | 1115 case OperandType::kMaybeReg: |
1245 // Expect kRegCount8 is part of a range previous operand is a | |
1246 // valid operand to start a range. | |
1247 if (operand_index > 0) { | |
1248 OperandType previous_operand_type = | |
1249 Bytecodes::GetOperandType(bytecode, operand_index - 1); | |
1250 return ((previous_operand_type == OperandType::kMaybeReg8 || | |
1251 previous_operand_type == OperandType::kReg8 || | |
1252 previous_operand_type == OperandType::kMaybeReg16) && | |
1253 static_cast<uint8_t>(operand_value) == operand_value); | |
1254 } else { | |
1255 return false; | |
1256 } | |
1257 } | |
1258 case OperandType::kIdx16: | |
1259 return static_cast<uint16_t>(operand_value) == operand_value; | |
1260 case OperandType::kImm8: | |
1261 case OperandType::kIdx8: | |
1262 return static_cast<uint8_t>(operand_value) == operand_value; | |
1263 case OperandType::kMaybeReg8: | |
1264 if (operand_value == 0) { | 1116 if (operand_value == 0) { |
1265 return true; | 1117 return true; |
1266 } | 1118 } |
1267 // Fall-through to kReg8 case. | 1119 // Fall-through to kReg case. |
1268 case OperandType::kReg8: | 1120 case OperandType::kReg: |
1269 case OperandType::kRegOut8: | 1121 case OperandType::kRegOut: |
1270 return RegisterIsValid(Register::FromRawOperand(operand_value), | 1122 return RegisterIsValid(Register::FromRawOperand(operand_value), |
1271 operand_type); | 1123 operand_size); |
1272 case OperandType::kRegOutPair8: | 1124 case OperandType::kRegOutPair: |
1273 case OperandType::kRegOutPair16: | 1125 case OperandType::kRegPair: { |
1274 case OperandType::kRegPair8: | |
1275 case OperandType::kRegPair16: { | |
1276 Register reg0 = Register::FromRawOperand(operand_value); | 1126 Register reg0 = Register::FromRawOperand(operand_value); |
1277 Register reg1 = Register(reg0.index() + 1); | 1127 Register reg1 = Register(reg0.index() + 1); |
1278 return RegisterIsValid(reg0, operand_type) && | 1128 // The size of reg1 is imaaterial. |
1279 RegisterIsValid(reg1, operand_type); | 1129 return RegisterIsValid(reg0, operand_size) && |
| 1130 RegisterIsValid(reg1, OperandSize::kQuad); |
1280 } | 1131 } |
1281 case OperandType::kRegOutTriple8: | 1132 case OperandType::kRegOutTriple: { |
1282 case OperandType::kRegOutTriple16: { | |
1283 Register reg0 = Register::FromRawOperand(operand_value); | 1133 Register reg0 = Register::FromRawOperand(operand_value); |
1284 Register reg1 = Register(reg0.index() + 1); | 1134 Register reg1 = Register(reg0.index() + 1); |
1285 Register reg2 = Register(reg0.index() + 2); | 1135 Register reg2 = Register(reg0.index() + 2); |
1286 return RegisterIsValid(reg0, operand_type) && | 1136 // The size of reg1 and reg1 is immaterial. |
1287 RegisterIsValid(reg1, operand_type) && | 1137 return RegisterIsValid(reg0, operand_size) && |
1288 RegisterIsValid(reg2, operand_type); | 1138 RegisterIsValid(reg1, OperandSize::kQuad) && |
1289 } | 1139 RegisterIsValid(reg2, OperandSize::kQuad); |
1290 case OperandType::kMaybeReg16: | |
1291 if (operand_value == 0) { | |
1292 return true; | |
1293 } | |
1294 // Fall-through to kReg16 case. | |
1295 case OperandType::kReg16: | |
1296 case OperandType::kRegOut16: { | |
1297 Register reg = Register::FromRawOperand(operand_value); | |
1298 return RegisterIsValid(reg, operand_type); | |
1299 } | 1140 } |
1300 } | 1141 } |
1301 UNREACHABLE(); | 1142 UNREACHABLE(); |
1302 return false; | 1143 return false; |
1303 } | 1144 } |
1304 | 1145 |
1305 | |
1306 bool BytecodeArrayBuilder::RegisterIsValid(Register reg, | 1146 bool BytecodeArrayBuilder::RegisterIsValid(Register reg, |
1307 OperandType reg_type) const { | 1147 OperandSize reg_size) const { |
1308 if (!reg.is_valid()) { | 1148 if (!reg.is_valid()) { |
1309 return false; | 1149 return false; |
1310 } | 1150 } |
1311 | 1151 |
1312 switch (Bytecodes::SizeOfOperand(reg_type)) { | 1152 if (SizeForRegisterOperand(reg) > reg_size) { |
1313 case OperandSize::kByte: | 1153 return false; |
1314 if (!FitsInReg8OperandUntranslated(reg)) { | |
1315 return false; | |
1316 } | |
1317 break; | |
1318 case OperandSize::kShort: | |
1319 if (!FitsInReg16OperandUntranslated(reg)) { | |
1320 return false; | |
1321 } | |
1322 break; | |
1323 case OperandSize::kNone: | |
1324 UNREACHABLE(); | |
1325 return false; | |
1326 } | 1154 } |
1327 | 1155 |
1328 if (reg.is_current_context() || reg.is_function_closure() || | 1156 if (reg.is_current_context() || reg.is_function_closure() || |
1329 reg.is_new_target()) { | 1157 reg.is_new_target()) { |
1330 return true; | 1158 return true; |
1331 } else if (reg.is_parameter()) { | 1159 } else if (reg.is_parameter()) { |
1332 int parameter_index = reg.ToParameterIndex(parameter_count()); | 1160 int parameter_index = reg.ToParameterIndex(parameter_count()); |
1333 return parameter_index >= 0 && parameter_index < parameter_count(); | 1161 return parameter_index >= 0 && parameter_index < parameter_count(); |
1334 } else if (RegisterTranslator::InTranslationWindow(reg)) { | 1162 } else if (reg.index() < fixed_register_count()) { |
1335 return translation_register_count() > 0; | 1163 return true; |
1336 } else { | 1164 } else { |
1337 reg = RegisterTranslator::UntranslateRegister(reg); | 1165 return TemporaryRegisterIsLive(reg); |
1338 if (reg.index() < fixed_register_count()) { | |
1339 return true; | |
1340 } else { | |
1341 return TemporaryRegisterIsLive(reg); | |
1342 } | |
1343 } | 1166 } |
1344 } | 1167 } |
1345 | 1168 |
1346 | 1169 |
1347 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { | 1170 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { |
1348 return last_bytecode_start_ < bytecodes()->size() && | 1171 return last_bytecode_start_ < bytecodes()->size() && |
1349 last_bytecode_start_ >= last_block_end_; | 1172 last_bytecode_start_ >= last_block_end_; |
1350 } | 1173 } |
1351 | 1174 |
1352 | 1175 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1432 case Token::Value::IN: | 1255 case Token::Value::IN: |
1433 return Bytecode::kTestIn; | 1256 return Bytecode::kTestIn; |
1434 default: | 1257 default: |
1435 UNREACHABLE(); | 1258 UNREACHABLE(); |
1436 return static_cast<Bytecode>(-1); | 1259 return static_cast<Bytecode>(-1); |
1437 } | 1260 } |
1438 } | 1261 } |
1439 | 1262 |
1440 | 1263 |
1441 // static | 1264 // static |
1442 Bytecode BytecodeArrayBuilder::BytecodeForWideOperands(Bytecode bytecode) { | |
1443 switch (bytecode) { | |
1444 case Bytecode::kCall: | |
1445 return Bytecode::kCallWide; | |
1446 case Bytecode::kTailCall: | |
1447 return Bytecode::kTailCallWide; | |
1448 case Bytecode::kLoadIC: | |
1449 return Bytecode::kLoadICWide; | |
1450 case Bytecode::kKeyedLoadIC: | |
1451 return Bytecode::kKeyedLoadICWide; | |
1452 case Bytecode::kStoreICSloppy: | |
1453 return Bytecode::kStoreICSloppyWide; | |
1454 case Bytecode::kStoreICStrict: | |
1455 return Bytecode::kStoreICStrictWide; | |
1456 case Bytecode::kKeyedStoreICSloppy: | |
1457 return Bytecode::kKeyedStoreICSloppyWide; | |
1458 case Bytecode::kKeyedStoreICStrict: | |
1459 return Bytecode::kKeyedStoreICStrictWide; | |
1460 case Bytecode::kLdaGlobal: | |
1461 return Bytecode::kLdaGlobalWide; | |
1462 case Bytecode::kLdaGlobalInsideTypeof: | |
1463 return Bytecode::kLdaGlobalInsideTypeofWide; | |
1464 case Bytecode::kStaGlobalSloppy: | |
1465 return Bytecode::kStaGlobalSloppyWide; | |
1466 case Bytecode::kStaGlobalStrict: | |
1467 return Bytecode::kStaGlobalStrictWide; | |
1468 case Bytecode::kLdaLookupSlot: | |
1469 return Bytecode::kLdaLookupSlotWide; | |
1470 case Bytecode::kLdaLookupSlotInsideTypeof: | |
1471 return Bytecode::kLdaLookupSlotInsideTypeofWide; | |
1472 case Bytecode::kStaLookupSlotStrict: | |
1473 return Bytecode::kStaLookupSlotStrictWide; | |
1474 case Bytecode::kStaLookupSlotSloppy: | |
1475 return Bytecode::kStaLookupSlotSloppyWide; | |
1476 default: | |
1477 UNREACHABLE(); | |
1478 return static_cast<Bytecode>(-1); | |
1479 } | |
1480 } | |
1481 | |
1482 | |
1483 // static | |
1484 Bytecode BytecodeArrayBuilder::BytecodeForStoreIC(LanguageMode language_mode) { | 1265 Bytecode BytecodeArrayBuilder::BytecodeForStoreIC(LanguageMode language_mode) { |
1485 switch (language_mode) { | 1266 switch (language_mode) { |
1486 case SLOPPY: | 1267 case SLOPPY: |
1487 return Bytecode::kStoreICSloppy; | 1268 return Bytecode::kStoreICSloppy; |
1488 case STRICT: | 1269 case STRICT: |
1489 return Bytecode::kStoreICStrict; | 1270 return Bytecode::kStoreICStrict; |
1490 default: | 1271 default: |
1491 UNREACHABLE(); | 1272 UNREACHABLE(); |
1492 } | 1273 } |
1493 return static_cast<Bytecode>(-1); | 1274 return static_cast<Bytecode>(-1); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1581 return Bytecode::kCall; | 1362 return Bytecode::kCall; |
1582 case TailCallMode::kAllow: | 1363 case TailCallMode::kAllow: |
1583 return Bytecode::kTailCall; | 1364 return Bytecode::kTailCall; |
1584 default: | 1365 default: |
1585 UNREACHABLE(); | 1366 UNREACHABLE(); |
1586 } | 1367 } |
1587 return static_cast<Bytecode>(-1); | 1368 return static_cast<Bytecode>(-1); |
1588 } | 1369 } |
1589 | 1370 |
1590 // static | 1371 // static |
1591 bool BytecodeArrayBuilder::FitsInIdx8Operand(int value) { | 1372 OperandSize BytecodeArrayBuilder::SizeForRegisterOperand(Register value) { |
1592 return kMinUInt8 <= value && value <= kMaxUInt8; | 1373 if (value.is_byte_operand()) { |
1593 } | 1374 return OperandSize::kByte; |
1594 | 1375 } else if (value.is_short_operand()) { |
1595 | 1376 return OperandSize::kShort; |
1596 // static | 1377 } else { |
1597 bool BytecodeArrayBuilder::FitsInIdx8Operand(size_t value) { | 1378 return OperandSize::kQuad; |
1598 return value <= static_cast<size_t>(kMaxUInt8); | 1379 } |
1599 } | |
1600 | |
1601 | |
1602 // static | |
1603 bool BytecodeArrayBuilder::FitsInImm8Operand(int value) { | |
1604 return kMinInt8 <= value && value <= kMaxInt8; | |
1605 } | |
1606 | |
1607 | |
1608 // static | |
1609 bool BytecodeArrayBuilder::FitsInIdx16Operand(int value) { | |
1610 return kMinUInt16 <= value && value <= kMaxUInt16; | |
1611 } | |
1612 | |
1613 | |
1614 // static | |
1615 bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) { | |
1616 return value <= static_cast<size_t>(kMaxUInt16); | |
1617 } | |
1618 | |
1619 | |
1620 // static | |
1621 bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) { | |
1622 return RegisterTranslator::FitsInReg8Operand(value); | |
1623 } | 1380 } |
1624 | 1381 |
1625 // static | 1382 // static |
1626 bool BytecodeArrayBuilder::FitsInReg8OperandUntranslated(Register value) { | 1383 OperandSize BytecodeArrayBuilder::SizeForSignedOperand(int value) { |
1627 return value.is_byte_operand(); | 1384 if (kMinInt8 <= value && value <= kMaxInt8) { |
1628 } | 1385 return OperandSize::kByte; |
1629 | 1386 } else if (kMinInt16 <= value && value <= kMaxInt16) { |
1630 | 1387 return OperandSize::kShort; |
1631 // static | 1388 } else { |
1632 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) { | 1389 return OperandSize::kQuad; |
1633 return RegisterTranslator::FitsInReg16Operand(value); | 1390 } |
1634 } | 1391 } |
1635 | 1392 |
1636 // static | 1393 // static |
1637 bool BytecodeArrayBuilder::FitsInReg16OperandUntranslated(Register value) { | 1394 OperandSize BytecodeArrayBuilder::SizeForUnsignedOperand(int value) { |
1638 return value.is_short_operand(); | 1395 DCHECK_GE(value, 0); |
| 1396 if (value <= kMaxUInt8) { |
| 1397 return OperandSize::kByte; |
| 1398 } else if (value <= kMaxUInt16) { |
| 1399 return OperandSize::kShort; |
| 1400 } else { |
| 1401 return OperandSize::kQuad; |
| 1402 } |
| 1403 } |
| 1404 |
| 1405 OperandSize BytecodeArrayBuilder::SizeForUnsignedOperand(size_t value) { |
| 1406 if (value <= static_cast<size_t>(kMaxUInt8)) { |
| 1407 return OperandSize::kByte; |
| 1408 } else if (value <= static_cast<size_t>(kMaxUInt16)) { |
| 1409 return OperandSize::kShort; |
| 1410 } else if (value <= kMaxUInt32) { |
| 1411 return OperandSize::kQuad; |
| 1412 } else { |
| 1413 UNREACHABLE(); |
| 1414 return OperandSize::kQuad; |
| 1415 } |
| 1416 } |
| 1417 |
| 1418 int BytecodeArrayBuilder::OperandScale(OperandSize size0, OperandSize size1, |
| 1419 OperandSize size2, OperandSize size3) { |
| 1420 OperandSize upper = std::max(size0, size1); |
| 1421 OperandSize lower = std::max(size2, size3); |
| 1422 OperandSize result = std::max(upper, lower); |
| 1423 DCHECK(result <= OperandSize::kQuad); |
| 1424 int operand_scale = static_cast<int>(result); |
| 1425 DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(operand_scale))); |
| 1426 return operand_scale; |
| 1427 } |
| 1428 |
| 1429 uint32_t BytecodeArrayBuilder::SignedOperand(int value, OperandSize size) { |
| 1430 switch (size) { |
| 1431 case OperandSize::kByte: |
| 1432 return static_cast<uint8_t>(value & 0xff); |
| 1433 case OperandSize::kShort: |
| 1434 return static_cast<uint16_t>(value & 0xffff); |
| 1435 case OperandSize::kQuad: |
| 1436 return static_cast<uint32_t>(value); |
| 1437 case OperandSize::kNone: |
| 1438 UNREACHABLE(); |
| 1439 } |
| 1440 return 0; |
| 1441 } |
| 1442 |
| 1443 uint32_t BytecodeArrayBuilder::UnsignedOperand(int value) { |
| 1444 DCHECK_GE(value, 0); |
| 1445 return static_cast<uint32_t>(value); |
| 1446 } |
| 1447 |
| 1448 uint32_t BytecodeArrayBuilder::UnsignedOperand(size_t value) { |
| 1449 DCHECK_LE(value, kMaxUInt32); |
| 1450 return static_cast<uint32_t>(value); |
1639 } | 1451 } |
1640 | 1452 |
1641 } // namespace interpreter | 1453 } // namespace interpreter |
1642 } // namespace internal | 1454 } // namespace internal |
1643 } // namespace v8 | 1455 } // namespace v8 |
OLD | NEW |