Chromium Code Reviews| 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 |