| 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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 Handle<BytecodeArray> output = | 103 Handle<BytecodeArray> output = |
| 104 factory->NewBytecodeArray(bytecode_size, &bytecodes_.front(), frame_size, | 104 factory->NewBytecodeArray(bytecode_size, &bytecodes_.front(), frame_size, |
| 105 parameter_count(), constant_pool); | 105 parameter_count(), constant_pool); |
| 106 bytecode_generated_ = true; | 106 bytecode_generated_ = true; |
| 107 return output; | 107 return output; |
| 108 } | 108 } |
| 109 | 109 |
| 110 | 110 |
| 111 template <size_t N> | 111 template <size_t N> |
| 112 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { | 112 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { |
| 113 // Don't output dead code. |
| 114 if (exit_seen_in_block_) return; |
| 115 |
| 113 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), static_cast<int>(N)); | 116 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), static_cast<int>(N)); |
| 114 last_bytecode_start_ = bytecodes()->size(); | 117 last_bytecode_start_ = bytecodes()->size(); |
| 115 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | 118 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
| 116 for (int i = 0; i < static_cast<int>(N); i++) { | 119 for (int i = 0; i < static_cast<int>(N); i++) { |
| 117 DCHECK(OperandIsValid(bytecode, i, operands[i])); | 120 DCHECK(OperandIsValid(bytecode, i, operands[i])); |
| 118 switch (Bytecodes::GetOperandSize(bytecode, i)) { | 121 switch (Bytecodes::GetOperandSize(bytecode, i)) { |
| 119 case OperandSize::kNone: | 122 case OperandSize::kNone: |
| 120 UNREACHABLE(); | 123 UNREACHABLE(); |
| 121 case OperandSize::kByte: | 124 case OperandSize::kByte: |
| 122 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); | 125 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 147 } | 150 } |
| 148 | 151 |
| 149 | 152 |
| 150 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { | 153 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { |
| 151 uint32_t operands[] = {operand0}; | 154 uint32_t operands[] = {operand0}; |
| 152 Output(bytecode, operands); | 155 Output(bytecode, operands); |
| 153 } | 156 } |
| 154 | 157 |
| 155 | 158 |
| 156 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | 159 void BytecodeArrayBuilder::Output(Bytecode bytecode) { |
| 160 // Don't output dead code. |
| 161 if (exit_seen_in_block_) return; |
| 162 |
| 157 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); | 163 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); |
| 158 last_bytecode_start_ = bytecodes()->size(); | 164 last_bytecode_start_ = bytecodes()->size(); |
| 159 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | 165 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
| 160 } | 166 } |
| 161 | 167 |
| 162 | 168 |
| 163 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | 169 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
| 164 Register reg, | 170 Register reg, |
| 165 Strength strength) { | 171 Strength strength) { |
| 166 if (is_strong(strength)) { | 172 if (is_strong(strength)) { |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 } | 547 } |
| 542 | 548 |
| 543 | 549 |
| 544 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) { | 550 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) { |
| 545 if (label->is_forward_target()) { | 551 if (label->is_forward_target()) { |
| 546 // An earlier jump instruction refers to this label. Update it's location. | 552 // An earlier jump instruction refers to this label. Update it's location. |
| 547 PatchJump(bytecodes()->end(), bytecodes()->begin() + label->offset()); | 553 PatchJump(bytecodes()->end(), bytecodes()->begin() + label->offset()); |
| 548 // Now treat as if the label will only be back referred to. | 554 // Now treat as if the label will only be back referred to. |
| 549 } | 555 } |
| 550 label->bind_to(bytecodes()->size()); | 556 label->bind_to(bytecodes()->size()); |
| 557 LeaveBasicBlock(); |
| 551 return *this; | 558 return *this; |
| 552 } | 559 } |
| 553 | 560 |
| 554 | 561 |
| 555 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, | 562 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, |
| 556 BytecodeLabel* label) { | 563 BytecodeLabel* label) { |
| 557 DCHECK_EQ(label->is_bound(), false); | 564 DCHECK(!label->is_bound()); |
| 558 DCHECK_EQ(target.is_bound(), true); | 565 DCHECK(target.is_bound()); |
| 559 PatchJump(bytecodes()->begin() + target.offset(), | 566 PatchJump(bytecodes()->begin() + target.offset(), |
| 560 bytecodes()->begin() + label->offset()); | 567 bytecodes()->begin() + label->offset()); |
| 561 label->bind_to(target.offset()); | 568 label->bind_to(target.offset()); |
| 569 LeaveBasicBlock(); |
| 562 return *this; | 570 return *this; |
| 563 } | 571 } |
| 564 | 572 |
| 565 | 573 |
| 566 // static | 574 // static |
| 567 Bytecode BytecodeArrayBuilder::GetJumpWithConstantOperand( | 575 Bytecode BytecodeArrayBuilder::GetJumpWithConstantOperand( |
| 568 Bytecode jump_bytecode) { | 576 Bytecode jump_bytecode) { |
| 569 switch (jump_bytecode) { | 577 switch (jump_bytecode) { |
| 570 case Bytecode::kJump: | 578 case Bytecode::kJump: |
| 571 return Bytecode::kJumpConstant; | 579 return Bytecode::kJumpConstant; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 return Bytecode::kJumpIfToBooleanFalse; | 644 return Bytecode::kJumpIfToBooleanFalse; |
| 637 default: | 645 default: |
| 638 UNREACHABLE(); | 646 UNREACHABLE(); |
| 639 } | 647 } |
| 640 return static_cast<Bytecode>(-1); | 648 return static_cast<Bytecode>(-1); |
| 641 } | 649 } |
| 642 | 650 |
| 643 | 651 |
| 644 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, | 652 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, |
| 645 BytecodeLabel* label) { | 653 BytecodeLabel* label) { |
| 654 // Don't emit dead code. |
| 655 if (exit_seen_in_block_) return *this; |
| 656 |
| 646 // Check if the value in accumulator is boolean, if not choose an | 657 // Check if the value in accumulator is boolean, if not choose an |
| 647 // appropriate JumpIfToBoolean bytecode. | 658 // appropriate JumpIfToBoolean bytecode. |
| 648 if (NeedToBooleanCast()) { | 659 if (NeedToBooleanCast()) { |
| 649 jump_bytecode = GetJumpWithToBoolean(jump_bytecode); | 660 jump_bytecode = GetJumpWithToBoolean(jump_bytecode); |
| 650 } | 661 } |
| 651 | 662 |
| 652 int delta; | 663 int delta; |
| 653 if (label->is_bound()) { | 664 if (label->is_bound()) { |
| 654 // Label has been bound already so this is a backwards jump. | 665 // Label has been bound already so this is a backwards jump. |
| 655 CHECK_GE(bytecodes()->size(), label->offset()); | 666 CHECK_GE(bytecodes()->size(), label->offset()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 667 Output(jump_bytecode, static_cast<uint8_t>(delta)); | 678 Output(jump_bytecode, static_cast<uint8_t>(delta)); |
| 668 } else { | 679 } else { |
| 669 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); | 680 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); |
| 670 if (FitsInIdx8Operand(entry)) { | 681 if (FitsInIdx8Operand(entry)) { |
| 671 Output(GetJumpWithConstantOperand(jump_bytecode), | 682 Output(GetJumpWithConstantOperand(jump_bytecode), |
| 672 static_cast<uint8_t>(entry)); | 683 static_cast<uint8_t>(entry)); |
| 673 } else { | 684 } else { |
| 674 UNIMPLEMENTED(); | 685 UNIMPLEMENTED(); |
| 675 } | 686 } |
| 676 } | 687 } |
| 688 LeaveBasicBlock(); |
| 677 return *this; | 689 return *this; |
| 678 } | 690 } |
| 679 | 691 |
| 680 | 692 |
| 681 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { | 693 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { |
| 682 return OutputJump(Bytecode::kJump, label); | 694 return OutputJump(Bytecode::kJump, label); |
| 683 } | 695 } |
| 684 | 696 |
| 685 | 697 |
| 686 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { | 698 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 return *this; | 742 return *this; |
| 731 } | 743 } |
| 732 | 744 |
| 733 | 745 |
| 734 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register for_in_state) { | 746 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register for_in_state) { |
| 735 Output(Bytecode::kForInDone, for_in_state.ToOperand()); | 747 Output(Bytecode::kForInDone, for_in_state.ToOperand()); |
| 736 return *this; | 748 return *this; |
| 737 } | 749 } |
| 738 | 750 |
| 739 | 751 |
| 740 BytecodeArrayBuilder& BytecodeArrayBuilder::EnterBlock() { return *this; } | 752 void BytecodeArrayBuilder::LeaveBasicBlock() { |
| 741 | |
| 742 | |
| 743 BytecodeArrayBuilder& BytecodeArrayBuilder::LeaveBlock() { | |
| 744 last_block_end_ = bytecodes()->size(); | 753 last_block_end_ = bytecodes()->size(); |
| 745 exit_seen_in_block_ = false; | 754 exit_seen_in_block_ = false; |
| 746 return *this; | |
| 747 } | 755 } |
| 748 | 756 |
| 749 | 757 |
| 750 void BytecodeArrayBuilder::EnsureReturn() { | 758 void BytecodeArrayBuilder::EnsureReturn() { |
| 751 if (!exit_seen_in_block_) { | 759 if (!exit_seen_in_block_) { |
| 752 LoadUndefined(); | 760 LoadUndefined(); |
| 753 Return(); | 761 Return(); |
| 754 } | 762 } |
| 755 } | 763 } |
| 756 | 764 |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 DCHECK_GT(next_consecutive_count_, 0); | 1247 DCHECK_GT(next_consecutive_count_, 0); |
| 1240 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); | 1248 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); |
| 1241 allocated_.push_back(next_consecutive_register_); | 1249 allocated_.push_back(next_consecutive_register_); |
| 1242 next_consecutive_count_--; | 1250 next_consecutive_count_--; |
| 1243 return Register(next_consecutive_register_++); | 1251 return Register(next_consecutive_register_++); |
| 1244 } | 1252 } |
| 1245 | 1253 |
| 1246 } // namespace interpreter | 1254 } // namespace interpreter |
| 1247 } // namespace internal | 1255 } // namespace internal |
| 1248 } // namespace v8 | 1256 } // namespace v8 |
| OLD | NEW |