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 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
443 return *this; | 443 return *this; |
444 } | 444 } |
445 | 445 |
446 | 446 |
447 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { | 447 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { |
448 Output(Bytecode::kPopContext, context.ToOperand()); | 448 Output(Bytecode::kPopContext, context.ToOperand()); |
449 return *this; | 449 return *this; |
450 } | 450 } |
451 | 451 |
452 | 452 |
453 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { | 453 bool BytecodeArrayBuilder::IsAccumulatorBoolean() { |
454 if (LastBytecodeInSameBlock()) { | 454 if (LastBytecodeInSameBlock()) { |
455 // If the previous bytecode puts a boolean in the accumulator | 455 // If the previous bytecode puts a boolean in |
456 // there is no need to emit an instruction. | 456 // the accumulator return true. |
457 switch (Bytecodes::FromByte(bytecodes()->at(last_bytecode_start_))) { | 457 switch (Bytecodes::FromByte(bytecodes()->at(last_bytecode_start_))) { |
458 case Bytecode::kToBoolean: | 458 case Bytecode::kToBoolean: |
459 UNREACHABLE(); | 459 UNREACHABLE(); |
460 case Bytecode::kLdaTrue: | 460 case Bytecode::kLdaTrue: |
461 case Bytecode::kLdaFalse: | 461 case Bytecode::kLdaFalse: |
462 case Bytecode::kLogicalNot: | 462 case Bytecode::kLogicalNot: |
463 case Bytecode::kTestEqual: | 463 case Bytecode::kTestEqual: |
464 case Bytecode::kTestNotEqual: | 464 case Bytecode::kTestNotEqual: |
465 case Bytecode::kTestEqualStrict: | 465 case Bytecode::kTestEqualStrict: |
466 case Bytecode::kTestNotEqualStrict: | 466 case Bytecode::kTestNotEqualStrict: |
467 case Bytecode::kTestLessThan: | 467 case Bytecode::kTestLessThan: |
468 case Bytecode::kTestLessThanOrEqual: | 468 case Bytecode::kTestLessThanOrEqual: |
469 case Bytecode::kTestGreaterThan: | 469 case Bytecode::kTestGreaterThan: |
470 case Bytecode::kTestGreaterThanOrEqual: | 470 case Bytecode::kTestGreaterThanOrEqual: |
471 case Bytecode::kTestInstanceOf: | 471 case Bytecode::kTestInstanceOf: |
472 case Bytecode::kTestIn: | 472 case Bytecode::kTestIn: |
473 return *this; | 473 return true; |
474 default: | 474 default: |
475 // Fall through to output kToBoolean. | 475 return false; |
476 break; | |
477 } | 476 } |
478 } | 477 } |
479 Output(Bytecode::kToBoolean); | 478 // If the previous bytecode was from a different block return false. |
479 return false; | |
rmcilroy
2015/10/29 10:40:24
nit - do this as an early out at the to, i.e.:
if
mythria
2015/10/29 17:58:39
Done.
| |
480 } | |
481 | |
482 | |
483 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { | |
484 // If the previous bytecode puts a boolean in the accumulator | |
485 // there is no need to emit an instruction. | |
486 if (!IsAccumulatorBoolean()) { | |
487 Output(Bytecode::kToBoolean); | |
488 } | |
480 return *this; | 489 return *this; |
481 } | 490 } |
482 | 491 |
483 | 492 |
484 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { | 493 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { |
485 Output(Bytecode::kToName); | 494 Output(Bytecode::kToName); |
486 return *this; | 495 return *this; |
487 } | 496 } |
488 | 497 |
489 | 498 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
566 // to match the size of the code it's replacing. In future, | 575 // to match the size of the code it's replacing. In future, |
567 // there will probably be a jump with 32-bit operand for cases | 576 // there will probably be a jump with 32-bit operand for cases |
568 // when constant pool is full, but that needs to be emitted in | 577 // when constant pool is full, but that needs to be emitted in |
569 // OutputJump too. | 578 // OutputJump too. |
570 UNIMPLEMENTED(); | 579 UNIMPLEMENTED(); |
571 } | 580 } |
572 } | 581 } |
573 } | 582 } |
574 | 583 |
575 | 584 |
585 // static | |
586 Bytecode BytecodeArrayBuilder::GetJumpWithToBoolean(Bytecode jump_bytecode, | |
587 bool is_cast_required) { | |
588 if (is_cast_required) { | |
589 switch (jump_bytecode) { | |
590 case Bytecode::kJump: | |
591 return Bytecode::kJump; | |
592 case Bytecode::kJumpIfTrue: | |
593 return Bytecode::kJumpIfToBooleanTrue; | |
594 case Bytecode::kJumpIfFalse: | |
595 return Bytecode::kJumpIfToBooleanFalse; | |
596 default: | |
597 UNREACHABLE(); | |
598 } | |
599 } | |
600 return jump_bytecode; | |
601 } | |
602 | |
603 | |
576 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, | 604 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, |
577 BytecodeLabel* label) { | 605 BytecodeLabel* label) { |
606 // Check if the value in accumulator is boolean, if not choose an | |
607 // appropriate JumpIfToBoolean bytecode. | |
608 bool is_cast_required = !IsAccumulatorBoolean(); | |
609 Bytecode jump_boolean_bytecode = | |
610 GetJumpWithToBoolean(jump_bytecode, is_cast_required); | |
rmcilroy
2015/10/29 10:40:24
Avoid the need for the is_cast_required argument a
mythria
2015/10/29 17:58:39
Done.
| |
611 | |
578 int delta; | 612 int delta; |
579 if (label->is_bound()) { | 613 if (label->is_bound()) { |
580 // Label has been bound already so this is a backwards jump. | 614 // Label has been bound already so this is a backwards jump. |
581 CHECK_GE(bytecodes()->size(), label->offset()); | 615 CHECK_GE(bytecodes()->size(), label->offset()); |
582 CHECK_LE(bytecodes()->size(), static_cast<size_t>(kMaxInt)); | 616 CHECK_LE(bytecodes()->size(), static_cast<size_t>(kMaxInt)); |
583 size_t abs_delta = bytecodes()->size() - label->offset(); | 617 size_t abs_delta = bytecodes()->size() - label->offset(); |
584 delta = -static_cast<int>(abs_delta); | 618 delta = -static_cast<int>(abs_delta); |
585 } else { | 619 } else { |
586 // Label has not yet been bound so this is a forward reference | 620 // Label has not yet been bound so this is a forward reference |
587 // that will be patched when the label is bound. | 621 // that will be patched when the label is bound. |
588 label->set_referrer(bytecodes()->size()); | 622 label->set_referrer(bytecodes()->size()); |
589 delta = 0; | 623 delta = 0; |
590 } | 624 } |
591 | 625 |
592 if (FitsInImm8Operand(delta)) { | 626 if (FitsInImm8Operand(delta)) { |
593 Output(jump_bytecode, static_cast<uint8_t>(delta)); | 627 Output(jump_boolean_bytecode, static_cast<uint8_t>(delta)); |
594 } else { | 628 } else { |
595 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); | 629 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); |
596 if (FitsInIdx8Operand(entry)) { | 630 if (FitsInIdx8Operand(entry)) { |
597 Output(GetJumpWithConstantOperand(jump_bytecode), | 631 Output(GetJumpWithConstantOperand(jump_boolean_bytecode), |
598 static_cast<uint8_t>(entry)); | 632 static_cast<uint8_t>(entry)); |
599 } else { | 633 } else { |
600 UNIMPLEMENTED(); | 634 UNIMPLEMENTED(); |
601 } | 635 } |
602 } | 636 } |
603 return *this; | 637 return *this; |
604 } | 638 } |
605 | 639 |
606 | 640 |
607 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { | 641 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { |
608 return OutputJump(Bytecode::kJump, label); | 642 return OutputJump(Bytecode::kJump, label); |
609 } | 643 } |
610 | 644 |
611 | 645 |
612 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { | 646 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { |
613 return OutputJump(Bytecode::kJumpIfTrue, label); | 647 return OutputJump(Bytecode::kJumpIfTrue, label); |
614 } | 648 } |
615 | 649 |
616 | 650 |
617 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { | 651 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { |
618 return OutputJump(Bytecode::kJumpIfFalse, label); | 652 return OutputJump(Bytecode::kJumpIfFalse, label); |
619 } | 653 } |
620 | 654 |
621 | 655 |
622 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfToBooleanTrue( | |
623 BytecodeLabel* label) { | |
624 return OutputJump(Bytecode::kJumpIfToBooleanTrue, label); | |
625 } | |
626 | |
627 | |
628 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfToBooleanFalse( | |
629 BytecodeLabel* label) { | |
630 return OutputJump(Bytecode::kJumpIfToBooleanFalse, label); | |
631 } | |
632 | |
633 | |
634 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() { | 656 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() { |
635 Output(Bytecode::kThrow); | 657 Output(Bytecode::kThrow); |
636 exit_seen_in_block_ = true; | 658 exit_seen_in_block_ = true; |
637 return *this; | 659 return *this; |
638 } | 660 } |
639 | 661 |
640 | 662 |
641 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { | 663 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { |
642 Output(Bytecode::kReturn); | 664 Output(Bytecode::kReturn); |
643 exit_seen_in_block_ = true; | 665 exit_seen_in_block_ = true; |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1107 DCHECK_GT(next_consecutive_count_, 0); | 1129 DCHECK_GT(next_consecutive_count_, 0); |
1108 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); | 1130 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); |
1109 allocated_.push_back(next_consecutive_register_); | 1131 allocated_.push_back(next_consecutive_register_); |
1110 next_consecutive_count_--; | 1132 next_consecutive_count_--; |
1111 return Register(next_consecutive_register_++); | 1133 return Register(next_consecutive_register_++); |
1112 } | 1134 } |
1113 | 1135 |
1114 } // namespace interpreter | 1136 } // namespace interpreter |
1115 } // namespace internal | 1137 } // namespace internal |
1116 } // namespace v8 | 1138 } // namespace v8 |
OLD | NEW |