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 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
270 return *this; | 270 return *this; |
271 } | 271 } |
272 | 272 |
273 | 273 |
274 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { | 274 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { |
275 Output(Bytecode::kLdaFalse); | 275 Output(Bytecode::kLdaFalse); |
276 return *this; | 276 return *this; |
277 } | 277 } |
278 | 278 |
279 | 279 |
280 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBooleanConstant(bool value) { | |
281 if (value) { | |
282 LoadTrue(); | |
283 } else { | |
284 LoadFalse(); | |
285 } | |
286 return *this; | |
287 } | |
288 | |
289 | |
280 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( | 290 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( |
281 Register reg) { | 291 Register reg) { |
282 if (!IsRegisterInAccumulator(reg)) { | 292 if (!IsRegisterInAccumulator(reg)) { |
283 Output(Bytecode::kLdar, reg.ToOperand()); | 293 Output(Bytecode::kLdar, reg.ToOperand()); |
284 } | 294 } |
285 return *this; | 295 return *this; |
286 } | 296 } |
287 | 297 |
288 | 298 |
289 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( | 299 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
506 } | 516 } |
507 | 517 |
508 | 518 |
509 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { | 519 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { |
510 Output(Bytecode::kPopContext, context.ToOperand()); | 520 Output(Bytecode::kPopContext, context.ToOperand()); |
511 return *this; | 521 return *this; |
512 } | 522 } |
513 | 523 |
514 | 524 |
515 bool BytecodeArrayBuilder::NeedToBooleanCast() { | 525 bool BytecodeArrayBuilder::NeedToBooleanCast() { |
516 if (!LastBytecodeInSameBlock()) { | 526 switch (GetPreviousBytecodeInSameBlock()) { |
517 // If the previous bytecode was from a different block return false. | |
518 return true; | |
519 } | |
520 | |
521 // If the previous bytecode puts a boolean in the accumulator return true. | |
522 switch (Bytecodes::FromByte(bytecodes()->at(last_bytecode_start_))) { | |
523 case Bytecode::kToBoolean: | 527 case Bytecode::kToBoolean: |
524 UNREACHABLE(); | 528 UNREACHABLE(); |
529 // If the previous bytecode puts a boolean in the accumulator return true. | |
525 case Bytecode::kLdaTrue: | 530 case Bytecode::kLdaTrue: |
526 case Bytecode::kLdaFalse: | 531 case Bytecode::kLdaFalse: |
527 case Bytecode::kLogicalNot: | 532 case Bytecode::kLogicalNot: |
528 case Bytecode::kTestEqual: | 533 case Bytecode::kTestEqual: |
529 case Bytecode::kTestNotEqual: | 534 case Bytecode::kTestNotEqual: |
530 case Bytecode::kTestEqualStrict: | 535 case Bytecode::kTestEqualStrict: |
531 case Bytecode::kTestNotEqualStrict: | 536 case Bytecode::kTestNotEqualStrict: |
532 case Bytecode::kTestLessThan: | 537 case Bytecode::kTestLessThan: |
533 case Bytecode::kTestLessThanOrEqual: | 538 case Bytecode::kTestLessThanOrEqual: |
534 case Bytecode::kTestGreaterThan: | 539 case Bytecode::kTestGreaterThan: |
535 case Bytecode::kTestGreaterThanOrEqual: | 540 case Bytecode::kTestGreaterThanOrEqual: |
536 case Bytecode::kTestInstanceOf: | 541 case Bytecode::kTestInstanceOf: |
537 case Bytecode::kTestIn: | 542 case Bytecode::kTestIn: |
538 case Bytecode::kForInDone: | 543 case Bytecode::kForInDone: |
539 return false; | 544 return false; |
545 // Also handles the case where the previous bytecode was in a different | |
546 // block. | |
540 default: | 547 default: |
541 return true; | 548 return true; |
542 } | 549 } |
543 } | 550 } |
544 | 551 |
545 | 552 |
546 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { | 553 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { |
547 // If the previous bytecode puts a boolean in the accumulator | 554 // If the previous bytecode puts a boolean in the accumulator |
548 // there is no need to emit an instruction. | 555 // there is no need to emit an instruction. |
549 if (NeedToBooleanCast()) { | 556 if (NeedToBooleanCast()) { |
550 Output(Bytecode::kToBoolean); | 557 switch (GetPreviousBytecodeInSameBlock()) { |
558 // If the previous bytecode is a constant evaluate it and return false. | |
559 case Bytecode::kLdaZero: { | |
560 LoadFalse(); | |
561 break; | |
562 } | |
563 case Bytecode::kLdaSmi8: { | |
564 LoadBooleanConstant(GetRawOperand(0) != 0); | |
565 break; | |
566 } | |
567 case Bytecode::kLdaConstant: { | |
568 Handle<Object> object = GetConstantForIndexOperand(0); | |
569 LoadBooleanConstant(object->BooleanValue()); | |
570 break; | |
571 } | |
572 default: | |
573 Output(Bytecode::kToBoolean); | |
574 } | |
551 } | 575 } |
552 return *this; | 576 return *this; |
553 } | 577 } |
554 | 578 |
555 | 579 |
556 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() { | 580 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() { |
557 Output(Bytecode::kToObject); | 581 Output(Bytecode::kToObject); |
558 return *this; | 582 return *this; |
559 } | 583 } |
560 | 584 |
561 | 585 |
562 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { | 586 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { |
587 Bytecode prev_bytecode = GetPreviousBytecodeInSameBlock(); | |
588 switch (prev_bytecode) { | |
589 case Bytecode::kLdaConstantWide: | |
590 case Bytecode::kLdaConstant: { | |
591 Handle<Object> object = GetConstantForIndexOperand(0); | |
592 if (object->IsName()) return *this; | |
593 break; | |
594 } | |
595 case Bytecode::kToName: | |
596 case Bytecode::kTypeOf: | |
597 return *this; | |
598 default: | |
599 break; | |
600 } | |
563 Output(Bytecode::kToName); | 601 Output(Bytecode::kToName); |
564 return *this; | 602 return *this; |
565 } | 603 } |
566 | 604 |
567 | 605 |
568 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToNumber() { | 606 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToNumber() { |
569 // TODO(rmcilroy): consider omitting if the preceeding bytecode always returns | 607 // TODO(rmcilroy): consider omitting if the preceeding bytecode always returns |
570 // a number. | 608 // a number. |
571 Output(Bytecode::kToNumber); | 609 Output(Bytecode::kToNumber); |
572 return *this; | 610 return *this; |
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
983 return false; | 1021 return false; |
984 } | 1022 } |
985 | 1023 |
986 | 1024 |
987 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { | 1025 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { |
988 return last_bytecode_start_ < bytecodes()->size() && | 1026 return last_bytecode_start_ < bytecodes()->size() && |
989 last_bytecode_start_ >= last_block_end_; | 1027 last_bytecode_start_ >= last_block_end_; |
990 } | 1028 } |
991 | 1029 |
992 | 1030 |
1031 Bytecode BytecodeArrayBuilder::GetPreviousBytecodeInSameBlock() const { | |
oth
2015/11/23 13:46:41
Suggest renaming to GetPreviousBytecode() as the m
mythria
2015/11/24 12:58:48
I added a helper class that takes BytecodeArrayBui
| |
1032 // Returns the previous bytecode in the same basicblock. If there is none it | |
1033 // returns Bytecode::kLast. | |
1034 if (!LastBytecodeInSameBlock()) { | |
1035 return Bytecode::kLast; | |
1036 } | |
1037 return Bytecodes::FromByte(bytecodes()->at(last_bytecode_start_)); | |
1038 } | |
1039 | |
1040 | |
1041 uint32_t BytecodeArrayBuilder::GetRawOperand(int operand_index) const { | |
oth
2015/11/23 13:46:41
For clarity, it would be better to call this somet
| |
1042 Bytecode bytecode = GetPreviousBytecodeInSameBlock(); | |
1043 DCHECK_GE(operand_index, 0); | |
1044 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); | |
1045 size_t operand_offset = last_bytecode_start_ + | |
1046 Bytecodes::GetOperandOffset(bytecode, operand_index); | |
1047 OperandSize size = Bytecodes::GetOperandSize(GetPreviousBytecodeInSameBlock(), | |
1048 operand_index); | |
1049 switch (size) { | |
1050 default: | |
1051 case OperandSize::kNone: | |
1052 UNREACHABLE(); | |
1053 case OperandSize::kByte: | |
1054 return static_cast<uint32_t>(bytecodes()->at(operand_offset)); | |
1055 case OperandSize::kShort: | |
1056 uint16_t operand = (bytecodes()->at(operand_offset) << 8) + | |
1057 bytecodes()->at(operand_offset + 1); | |
1058 return static_cast<uint32_t>(operand); | |
1059 } | |
1060 } | |
1061 | |
1062 | |
1063 Handle<Object> BytecodeArrayBuilder::GetConstantForIndexOperand( | |
oth
2015/11/23 13:46:41
GetConstantForIndexOperandOfPreviousBytecode(). Ph
| |
1064 int operand_index) { | |
1065 return constants_.at(GetRawOperand(operand_index)); | |
1066 } | |
1067 | |
1068 | |
993 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { | 1069 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { |
994 if (!LastBytecodeInSameBlock()) return false; | 1070 Bytecode previous_bytecode = GetPreviousBytecodeInSameBlock(); |
995 Bytecode previous_bytecode = | |
996 Bytecodes::FromByte(bytecodes()->at(last_bytecode_start_)); | |
997 if (previous_bytecode == Bytecode::kLdar || | 1071 if (previous_bytecode == Bytecode::kLdar || |
998 previous_bytecode == Bytecode::kStar) { | 1072 previous_bytecode == Bytecode::kStar) { |
999 size_t operand_offset = last_bytecode_start_ + | 1073 if (reg == Register::FromOperand(GetRawOperand(0))) { |
1000 Bytecodes::GetOperandOffset(previous_bytecode, 0); | |
1001 if (reg == Register::FromOperand(bytecodes()->at(operand_offset))) { | |
1002 return true; | 1074 return true; |
1003 } | 1075 } |
1004 } | 1076 } |
1005 return false; | 1077 return false; |
1006 } | 1078 } |
1007 | 1079 |
1008 | 1080 |
1009 // static | 1081 // static |
1010 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { | 1082 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { |
1011 switch (op) { | 1083 switch (op) { |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1330 DCHECK_GT(next_consecutive_count_, 0); | 1402 DCHECK_GT(next_consecutive_count_, 0); |
1331 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); | 1403 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); |
1332 allocated_.push_back(next_consecutive_register_); | 1404 allocated_.push_back(next_consecutive_register_); |
1333 next_consecutive_count_--; | 1405 next_consecutive_count_--; |
1334 return Register(next_consecutive_register_++); | 1406 return Register(next_consecutive_register_++); |
1335 } | 1407 } |
1336 | 1408 |
1337 } // namespace interpreter | 1409 } // namespace interpreter |
1338 } // namespace internal | 1410 } // namespace internal |
1339 } // namespace v8 | 1411 } // namespace v8 |
OLD | NEW |