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 |
11 class BytecodeArrayBuilder::PreviousBytecodeHelper { | 11 class BytecodeArrayBuilder::PreviousBytecodeHelper { |
12 public: | 12 public: |
13 explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder) | 13 explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder) |
14 : array_builder_(array_builder) {} | 14 : array_builder_(array_builder), |
15 | 15 previous_bytecode_start_(array_builder_.last_bytecode_start_) { |
16 Bytecode GetBytecode() const { | 16 // This helper is expected to be instantiated only when the last bytecode is |
17 // Returns the previous bytecode in the same basicblock. If there is none it | 17 // in the same basic block. |
18 // returns Bytecode::kLast. | 18 DCHECK(array_builder_.LastBytecodeInSameBlock()); |
19 if (!array_builder_.LastBytecodeInSameBlock()) { | |
20 return Bytecode::kLast; | |
21 } | |
22 return Bytecodes::FromByte( | |
23 array_builder_.bytecodes()->at(array_builder_.last_bytecode_start_)); | |
24 } | 19 } |
25 | 20 |
26 uint32_t GetOperand(int operand_index) const { | 21 // Returns the previous bytecode in the same basic block. |
| 22 MUST_USE_RESULT Bytecode GetBytecode() const { |
| 23 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); |
| 24 return Bytecodes::FromByte( |
| 25 array_builder_.bytecodes()->at(previous_bytecode_start_)); |
| 26 } |
| 27 |
| 28 // Returns the operand at operand_index for the previous bytecode in the |
| 29 // same basic block. |
| 30 MUST_USE_RESULT uint32_t GetOperand(int operand_index) const { |
| 31 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); |
27 Bytecode bytecode = GetBytecode(); | 32 Bytecode bytecode = GetBytecode(); |
28 DCHECK_GE(operand_index, 0); | 33 DCHECK_GE(operand_index, 0); |
29 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); | 34 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); |
30 size_t operand_offset = | 35 size_t operand_offset = |
31 array_builder_.last_bytecode_start_ + | 36 previous_bytecode_start_ + |
32 Bytecodes::GetOperandOffset(bytecode, operand_index); | 37 Bytecodes::GetOperandOffset(bytecode, operand_index); |
33 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); | 38 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); |
34 switch (size) { | 39 switch (size) { |
35 default: | 40 default: |
36 case OperandSize::kNone: | 41 case OperandSize::kNone: |
37 UNREACHABLE(); | 42 UNREACHABLE(); |
38 case OperandSize::kByte: | 43 case OperandSize::kByte: |
39 return static_cast<uint32_t>( | 44 return static_cast<uint32_t>( |
40 array_builder_.bytecodes()->at(operand_offset)); | 45 array_builder_.bytecodes()->at(operand_offset)); |
41 case OperandSize::kShort: | 46 case OperandSize::kShort: |
42 uint16_t operand = | 47 uint16_t operand = |
43 (array_builder_.bytecodes()->at(operand_offset) << 8) + | 48 (array_builder_.bytecodes()->at(operand_offset) << 8) + |
44 array_builder_.bytecodes()->at(operand_offset + 1); | 49 array_builder_.bytecodes()->at(operand_offset + 1); |
45 return static_cast<uint32_t>(operand); | 50 return static_cast<uint32_t>(operand); |
46 } | 51 } |
47 } | 52 } |
48 | 53 |
49 Handle<Object> GetConstantForIndexOperand(int operand_index) const { | 54 Handle<Object> GetConstantForIndexOperand(int operand_index) const { |
50 return array_builder_.constants_.at(GetOperand(operand_index)); | 55 return array_builder_.constants_.at(GetOperand(operand_index)); |
51 } | 56 } |
52 | 57 |
53 private: | 58 private: |
54 const BytecodeArrayBuilder& array_builder_; | 59 const BytecodeArrayBuilder& array_builder_; |
| 60 size_t previous_bytecode_start_; |
| 61 |
| 62 DISALLOW_COPY_AND_ASSIGN(PreviousBytecodeHelper); |
55 }; | 63 }; |
56 | 64 |
57 | 65 |
58 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) | 66 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) |
59 : isolate_(isolate), | 67 : isolate_(isolate), |
60 zone_(zone), | 68 zone_(zone), |
61 bytecodes_(zone), | 69 bytecodes_(zone), |
62 bytecode_generated_(false), | 70 bytecode_generated_(false), |
63 last_block_end_(0), | 71 last_block_end_(0), |
64 last_bytecode_start_(~0), | 72 last_bytecode_start_(~0), |
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 } | 581 } |
574 | 582 |
575 | 583 |
576 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { | 584 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { |
577 Output(Bytecode::kPopContext, context.ToOperand()); | 585 Output(Bytecode::kPopContext, context.ToOperand()); |
578 return *this; | 586 return *this; |
579 } | 587 } |
580 | 588 |
581 | 589 |
582 bool BytecodeArrayBuilder::NeedToBooleanCast() { | 590 bool BytecodeArrayBuilder::NeedToBooleanCast() { |
| 591 if (!LastBytecodeInSameBlock()) { |
| 592 return true; |
| 593 } |
583 PreviousBytecodeHelper previous_bytecode(*this); | 594 PreviousBytecodeHelper previous_bytecode(*this); |
584 switch (previous_bytecode.GetBytecode()) { | 595 switch (previous_bytecode.GetBytecode()) { |
585 case Bytecode::kToBoolean: | 596 case Bytecode::kToBoolean: |
586 UNREACHABLE(); | 597 UNREACHABLE(); |
587 // If the previous bytecode puts a boolean in the accumulator return true. | 598 // If the previous bytecode puts a boolean in the accumulator return true. |
588 case Bytecode::kLdaTrue: | 599 case Bytecode::kLdaTrue: |
589 case Bytecode::kLdaFalse: | 600 case Bytecode::kLdaFalse: |
590 case Bytecode::kLogicalNot: | 601 case Bytecode::kLogicalNot: |
591 case Bytecode::kTestEqual: | 602 case Bytecode::kTestEqual: |
592 case Bytecode::kTestNotEqual: | 603 case Bytecode::kTestNotEqual: |
593 case Bytecode::kTestEqualStrict: | 604 case Bytecode::kTestEqualStrict: |
594 case Bytecode::kTestNotEqualStrict: | 605 case Bytecode::kTestNotEqualStrict: |
595 case Bytecode::kTestLessThan: | 606 case Bytecode::kTestLessThan: |
596 case Bytecode::kTestLessThanOrEqual: | 607 case Bytecode::kTestLessThanOrEqual: |
597 case Bytecode::kTestGreaterThan: | 608 case Bytecode::kTestGreaterThan: |
598 case Bytecode::kTestGreaterThanOrEqual: | 609 case Bytecode::kTestGreaterThanOrEqual: |
599 case Bytecode::kTestInstanceOf: | 610 case Bytecode::kTestInstanceOf: |
600 case Bytecode::kTestIn: | 611 case Bytecode::kTestIn: |
601 case Bytecode::kForInDone: | 612 case Bytecode::kForInDone: |
602 return false; | 613 return false; |
603 // Also handles the case where the previous bytecode was in a different | |
604 // block. | |
605 default: | 614 default: |
606 return true; | 615 return true; |
607 } | 616 } |
608 } | 617 } |
609 | 618 |
610 | 619 |
611 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { | 620 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { |
612 PreviousBytecodeHelper previous_bytecode(*this); | 621 if (!LastBytecodeInSameBlock()) { |
| 622 Output(Bytecode::kToBoolean); |
| 623 return *this; |
| 624 } |
613 // If the previous bytecode puts a boolean in the accumulator | 625 // If the previous bytecode puts a boolean in the accumulator |
614 // there is no need to emit an instruction. | 626 // there is no need to emit an instruction. |
615 if (NeedToBooleanCast()) { | 627 if (NeedToBooleanCast()) { |
| 628 PreviousBytecodeHelper previous_bytecode(*this); |
616 switch (previous_bytecode.GetBytecode()) { | 629 switch (previous_bytecode.GetBytecode()) { |
617 // If the previous bytecode is a constant evaluate it and return false. | 630 // If the previous bytecode is a constant evaluate it and return false. |
618 case Bytecode::kLdaZero: { | 631 case Bytecode::kLdaZero: { |
619 LoadFalse(); | 632 LoadFalse(); |
620 break; | 633 break; |
621 } | 634 } |
622 case Bytecode::kLdaSmi8: { | 635 case Bytecode::kLdaSmi8: { |
623 LoadBooleanConstant(previous_bytecode.GetOperand(0) != 0); | 636 LoadBooleanConstant(previous_bytecode.GetOperand(0) != 0); |
624 break; | 637 break; |
625 } | 638 } |
(...skipping 10 matching lines...) Expand all Loading... |
636 } | 649 } |
637 | 650 |
638 | 651 |
639 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() { | 652 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() { |
640 Output(Bytecode::kToObject); | 653 Output(Bytecode::kToObject); |
641 return *this; | 654 return *this; |
642 } | 655 } |
643 | 656 |
644 | 657 |
645 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { | 658 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { |
646 PreviousBytecodeHelper previous_bytecode(*this); | 659 if (LastBytecodeInSameBlock()) { |
647 switch (previous_bytecode.GetBytecode()) { | 660 PreviousBytecodeHelper previous_bytecode(*this); |
648 case Bytecode::kLdaConstantWide: | 661 switch (previous_bytecode.GetBytecode()) { |
649 case Bytecode::kLdaConstant: { | 662 case Bytecode::kToName: |
650 Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0); | 663 case Bytecode::kTypeOf: |
651 if (object->IsName()) return *this; | 664 return *this; |
652 break; | 665 case Bytecode::kLdaConstantWide: |
| 666 case Bytecode::kLdaConstant: { |
| 667 Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0); |
| 668 if (object->IsName()) return *this; |
| 669 break; |
| 670 } |
| 671 default: |
| 672 break; |
653 } | 673 } |
654 case Bytecode::kToName: | |
655 case Bytecode::kTypeOf: | |
656 return *this; | |
657 default: | |
658 break; | |
659 } | 674 } |
660 Output(Bytecode::kToName); | 675 Output(Bytecode::kToName); |
661 return *this; | 676 return *this; |
662 } | 677 } |
663 | 678 |
664 | 679 |
665 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToNumber() { | 680 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToNumber() { |
666 // TODO(rmcilroy): consider omitting if the preceeding bytecode always returns | 681 // TODO(rmcilroy): consider omitting if the preceeding bytecode always returns |
667 // a number. | 682 // a number. |
668 Output(Bytecode::kToNumber); | 683 Output(Bytecode::kToNumber); |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 } | 1097 } |
1083 | 1098 |
1084 | 1099 |
1085 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { | 1100 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { |
1086 return last_bytecode_start_ < bytecodes()->size() && | 1101 return last_bytecode_start_ < bytecodes()->size() && |
1087 last_bytecode_start_ >= last_block_end_; | 1102 last_bytecode_start_ >= last_block_end_; |
1088 } | 1103 } |
1089 | 1104 |
1090 | 1105 |
1091 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { | 1106 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { |
1092 PreviousBytecodeHelper previous_bytecode(*this); | 1107 if (LastBytecodeInSameBlock()) { |
1093 if (previous_bytecode.GetBytecode() == Bytecode::kLdar || | 1108 PreviousBytecodeHelper previous_bytecode(*this); |
1094 previous_bytecode.GetBytecode() == Bytecode::kStar) { | 1109 Bytecode bytecode = previous_bytecode.GetBytecode(); |
1095 if (reg == Register::FromOperand(previous_bytecode.GetOperand(0))) { | 1110 if ((bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) && |
| 1111 (reg == Register::FromOperand(previous_bytecode.GetOperand(0)))) { |
1096 return true; | 1112 return true; |
1097 } | 1113 } |
1098 } | 1114 } |
1099 return false; | 1115 return false; |
1100 } | 1116 } |
1101 | 1117 |
1102 | 1118 |
1103 // static | 1119 // static |
1104 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { | 1120 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { |
1105 switch (op) { | 1121 switch (op) { |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1424 DCHECK_GT(next_consecutive_count_, 0); | 1440 DCHECK_GT(next_consecutive_count_, 0); |
1425 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); | 1441 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); |
1426 allocated_.push_back(next_consecutive_register_); | 1442 allocated_.push_back(next_consecutive_register_); |
1427 next_consecutive_count_--; | 1443 next_consecutive_count_--; |
1428 return Register(next_consecutive_register_++); | 1444 return Register(next_consecutive_register_++); |
1429 } | 1445 } |
1430 | 1446 |
1431 } // namespace interpreter | 1447 } // namespace interpreter |
1432 } // namespace internal | 1448 } // namespace internal |
1433 } // namespace v8 | 1449 } // namespace v8 |
OLD | NEW |