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 | 
| 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 // This helper is expected to be instantiated only when the last bytecode is | |
| 16 // in the same basicblock. | |
| 
 
rmcilroy
2015/12/08 13:43:02
/s/basicblock/basic block/ throughout, and also in
 
mythria
2015/12/08 14:53:29
Done.
 
 | |
| 17 CHECK(array_builder_.LastBytecodeInSameBlock()); | |
| 
 
rmcilroy
2015/12/08 13:43:02
DCHECK is fine here I think.
 
mythria
2015/12/08 14:53:29
Done.
 
 | |
| 18 } | |
| 15 | 19 | 
| 16 Bytecode GetBytecode() const { | 20 // Returns the previous bytecode in the same basicblock. Expects that the | 
| 17 // Returns the previous bytecode in the same basicblock. If there is none it | 21 // lastbytecode is in the same basicblock. | 
| 
 
rmcilroy
2015/12/08 13:43:02
/s/lastbytecode/last bytecode/. Actually, there is
 
mythria
2015/12/08 14:53:29
Done.
 
 | |
| 18 // returns Bytecode::kLast. | 22 MUST_USE_RESULT Bytecode GetBytecode() const { | 
| 19 if (!array_builder_.LastBytecodeInSameBlock()) { | 23 DCHECK(array_builder_.LastBytecodeInSameBlock()); | 
| 
 
rmcilroy
2015/12/08 13:43:02
Rather than DCHECKING this (which is already CHECK
 
mythria
2015/12/08 14:53:29
Done.
 
 | |
| 20 return Bytecode::kLast; | |
| 21 } | |
| 22 return Bytecodes::FromByte( | 24 return Bytecodes::FromByte( | 
| 23 array_builder_.bytecodes()->at(array_builder_.last_bytecode_start_)); | 25 array_builder_.bytecodes()->at(array_builder_.last_bytecode_start_)); | 
| 24 } | 26 } | 
| 25 | 27 | 
| 26 uint32_t GetOperand(int operand_index) const { | 28 // Returns the operand at operand_index for the previous bytecode. Expects | 
| 29 // that the previous bytecode is in the same basicblock. | |
| 
 
rmcilroy
2015/12/08 13:43:02
ditto for the last sentence.
 
mythria
2015/12/08 14:53:29
Done.
 
 | |
| 30 MUST_USE_RESULT uint32_t GetOperand(int operand_index) const { | |
| 27 Bytecode bytecode = GetBytecode(); | 31 Bytecode bytecode = GetBytecode(); | 
| 28 DCHECK_GE(operand_index, 0); | 32 DCHECK_GE(operand_index, 0); | 
| 29 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); | 33 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); | 
| 30 size_t operand_offset = | 34 size_t operand_offset = | 
| 31 array_builder_.last_bytecode_start_ + | 35 array_builder_.last_bytecode_start_ + | 
| 32 Bytecodes::GetOperandOffset(bytecode, operand_index); | 36 Bytecodes::GetOperandOffset(bytecode, operand_index); | 
| 33 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); | 37 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); | 
| 34 switch (size) { | 38 switch (size) { | 
| 35 default: | 39 default: | 
| 36 case OperandSize::kNone: | 40 case OperandSize::kNone: | 
| 37 UNREACHABLE(); | 41 UNREACHABLE(); | 
| 38 case OperandSize::kByte: | 42 case OperandSize::kByte: | 
| 39 return static_cast<uint32_t>( | 43 return static_cast<uint32_t>( | 
| 40 array_builder_.bytecodes()->at(operand_offset)); | 44 array_builder_.bytecodes()->at(operand_offset)); | 
| 41 case OperandSize::kShort: | 45 case OperandSize::kShort: | 
| 42 uint16_t operand = | 46 uint16_t operand = | 
| 43 (array_builder_.bytecodes()->at(operand_offset) << 8) + | 47 (array_builder_.bytecodes()->at(operand_offset) << 8) + | 
| 44 array_builder_.bytecodes()->at(operand_offset + 1); | 48 array_builder_.bytecodes()->at(operand_offset + 1); | 
| 45 return static_cast<uint32_t>(operand); | 49 return static_cast<uint32_t>(operand); | 
| 46 } | 50 } | 
| 47 } | 51 } | 
| 48 | 52 | 
| 49 Handle<Object> GetConstantForIndexOperand(int operand_index) const { | 53 Handle<Object> GetConstantForIndexOperand(int operand_index) const { | 
| 50 return array_builder_.constants_.at(GetOperand(operand_index)); | 54 return array_builder_.constants_.at(GetOperand(operand_index)); | 
| 51 } | 55 } | 
| 52 | 56 | 
| 53 private: | 57 private: | 
| 54 const BytecodeArrayBuilder& array_builder_; | 58 const BytecodeArrayBuilder& array_builder_; | 
| 59 DISALLOW_COPY_AND_ASSIGN(PreviousBytecodeHelper); | |
| 
 
