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 | 6 |
7 namespace v8 { | 7 namespace v8 { |
8 namespace internal { | 8 namespace internal { |
9 namespace interpreter { | 9 namespace interpreter { |
10 | 10 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi)); | 154 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi)); |
155 } else { | 155 } else { |
156 LoadLiteral(Handle<Object>(smi, isolate_)); | 156 LoadLiteral(Handle<Object>(smi, isolate_)); |
157 } | 157 } |
158 return *this; | 158 return *this; |
159 } | 159 } |
160 | 160 |
161 | 161 |
162 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { | 162 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { |
163 size_t entry = GetConstantPoolEntry(object); | 163 size_t entry = GetConstantPoolEntry(object); |
164 if (FitsInIdxOperand(entry)) { | 164 if (FitsInIdx8Operand(entry)) { |
165 Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry)); | 165 Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry)); |
166 } else { | 166 } else { |
167 UNIMPLEMENTED(); | 167 UNIMPLEMENTED(); |
168 } | 168 } |
169 return *this; | 169 return *this; |
170 } | 170 } |
171 | 171 |
172 | 172 |
173 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { | 173 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { |
174 Output(Bytecode::kLdaUndefined); | 174 Output(Bytecode::kLdaUndefined); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 | 209 |
210 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( | 210 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( |
211 Register reg) { | 211 Register reg) { |
212 Output(Bytecode::kStar, reg.ToOperand()); | 212 Output(Bytecode::kStar, reg.ToOperand()); |
213 return *this; | 213 return *this; |
214 } | 214 } |
215 | 215 |
216 | 216 |
217 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int slot_index) { | 217 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int slot_index) { |
218 DCHECK(slot_index >= 0); | 218 DCHECK(slot_index >= 0); |
219 if (FitsInIdxOperand(slot_index)) { | 219 if (FitsInIdx8Operand(slot_index)) { |
220 Output(Bytecode::kLdaGlobal, static_cast<uint8_t>(slot_index)); | 220 Output(Bytecode::kLdaGlobal, static_cast<uint8_t>(slot_index)); |
221 } else { | 221 } else { |
222 UNIMPLEMENTED(); | 222 UNIMPLEMENTED(); |
223 } | 223 } |
224 return *this; | 224 return *this; |
225 } | 225 } |
226 | 226 |
227 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( | 227 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
228 Register object, int feedback_slot, LanguageMode language_mode) { | 228 Register object, int feedback_slot, LanguageMode language_mode) { |
229 if (!is_sloppy(language_mode)) { | 229 if (!is_sloppy(language_mode)) { |
230 UNIMPLEMENTED(); | 230 UNIMPLEMENTED(); |
231 } | 231 } |
232 | 232 |
233 if (FitsInIdxOperand(feedback_slot)) { | 233 if (FitsInIdx8Operand(feedback_slot)) { |
234 Output(Bytecode::kLoadIC, object.ToOperand(), | 234 Output(Bytecode::kLoadIC, object.ToOperand(), |
235 static_cast<uint8_t>(feedback_slot)); | 235 static_cast<uint8_t>(feedback_slot)); |
236 } else { | 236 } else { |
237 UNIMPLEMENTED(); | 237 UNIMPLEMENTED(); |
238 } | 238 } |
239 return *this; | 239 return *this; |
240 } | 240 } |
241 | 241 |
242 | 242 |
243 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( | 243 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
244 Register object, int feedback_slot, LanguageMode language_mode) { | 244 Register object, int feedback_slot, LanguageMode language_mode) { |
245 if (!is_sloppy(language_mode)) { | 245 if (!is_sloppy(language_mode)) { |
246 UNIMPLEMENTED(); | 246 UNIMPLEMENTED(); |
247 } | 247 } |
248 | 248 |
249 if (FitsInIdxOperand(feedback_slot)) { | 249 if (FitsInIdx8Operand(feedback_slot)) { |
250 Output(Bytecode::kKeyedLoadIC, object.ToOperand(), | 250 Output(Bytecode::kKeyedLoadIC, object.ToOperand(), |
251 static_cast<uint8_t>(feedback_slot)); | 251 static_cast<uint8_t>(feedback_slot)); |
252 } else { | 252 } else { |
253 UNIMPLEMENTED(); | 253 UNIMPLEMENTED(); |
254 } | 254 } |
255 return *this; | 255 return *this; |
256 } | 256 } |
257 | 257 |
258 | 258 |
259 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( | 259 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
260 Register object, Register name, int feedback_slot, | 260 Register object, Register name, int feedback_slot, |
261 LanguageMode language_mode) { | 261 LanguageMode language_mode) { |
262 if (!is_sloppy(language_mode)) { | 262 if (!is_sloppy(language_mode)) { |
263 UNIMPLEMENTED(); | 263 UNIMPLEMENTED(); |
264 } | 264 } |
265 | 265 |
266 if (FitsInIdxOperand(feedback_slot)) { | 266 if (FitsInIdx8Operand(feedback_slot)) { |
267 Output(Bytecode::kStoreIC, object.ToOperand(), name.ToOperand(), | 267 Output(Bytecode::kStoreIC, object.ToOperand(), name.ToOperand(), |
268 static_cast<uint8_t>(feedback_slot)); | 268 static_cast<uint8_t>(feedback_slot)); |
269 } else { | 269 } else { |
270 UNIMPLEMENTED(); | 270 UNIMPLEMENTED(); |
271 } | 271 } |
272 return *this; | 272 return *this; |
273 } | 273 } |
274 | 274 |
275 | 275 |
276 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( | 276 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
277 Register object, Register key, int feedback_slot, | 277 Register object, Register key, int feedback_slot, |
278 LanguageMode language_mode) { | 278 LanguageMode language_mode) { |
279 if (!is_sloppy(language_mode)) { | 279 if (!is_sloppy(language_mode)) { |
280 UNIMPLEMENTED(); | 280 UNIMPLEMENTED(); |
281 } | 281 } |
282 | 282 |
283 if (FitsInIdxOperand(feedback_slot)) { | 283 if (FitsInIdx8Operand(feedback_slot)) { |
284 Output(Bytecode::kKeyedStoreIC, object.ToOperand(), key.ToOperand(), | 284 Output(Bytecode::kKeyedStoreIC, object.ToOperand(), key.ToOperand(), |
285 static_cast<uint8_t>(feedback_slot)); | 285 static_cast<uint8_t>(feedback_slot)); |
286 } else { | 286 } else { |
287 UNIMPLEMENTED(); | 287 UNIMPLEMENTED(); |
288 } | 288 } |
289 return *this; | 289 return *this; |
290 } | 290 } |
291 | 291 |
292 | 292 |
293 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { | 293 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 DCHECK_EQ(Bytecodes::Size(jump_bytecode), 2); | 369 DCHECK_EQ(Bytecodes::Size(jump_bytecode), 2); |
370 DCHECK_NE(delta, 0); | 370 DCHECK_NE(delta, 0); |
371 | 371 |
372 if (FitsInImm8Operand(delta)) { | 372 if (FitsInImm8Operand(delta)) { |
373 // Just update the operand | 373 // Just update the operand |
374 jump_location++; | 374 jump_location++; |
375 *jump_location = static_cast<uint8_t>(delta); | 375 *jump_location = static_cast<uint8_t>(delta); |
376 } else { | 376 } else { |
377 // Update the jump type and operand | 377 // Update the jump type and operand |
378 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); | 378 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); |
379 if (FitsInIdxOperand(entry)) { | 379 if (FitsInIdx8Operand(entry)) { |
380 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); | 380 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); |
381 *jump_location++ = Bytecodes::ToByte(jump_bytecode); | 381 *jump_location++ = Bytecodes::ToByte(jump_bytecode); |
382 *jump_location = static_cast<uint8_t>(entry); | 382 *jump_location = static_cast<uint8_t>(entry); |
383 } else { | 383 } else { |
384 // TODO(oth): OutputJump should reserve a constant pool entry | 384 // TODO(oth): OutputJump should reserve a constant pool entry |
385 // when jump is written. The reservation should be used here if | 385 // when jump is written. The reservation should be used here if |
386 // needed, or cancelled if not. This is due to the patch needing | 386 // needed, or cancelled if not. This is due to the patch needing |
387 // to match the size of the code it's replacing. In future, | 387 // to match the size of the code it's replacing. In future, |
388 // there will probably be a jump with 32-bit operand for cases | 388 // there will probably be a jump with 32-bit operand for cases |
389 // when constant pool is full, but that needs to be emitted in | 389 // when constant pool is full, but that needs to be emitted in |
(...skipping 17 matching lines...) Expand all Loading... |
407 // Label has not yet been bound so this is a forward reference | 407 // Label has not yet been bound so this is a forward reference |
408 // that will be patched when the label is bound. | 408 // that will be patched when the label is bound. |
409 label->set_referrer(bytecodes()->size()); | 409 label->set_referrer(bytecodes()->size()); |
410 delta = 0; | 410 delta = 0; |
411 } | 411 } |
412 | 412 |
413 if (FitsInImm8Operand(delta)) { | 413 if (FitsInImm8Operand(delta)) { |
414 Output(jump_bytecode, static_cast<uint8_t>(delta)); | 414 Output(jump_bytecode, static_cast<uint8_t>(delta)); |
415 } else { | 415 } else { |
416 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); | 416 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); |
417 if (FitsInIdxOperand(entry)) { | 417 if (FitsInIdx8Operand(entry)) { |
418 Output(GetJumpWithConstantOperand(jump_bytecode), | 418 Output(GetJumpWithConstantOperand(jump_bytecode), |
419 static_cast<uint8_t>(entry)); | 419 static_cast<uint8_t>(entry)); |
420 } else { | 420 } else { |
421 UNIMPLEMENTED(); | 421 UNIMPLEMENTED(); |
422 } | 422 } |
423 } | 423 } |
424 return *this; | 424 return *this; |
425 } | 425 } |
426 | 426 |
427 | 427 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 void BytecodeArrayBuilder::EnsureReturn() { | 460 void BytecodeArrayBuilder::EnsureReturn() { |
461 if (!return_seen_in_block_) { | 461 if (!return_seen_in_block_) { |
462 LoadUndefined(); | 462 LoadUndefined(); |
463 Return(); | 463 Return(); |
464 } | 464 } |
465 } | 465 } |
466 | 466 |
467 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 467 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
468 Register receiver, | 468 Register receiver, |
469 size_t arg_count) { | 469 size_t arg_count) { |
470 if (FitsInIdxOperand(arg_count)) { | 470 if (FitsInIdx8Operand(arg_count)) { |
471 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(), | 471 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(), |
472 static_cast<uint8_t>(arg_count)); | 472 static_cast<uint8_t>(arg_count)); |
473 } else { | 473 } else { |
474 UNIMPLEMENTED(); | 474 UNIMPLEMENTED(); |
475 } | 475 } |
476 return *this; | 476 return *this; |
477 } | 477 } |
478 | 478 |
479 | 479 |
| 480 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
| 481 Runtime::FunctionId function_id, Register first_arg, size_t arg_count) { |
| 482 DCHECK(FitsInIdx16Operand(function_id)); |
| 483 DCHECK(FitsInIdx8Operand(arg_count)); |
| 484 Output(Bytecode::kCallRuntime, static_cast<uint16_t>(function_id), |
| 485 first_arg.ToOperand(), static_cast<uint8_t>(arg_count)); |
| 486 return *this; |
| 487 } |
| 488 |
| 489 |
480 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 490 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
481 // These constants shouldn't be added to the constant pool, the should use | 491 // These constants shouldn't be added to the constant pool, the should use |
482 // specialzed bytecodes instead. | 492 // specialzed bytecodes instead. |
483 DCHECK(!object.is_identical_to(isolate_->factory()->undefined_value())); | 493 DCHECK(!object.is_identical_to(isolate_->factory()->undefined_value())); |
484 DCHECK(!object.is_identical_to(isolate_->factory()->null_value())); | 494 DCHECK(!object.is_identical_to(isolate_->factory()->null_value())); |
485 DCHECK(!object.is_identical_to(isolate_->factory()->the_hole_value())); | 495 DCHECK(!object.is_identical_to(isolate_->factory()->the_hole_value())); |
486 DCHECK(!object.is_identical_to(isolate_->factory()->true_value())); | 496 DCHECK(!object.is_identical_to(isolate_->factory()->true_value())); |
487 DCHECK(!object.is_identical_to(isolate_->factory()->false_value())); | 497 DCHECK(!object.is_identical_to(isolate_->factory()->false_value())); |
488 | 498 |
489 size_t* entry = constants_map_.Find(object); | 499 size_t* entry = constants_map_.Find(object); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 case Token::Value::IN: | 600 case Token::Value::IN: |
591 return Bytecode::kTestIn; | 601 return Bytecode::kTestIn; |
592 default: | 602 default: |
593 UNREACHABLE(); | 603 UNREACHABLE(); |
594 return static_cast<Bytecode>(-1); | 604 return static_cast<Bytecode>(-1); |
595 } | 605 } |
596 } | 606 } |
597 | 607 |
598 | 608 |
599 // static | 609 // static |
600 bool BytecodeArrayBuilder::FitsInIdxOperand(int value) { | 610 bool BytecodeArrayBuilder::FitsInIdx8Operand(int value) { |
601 return kMinUInt8 <= value && value <= kMaxUInt8; | 611 return kMinUInt8 <= value && value <= kMaxUInt8; |
602 } | 612 } |
603 | 613 |
604 | 614 |
605 // static | 615 // static |
606 bool BytecodeArrayBuilder::FitsInIdxOperand(size_t value) { | 616 bool BytecodeArrayBuilder::FitsInIdx8Operand(size_t value) { |
607 return value <= static_cast<size_t>(kMaxUInt8); | 617 return value <= static_cast<size_t>(kMaxUInt8); |
608 } | 618 } |
609 | 619 |
610 | 620 |
611 // static | 621 // static |
612 bool BytecodeArrayBuilder::FitsInImm8Operand(int value) { | 622 bool BytecodeArrayBuilder::FitsInImm8Operand(int value) { |
613 return kMinInt8 <= value && value < kMaxInt8; | 623 return kMinInt8 <= value && value < kMaxInt8; |
614 } | 624 } |
615 | 625 |
616 | 626 |
| 627 // static |
| 628 bool BytecodeArrayBuilder::FitsInIdx16Operand(int value) { |
| 629 return kMinUInt16 <= value && value <= kMaxUInt16; |
| 630 } |
| 631 |
| 632 |
617 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) | 633 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) |
618 : builder_(builder), count_(0), last_register_index_(-1) {} | 634 : builder_(builder), count_(0), last_register_index_(-1) {} |
619 | 635 |
620 | 636 |
621 TemporaryRegisterScope::~TemporaryRegisterScope() { | 637 TemporaryRegisterScope::~TemporaryRegisterScope() { |
622 while (count_-- != 0) { | 638 while (count_-- != 0) { |
623 builder_->ReturnTemporaryRegister(last_register_index_--); | 639 builder_->ReturnTemporaryRegister(last_register_index_--); |
624 } | 640 } |
625 } | 641 } |
626 | 642 |
627 | 643 |
628 Register TemporaryRegisterScope::NewRegister() { | 644 Register TemporaryRegisterScope::NewRegister() { |
629 count_++; | 645 count_++; |
630 last_register_index_ = builder_->BorrowTemporaryRegister(); | 646 last_register_index_ = builder_->BorrowTemporaryRegister(); |
631 return Register(last_register_index_); | 647 return Register(last_register_index_); |
632 } | 648 } |
633 | 649 |
634 } // namespace interpreter | 650 } // namespace interpreter |
635 } // namespace internal | 651 } // namespace internal |
636 } // namespace v8 | 652 } // namespace v8 |
OLD | NEW |