rmcilroy
2015/12/08 13:43:02
nit - newline above
 
mythria
2015/12/08 14:53:29
Done.
 
 | |
| 55 }; | 60 }; | 
| 56 | 61 | 
| 57 | 62 | 
| 58 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) | 63 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) | 
| 59 : isolate_(isolate), | 64 : isolate_(isolate), | 
| 60 zone_(zone), | 65 zone_(zone), | 
| 61 bytecodes_(zone), | 66 bytecodes_(zone), | 
| 62 bytecode_generated_(false), | 67 bytecode_generated_(false), | 
| 63 last_block_end_(0), | 68 last_block_end_(0), | 
| 64 last_bytecode_start_(~0), | 69 last_bytecode_start_(~0), | 
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 573 } | 578 } | 
| 574 | 579 | 
| 575 | 580 | 
| 576 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { | 581 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { | 
| 577 Output(Bytecode::kPopContext, context.ToOperand()); | 582 Output(Bytecode::kPopContext, context.ToOperand()); | 
| 578 return *this; | 583 return *this; | 
| 579 } | 584 } | 
| 580 | 585 | 
| 581 | 586 | 
| 582 bool BytecodeArrayBuilder::NeedToBooleanCast() { | 587 bool BytecodeArrayBuilder::NeedToBooleanCast() { | 
| 588 if (!LastBytecodeInSameBlock()) { | |
| 589 return true; | |
| 590 } | |
| 583 PreviousBytecodeHelper previous_bytecode(*this); | 591 PreviousBytecodeHelper previous_bytecode(*this); | 
| 584 switch (previous_bytecode.GetBytecode()) { | 592 switch (previous_bytecode.GetBytecode()) { | 
| 585 case Bytecode::kToBoolean: | 593 case Bytecode::kToBoolean: | 
| 586 UNREACHABLE(); | 594 UNREACHABLE(); | 
| 587 // If the previous bytecode puts a boolean in the accumulator return true. | 595 // If the previous bytecode puts a boolean in the accumulator return true. | 
| 588 case Bytecode::kLdaTrue: | 596 case Bytecode::kLdaTrue: | 
| 589 case Bytecode::kLdaFalse: | 597 case Bytecode::kLdaFalse: | 
| 590 case Bytecode::kLogicalNot: | 598 case Bytecode::kLogicalNot: | 
| 591 case Bytecode::kTestEqual: | 599 case Bytecode::kTestEqual: | 
| 592 case Bytecode::kTestNotEqual: | 600 case Bytecode::kTestNotEqual: | 
| 593 case Bytecode::kTestEqualStrict: | 601 case Bytecode::kTestEqualStrict: | 
| 594 case Bytecode::kTestNotEqualStrict: | 602 case Bytecode::kTestNotEqualStrict: | 
| 595 case Bytecode::kTestLessThan: | 603 case Bytecode::kTestLessThan: | 
| 596 case Bytecode::kTestLessThanOrEqual: | 604 case Bytecode::kTestLessThanOrEqual: | 
| 597 case Bytecode::kTestGreaterThan: | 605 case Bytecode::kTestGreaterThan: | 
| 598 case Bytecode::kTestGreaterThanOrEqual: | 606 case Bytecode::kTestGreaterThanOrEqual: | 
| 599 case Bytecode::kTestInstanceOf: | 607 case Bytecode::kTestInstanceOf: | 
| 600 case Bytecode::kTestIn: | 608 case Bytecode::kTestIn: | 
| 601 case Bytecode::kForInDone: | 609 case Bytecode::kForInDone: | 
| 602 return false; | 610 return false; | 
| 603 // Also handles the case where the previous bytecode was in a different | |
| 604 // block. | |
| 605 default: | 611 default: | 
| 606 return true; | 612 return true; | 
| 607 } | 613 } | 
| 608 } | 614 } | 
| 609 | 615 | 
| 610 | 616 | 
| 611 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { | 617 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { | 
| 612 PreviousBytecodeHelper previous_bytecode(*this); | 618 if (!LastBytecodeInSameBlock()) { | 
| 619 Output(Bytecode::kToBoolean); | |
| 620 return *this; | |
| 621 } | |
| 613 // If the previous bytecode puts a boolean in the accumulator | 622 // If the previous bytecode puts a boolean in the accumulator | 
| 614 // there is no need to emit an instruction. | 623 // there is no need to emit an instruction. | 
| 615 if (NeedToBooleanCast()) { | 624 if (NeedToBooleanCast()) { | 
| 625 PreviousBytecodeHelper previous_bytecode(*this); | |
| 616 switch (previous_bytecode.GetBytecode()) { | 626 switch (previous_bytecode.GetBytecode()) { | 
| 617 // If the previous bytecode is a constant evaluate it and return false. | 627 // If the previous bytecode is a constant evaluate it and return false. | 
| 618 case Bytecode::kLdaZero: { | 628 case Bytecode::kLdaZero: { | 
| 619 LoadFalse(); | 629 LoadFalse(); | 
| 620 break; | 630 break; | 
| 621 } | 631 } | 
| 622 case Bytecode::kLdaSmi8: { | 632 case Bytecode::kLdaSmi8: { | 
| 623 LoadBooleanConstant(previous_bytecode.GetOperand(0) != 0); | 633 LoadBooleanConstant(previous_bytecode.GetOperand(0) != 0); | 
| 624 break; | 634 break; | 
| 625 } | 635 } | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 636 } | 646 } | 
| 637 | 647 | 
| 638 | 648 | 
| 639 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() { | 649 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() { | 
| 640 Output(Bytecode::kToObject); | 650 Output(Bytecode::kToObject); | 
| 641 return *this; | 651 return *this; | 
| 642 } | 652 } | 
| 643 | 653 | 
| 644 | 654 | 
| 645 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { | 655 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { | 
| 656 if (!LastBytecodeInSameBlock()) { | |
| 
 
rmcilroy
2015/12/08 13:43:02
If you reverse this (do the check for if (LastByte
 
mythria
2015/12/08 14:53:29
Done.
 
 | |
| 657 Output(Bytecode::kToName); | |
| 658 return *this; | |
| 659 } | |
| 646 PreviousBytecodeHelper previous_bytecode(*this); | 660 PreviousBytecodeHelper previous_bytecode(*this); | 
| 647 switch (previous_bytecode.GetBytecode()) { | 661 switch (previous_bytecode.GetBytecode()) { | 
| 662 case Bytecode::kToName: | |
| 663 case Bytecode::kTypeOf: | |
| 664 return *this; | |
| 648 case Bytecode::kLdaConstantWide: | 665 case Bytecode::kLdaConstantWide: | 
| 649 case Bytecode::kLdaConstant: { | 666 case Bytecode::kLdaConstant: { | 
| 650 Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0); | 667 Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0); | 
| 651 if (object->IsName()) return *this; | 668 if (object->IsName()) return *this; | 
| 652 break; | 669 break; | 
| 653 } | 670 } | 
| 654 case Bytecode::kToName: | |
| 655 case Bytecode::kTypeOf: | |
| 656 return *this; | |
| 657 default: | 671 default: | 
| 658 break; | 672 break; | 
| 659 } | 673 } | 
| 660 Output(Bytecode::kToName); | 674 Output(Bytecode::kToName); | 
| 661 return *this; | 675 return *this; | 
| 662 } | 676 } | 
| 663 | 677 | 
| 664 | 678 | 
| 665 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToNumber() { | 679 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToNumber() { | 
| 666 // TODO(rmcilroy): consider omitting if the preceeding bytecode always returns | 680 // TODO(rmcilroy): consider omitting if the preceeding bytecode always returns | 
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1082 } | 1096 } | 
| 1083 | 1097 | 
| 1084 | 1098 | 
| 1085 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { | 1099 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { | 
| 1086 return last_bytecode_start_ < bytecodes()->size() && | 1100 return last_bytecode_start_ < bytecodes()->size() && | 
| 1087 last_bytecode_start_ >= last_block_end_; | 1101 last_bytecode_start_ >= last_block_end_; | 
| 1088 } | 1102 } | 
| 1089 | 1103 | 
| 1090 | 1104 | 
| 1091 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { | 1105 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { | 
| 1106 if (!LastBytecodeInSameBlock()) { | |
| 
 
rmcilroy
2015/12/08 13:43:02
ditto (avoids double return false)
 
mythria
2015/12/08 14:53:28
Done.
 
 | |
| 1107 return false; | |
| 1108 } | |
| 1092 PreviousBytecodeHelper previous_bytecode(*this); | 1109 PreviousBytecodeHelper previous_bytecode(*this); | 
| 1093 if (previous_bytecode.GetBytecode() == Bytecode::kLdar || | 1110 Bytecode bytecode = previous_bytecode.GetBytecode(); | 
| 1094 previous_bytecode.GetBytecode() == Bytecode::kStar) { | 1111 if ((bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) && | 
| 1095 if (reg == Register::FromOperand(previous_bytecode.GetOperand(0))) { | 1112 (reg == Register::FromOperand(previous_bytecode.GetOperand(0)))) { | 
| 1096 return true; | 1113 return true; | 
| 1097 } | |
| 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) { | 
| 1106 case Token::Value::ADD: | 1122 case Token::Value::ADD: | 
| 1107 return Bytecode::kAdd; | 1123 return Bytecode::kAdd; | 
| (...skipping 316 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 |