| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 | 86 |
| 87 void LLabel::PrintDataTo(StringStream* stream) const { | 87 void LLabel::PrintDataTo(StringStream* stream) const { |
| 88 LGap::PrintDataTo(stream); | 88 LGap::PrintDataTo(stream); |
| 89 LLabel* rep = replacement(); | 89 LLabel* rep = replacement(); |
| 90 if (rep != NULL) { | 90 if (rep != NULL) { |
| 91 stream->Add(" Dead block replaced with B%d", rep->block_id()); | 91 stream->Add(" Dead block replaced with B%d", rep->block_id()); |
| 92 } | 92 } |
| 93 } | 93 } |
| 94 | 94 |
| 95 | 95 |
| 96 bool LParallelMove::IsRedundant() const { | |
| 97 for (int i = 0; i < move_operands_.length(); ++i) { | |
| 98 if (!move_operands_[i].IsRedundant()) return false; | |
| 99 } | |
| 100 return true; | |
| 101 } | |
| 102 | |
| 103 | |
| 104 void LParallelMove::PrintDataTo(StringStream* stream) const { | |
| 105 for (int i = move_operands_.length() - 1; i >= 0; --i) { | |
| 106 if (!move_operands_[i].IsEliminated()) { | |
| 107 LOperand* from = move_operands_[i].from(); | |
| 108 LOperand* to = move_operands_[i].to(); | |
| 109 if (from->Equals(to)) { | |
| 110 to->PrintTo(stream); | |
| 111 } else { | |
| 112 to->PrintTo(stream); | |
| 113 stream->Add(" = "); | |
| 114 from->PrintTo(stream); | |
| 115 } | |
| 116 stream->Add("; "); | |
| 117 } | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 | |
| 122 bool LGap::IsRedundant() const { | 96 bool LGap::IsRedundant() const { |
| 123 for (int i = 0; i < 4; i++) { | 97 for (int i = 0; i < 4; i++) { |
| 124 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) { | 98 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) { |
| 125 return false; | 99 return false; |
| 126 } | 100 } |
| 127 } | 101 } |
| 128 | 102 |
| 129 return true; | 103 return true; |
| 130 } | 104 } |
| 131 | 105 |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 while (!IsGapAt(index)) index--; | 439 while (!IsGapAt(index)) index--; |
| 466 return index; | 440 return index; |
| 467 } | 441 } |
| 468 | 442 |
| 469 | 443 |
| 470 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) { | 444 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) { |
| 471 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to); | 445 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to); |
| 472 } | 446 } |
| 473 | 447 |
| 474 | 448 |
| 475 class LGapNode: public ZoneObject { | |
| 476 public: | |
| 477 explicit LGapNode(LOperand* operand) | |
| 478 : operand_(operand), resolved_(false), visited_id_(-1) { } | |
| 479 | |
| 480 LOperand* operand() const { return operand_; } | |
| 481 bool IsResolved() const { return !IsAssigned() || resolved_; } | |
| 482 void MarkResolved() { | |
| 483 ASSERT(!IsResolved()); | |
| 484 resolved_ = true; | |
| 485 } | |
| 486 int visited_id() const { return visited_id_; } | |
| 487 void set_visited_id(int id) { | |
| 488 ASSERT(id > visited_id_); | |
| 489 visited_id_ = id; | |
| 490 } | |
| 491 | |
| 492 bool IsAssigned() const { return assigned_from_.is_set(); } | |
| 493 LGapNode* assigned_from() const { return assigned_from_.get(); } | |
| 494 void set_assigned_from(LGapNode* n) { assigned_from_.set(n); } | |
| 495 | |
| 496 private: | |
| 497 LOperand* operand_; | |
| 498 SetOncePointer<LGapNode> assigned_from_; | |
| 499 bool resolved_; | |
| 500 int visited_id_; | |
| 501 }; | |
| 502 | |
| 503 | |
| 504 LGapResolver::LGapResolver(const ZoneList<LMoveOperands>* moves, | |
| 505 LOperand* marker_operand) | |
| 506 : nodes_(4), | |
| 507 identified_cycles_(4), | |
| 508 result_(4), | |
| 509 marker_operand_(marker_operand), | |
| 510 next_visited_id_(0) { | |
| 511 for (int i = 0; i < moves->length(); ++i) { | |
| 512 LMoveOperands move = moves->at(i); | |
| 513 if (!move.IsRedundant()) RegisterMove(move); | |
| 514 } | |
| 515 } | |
| 516 | |
| 517 | |
| 518 const ZoneList<LMoveOperands>* LGapResolver::ResolveInReverseOrder() { | |
| 519 for (int i = 0; i < identified_cycles_.length(); ++i) { | |
| 520 ResolveCycle(identified_cycles_[i]); | |
| 521 } | |
| 522 | |
| 523 int unresolved_nodes; | |
| 524 do { | |
| 525 unresolved_nodes = 0; | |
| 526 for (int j = 0; j < nodes_.length(); j++) { | |
| 527 LGapNode* node = nodes_[j]; | |
| 528 if (!node->IsResolved() && node->assigned_from()->IsResolved()) { | |
| 529 AddResultMove(node->assigned_from(), node); | |
| 530 node->MarkResolved(); | |
| 531 } | |
| 532 if (!node->IsResolved()) ++unresolved_nodes; | |
| 533 } | |
| 534 } while (unresolved_nodes > 0); | |
| 535 return &result_; | |
| 536 } | |
| 537 | |
| 538 | |
| 539 void LGapResolver::AddResultMove(LGapNode* from, LGapNode* to) { | |
| 540 AddResultMove(from->operand(), to->operand()); | |
| 541 } | |
| 542 | |
| 543 | |
| 544 void LGapResolver::AddResultMove(LOperand* from, LOperand* to) { | |
| 545 result_.Add(LMoveOperands(from, to)); | |
| 546 } | |
| 547 | |
| 548 | |
| 549 void LGapResolver::ResolveCycle(LGapNode* start) { | |
| 550 ZoneList<LOperand*> circle_operands(8); | |
| 551 circle_operands.Add(marker_operand_); | |
| 552 LGapNode* cur = start; | |
| 553 do { | |
| 554 cur->MarkResolved(); | |
| 555 circle_operands.Add(cur->operand()); | |
| 556 cur = cur->assigned_from(); | |
| 557 } while (cur != start); | |
| 558 circle_operands.Add(marker_operand_); | |
| 559 | |
| 560 for (int i = circle_operands.length() - 1; i > 0; --i) { | |
| 561 LOperand* from = circle_operands[i]; | |
| 562 LOperand* to = circle_operands[i - 1]; | |
| 563 AddResultMove(from, to); | |
| 564 } | |
| 565 } | |
| 566 | |
| 567 | |
| 568 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b, int visited_id) { | |
| 569 ASSERT(a != b); | |
| 570 LGapNode* cur = a; | |
| 571 while (cur != b && cur->visited_id() != visited_id && cur->IsAssigned()) { | |
| 572 cur->set_visited_id(visited_id); | |
| 573 cur = cur->assigned_from(); | |
| 574 } | |
| 575 | |
| 576 return cur == b; | |
| 577 } | |
| 578 | |
| 579 | |
| 580 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b) { | |
| 581 ASSERT(a != b); | |
| 582 return CanReach(a, b, next_visited_id_++); | |
| 583 } | |
| 584 | |
| 585 | |
| 586 void LGapResolver::RegisterMove(LMoveOperands move) { | |
| 587 if (move.from()->IsConstantOperand()) { | |
| 588 // Constant moves should be last in the machine code. Therefore add them | |
| 589 // first to the result set. | |
| 590 AddResultMove(move.from(), move.to()); | |
| 591 } else { | |
| 592 LGapNode* from = LookupNode(move.from()); | |
| 593 LGapNode* to = LookupNode(move.to()); | |
| 594 if (to->IsAssigned() && to->assigned_from() == from) { | |
| 595 move.Eliminate(); | |
| 596 return; | |
| 597 } | |
| 598 ASSERT(!to->IsAssigned()); | |
| 599 if (CanReach(from, to)) { | |
| 600 // This introduces a circle. Save. | |
| 601 identified_cycles_.Add(from); | |
| 602 } | |
| 603 to->set_assigned_from(from); | |
| 604 } | |
| 605 } | |
| 606 | |
| 607 | |
| 608 LGapNode* LGapResolver::LookupNode(LOperand* operand) { | |
| 609 for (int i = 0; i < nodes_.length(); ++i) { | |
| 610 if (nodes_[i]->operand()->Equals(operand)) return nodes_[i]; | |
| 611 } | |
| 612 | |
| 613 // No node found => create a new one. | |
| 614 LGapNode* result = new LGapNode(operand); | |
| 615 nodes_.Add(result); | |
| 616 return result; | |
| 617 } | |
| 618 | |
| 619 | |
| 620 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const { | 449 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const { |
| 621 return HConstant::cast(graph_->LookupValue(operand->index()))->handle(); | 450 return HConstant::cast(graph_->LookupValue(operand->index()))->handle(); |
| 622 } | 451 } |
| 623 | 452 |
| 624 | 453 |
| 625 Representation LChunk::LookupLiteralRepresentation( | 454 Representation LChunk::LookupLiteralRepresentation( |
| 626 LConstantOperand* operand) const { | 455 LConstantOperand* operand) const { |
| 627 return graph_->LookupValue(operand->index())->representation(); | 456 return graph_->LookupValue(operand->index())->representation(); |
| 628 } | 457 } |
| 629 | 458 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 LInstruction* LChunkBuilder::DefineAsRegister(LInstruction* instr) { | 589 LInstruction* LChunkBuilder::DefineAsRegister(LInstruction* instr) { |
| 761 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); | 590 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); |
| 762 } | 591 } |
| 763 | 592 |
| 764 | 593 |
| 765 LInstruction* LChunkBuilder::DefineAsSpilled(LInstruction* instr, int index) { | 594 LInstruction* LChunkBuilder::DefineAsSpilled(LInstruction* instr, int index) { |
| 766 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index)); | 595 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index)); |
| 767 } | 596 } |
| 768 | 597 |
| 769 | 598 |
| 770 LInstruction* LChunkBuilder::DefineSameAsAny(LInstruction* instr) { | |
| 771 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_ANY_INPUT)); | |
| 772 } | |
| 773 | |
| 774 | |
| 775 LInstruction* LChunkBuilder::DefineSameAsFirst(LInstruction* instr) { | 599 LInstruction* LChunkBuilder::DefineSameAsFirst(LInstruction* instr) { |
| 776 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); | 600 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); |
| 777 } | 601 } |
| 778 | 602 |
| 779 | 603 |
| 780 LInstruction* LChunkBuilder::DefineFixed(LInstruction* instr, Register reg) { | 604 LInstruction* LChunkBuilder::DefineFixed(LInstruction* instr, Register reg) { |
| 781 return Define(instr, ToUnallocated(reg)); | 605 return Define(instr, ToUnallocated(reg)); |
| 782 } | 606 } |
| 783 | 607 |
| 784 | 608 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 845 } | 669 } |
| 846 | 670 |
| 847 | 671 |
| 848 LInstruction* LChunkBuilder::Define(LInstruction* instr, LUnallocated* result) { | 672 LInstruction* LChunkBuilder::Define(LInstruction* instr, LUnallocated* result) { |
| 849 allocator_->RecordDefinition(current_instruction_, result); | 673 allocator_->RecordDefinition(current_instruction_, result); |
| 850 instr->set_result(result); | 674 instr->set_result(result); |
| 851 return instr; | 675 return instr; |
| 852 } | 676 } |
| 853 | 677 |
| 854 | 678 |
| 855 LOperand* LChunkBuilder::Temp() { | |
| 856 LUnallocated* operand = new LUnallocated(LUnallocated::NONE); | |
| 857 allocator_->RecordTemporary(operand); | |
| 858 return operand; | |
| 859 } | |
| 860 | |
| 861 | |
| 862 LUnallocated* LChunkBuilder::TempRegister() { | 679 LUnallocated* LChunkBuilder::TempRegister() { |
| 863 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER); | 680 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER); |
| 864 allocator_->RecordTemporary(operand); | 681 allocator_->RecordTemporary(operand); |
| 865 return operand; | 682 return operand; |
| 866 } | 683 } |
| 867 | 684 |
| 868 | 685 |
| 869 LOperand* LChunkBuilder::FixedTemp(Register reg) { | 686 LOperand* LChunkBuilder::FixedTemp(Register reg) { |
| 870 LUnallocated* operand = ToUnallocated(reg); | 687 LUnallocated* operand = ToUnallocated(reg); |
| 871 allocator_->RecordTemporary(operand); | 688 allocator_->RecordTemporary(operand); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1009 last_environment->SetValueAt(block->deleted_phis()->at(i), | 826 last_environment->SetValueAt(block->deleted_phis()->at(i), |
| 1010 graph_->GetConstantUndefined()); | 827 graph_->GetConstantUndefined()); |
| 1011 } | 828 } |
| 1012 block->UpdateEnvironment(last_environment); | 829 block->UpdateEnvironment(last_environment); |
| 1013 // Pick up the outgoing argument count of one of the predecessors. | 830 // Pick up the outgoing argument count of one of the predecessors. |
| 1014 argument_count_ = pred->argument_count(); | 831 argument_count_ = pred->argument_count(); |
| 1015 } | 832 } |
| 1016 HInstruction* current = block->first(); | 833 HInstruction* current = block->first(); |
| 1017 int start = chunk_->instructions()->length(); | 834 int start = chunk_->instructions()->length(); |
| 1018 while (current != NULL && !is_aborted()) { | 835 while (current != NULL && !is_aborted()) { |
| 1019 if (FLAG_trace_environment) { | |
| 1020 PrintF("Process instruction %d\n", current->id()); | |
| 1021 } | |
| 1022 // Code for constants in registers is generated lazily. | 836 // Code for constants in registers is generated lazily. |
| 1023 if (!current->EmitAtUses()) { | 837 if (!current->EmitAtUses()) { |
| 1024 VisitInstruction(current); | 838 VisitInstruction(current); |
| 1025 } | 839 } |
| 1026 current = current->next(); | 840 current = current->next(); |
| 1027 } | 841 } |
| 1028 int end = chunk_->instructions()->length() - 1; | 842 int end = chunk_->instructions()->length() - 1; |
| 1029 if (end >= start) { | 843 if (end >= start) { |
| 1030 block->set_first_instruction_index(start); | 844 block->set_first_instruction_index(start); |
| 1031 block->set_last_instruction_index(end); | 845 block->set_last_instruction_index(end); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1059 int index = chunk_->AddInstruction(instr, current_block_); | 873 int index = chunk_->AddInstruction(instr, current_block_); |
| 1060 allocator_->SummarizeInstruction(index); | 874 allocator_->SummarizeInstruction(index); |
| 1061 } else { | 875 } else { |
| 1062 // This instruction should be omitted. | 876 // This instruction should be omitted. |
| 1063 allocator_->OmitInstruction(); | 877 allocator_->OmitInstruction(); |
| 1064 } | 878 } |
| 1065 current_instruction_ = old_current; | 879 current_instruction_ = old_current; |
| 1066 } | 880 } |
| 1067 | 881 |
| 1068 | 882 |
| 1069 void LEnvironment::WriteTranslation(LCodeGen* cgen, | |
| 1070 Translation* translation) const { | |
| 1071 if (this == NULL) return; | |
| 1072 | |
| 1073 // The translation includes one command per value in the environment. | |
| 1074 int translation_size = values()->length(); | |
| 1075 // The output frame height does not include the parameters. | |
| 1076 int height = translation_size - parameter_count(); | |
| 1077 | |
| 1078 outer()->WriteTranslation(cgen, translation); | |
| 1079 int closure_id = cgen->DefineDeoptimizationLiteral(closure()); | |
| 1080 translation->BeginFrame(ast_id(), closure_id, height); | |
| 1081 for (int i = 0; i < translation_size; ++i) { | |
| 1082 LOperand* value = values()->at(i); | |
| 1083 // spilled_registers_ and spilled_double_registers_ are either | |
| 1084 // both NULL or both set. | |
| 1085 if (spilled_registers_ != NULL && value != NULL) { | |
| 1086 if (value->IsRegister() && | |
| 1087 spilled_registers_[value->index()] != NULL) { | |
| 1088 translation->MarkDuplicate(); | |
| 1089 cgen->AddToTranslation(translation, | |
| 1090 spilled_registers_[value->index()], | |
| 1091 HasTaggedValueAt(i)); | |
| 1092 } else if (value->IsDoubleRegister() && | |
| 1093 spilled_double_registers_[value->index()] != NULL) { | |
| 1094 translation->MarkDuplicate(); | |
| 1095 cgen->AddToTranslation(translation, | |
| 1096 spilled_double_registers_[value->index()], | |
| 1097 false); | |
| 1098 } | |
| 1099 } | |
| 1100 | |
| 1101 cgen->AddToTranslation(translation, value, HasTaggedValueAt(i)); | |
| 1102 } | |
| 1103 } | |
| 1104 | |
| 1105 | |
| 1106 void LEnvironment::PrintTo(StringStream* stream) const { | |
| 1107 stream->Add("[id=%d|", ast_id()); | |
| 1108 stream->Add("[parameters=%d|", parameter_count()); | |
| 1109 stream->Add("[arguments_stack_height=%d|", arguments_stack_height()); | |
| 1110 for (int i = 0; i < values_.length(); ++i) { | |
| 1111 if (i != 0) stream->Add(";"); | |
| 1112 if (values_[i] == NULL) { | |
| 1113 stream->Add("[hole]"); | |
| 1114 } else { | |
| 1115 values_[i]->PrintTo(stream); | |
| 1116 } | |
| 1117 } | |
| 1118 stream->Add("]"); | |
| 1119 } | |
| 1120 | |
| 1121 | |
| 1122 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { | 883 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { |
| 1123 if (hydrogen_env == NULL) return NULL; | 884 if (hydrogen_env == NULL) return NULL; |
| 1124 | 885 |
| 1125 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); | 886 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); |
| 1126 int ast_id = hydrogen_env->ast_id(); | 887 int ast_id = hydrogen_env->ast_id(); |
| 1127 ASSERT(ast_id != AstNode::kNoNumber); | 888 ASSERT(ast_id != AstNode::kNoNumber); |
| 1128 int value_count = hydrogen_env->values()->length(); | 889 int value_count = hydrogen_env->length(); |
| 1129 LEnvironment* result = new LEnvironment(hydrogen_env->closure(), | 890 LEnvironment* result = new LEnvironment(hydrogen_env->closure(), |
| 1130 ast_id, | 891 ast_id, |
| 1131 hydrogen_env->parameter_count(), | 892 hydrogen_env->parameter_count(), |
| 1132 argument_count_, | 893 argument_count_, |
| 1133 value_count, | 894 value_count, |
| 1134 outer); | 895 outer); |
| 1135 int argument_index = 0; | 896 int argument_index = 0; |
| 1136 for (int i = 0; i < value_count; ++i) { | 897 for (int i = 0; i < value_count; ++i) { |
| 1137 HValue* value = hydrogen_env->values()->at(i); | 898 HValue* value = hydrogen_env->values()->at(i); |
| 1138 LOperand* op = NULL; | 899 LOperand* op = NULL; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1170 int first_id = first->block_id(); | 931 int first_id = first->block_id(); |
| 1171 int second_id = second->block_id(); | 932 int second_id = second->block_id(); |
| 1172 | 933 |
| 1173 if (v->EmitAtUses()) { | 934 if (v->EmitAtUses()) { |
| 1174 if (v->IsClassOfTest()) { | 935 if (v->IsClassOfTest()) { |
| 1175 HClassOfTest* compare = HClassOfTest::cast(v); | 936 HClassOfTest* compare = HClassOfTest::cast(v); |
| 1176 ASSERT(compare->value()->representation().IsTagged()); | 937 ASSERT(compare->value()->representation().IsTagged()); |
| 1177 | 938 |
| 1178 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), | 939 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), |
| 1179 TempRegister(), | 940 TempRegister(), |
| 1180 TempRegister(), | |
| 1181 first_id, | 941 first_id, |
| 1182 second_id); | 942 second_id); |
| 1183 } else if (v->IsCompare()) { | 943 } else if (v->IsCompare()) { |
| 1184 HCompare* compare = HCompare::cast(v); | 944 HCompare* compare = HCompare::cast(v); |
| 1185 Token::Value op = compare->token(); | 945 Token::Value op = compare->token(); |
| 1186 HValue* left = compare->left(); | 946 HValue* left = compare->left(); |
| 1187 HValue* right = compare->right(); | 947 HValue* right = compare->right(); |
| 1188 if (left->representation().IsInteger32()) { | 948 Representation r = compare->GetInputRepresentation(); |
| 949 if (r.IsInteger32()) { |
| 950 ASSERT(left->representation().IsInteger32()); |
| 1189 ASSERT(right->representation().IsInteger32()); | 951 ASSERT(right->representation().IsInteger32()); |
| 1190 return new LCmpIDAndBranch(op, | 952 return new LCmpIDAndBranch(UseRegisterAtStart(left), |
| 1191 UseRegisterAtStart(left), | |
| 1192 UseOrConstantAtStart(right), | 953 UseOrConstantAtStart(right), |
| 1193 first_id, | 954 first_id, |
| 1194 second_id, | 955 second_id); |
| 1195 false); | 956 } else if (r.IsDouble()) { |
| 1196 } else if (left->representation().IsDouble()) { | 957 ASSERT(left->representation().IsDouble()); |
| 1197 ASSERT(right->representation().IsDouble()); | 958 ASSERT(right->representation().IsDouble()); |
| 1198 return new LCmpIDAndBranch(op, | 959 return new LCmpIDAndBranch(UseRegisterAtStart(left), |
| 1199 UseRegisterAtStart(left), | |
| 1200 UseRegisterAtStart(right), | 960 UseRegisterAtStart(right), |
| 1201 first_id, | 961 first_id, |
| 1202 second_id, | 962 second_id); |
| 1203 true); | |
| 1204 } else { | 963 } else { |
| 1205 ASSERT(left->representation().IsTagged()); | 964 ASSERT(left->representation().IsTagged()); |
| 1206 ASSERT(right->representation().IsTagged()); | 965 ASSERT(right->representation().IsTagged()); |
| 1207 bool reversed = op == Token::GT || op == Token::LTE; | 966 bool reversed = op == Token::GT || op == Token::LTE; |
| 1208 LOperand* left_operand = UseFixed(left, reversed ? r0 : r1); | 967 LOperand* left_operand = UseFixed(left, reversed ? r0 : r1); |
| 1209 LOperand* right_operand = UseFixed(right, reversed ? r1 : r0); | 968 LOperand* right_operand = UseFixed(right, reversed ? r1 : r0); |
| 1210 LInstruction* result = new LCmpTAndBranch(left_operand, | 969 LInstruction* result = new LCmpTAndBranch(left_operand, |
| 1211 right_operand, | 970 right_operand, |
| 1212 first_id, | 971 first_id, |
| 1213 second_id); | 972 second_id); |
| 1214 return MarkAsCall(result, instr); | 973 return MarkAsCall(result, instr); |
| 1215 } | 974 } |
| 1216 } else if (v->IsIsSmi()) { | 975 } else if (v->IsIsSmi()) { |
| 1217 HIsSmi* compare = HIsSmi::cast(v); | 976 HIsSmi* compare = HIsSmi::cast(v); |
| 1218 ASSERT(compare->value()->representation().IsTagged()); | 977 ASSERT(compare->value()->representation().IsTagged()); |
| 1219 | 978 |
| 1220 return new LIsSmiAndBranch(Use(compare->value()), | 979 return new LIsSmiAndBranch(Use(compare->value()), |
| 1221 first_id, | 980 first_id, |
| 1222 second_id); | 981 second_id); |
| 1223 } else if (v->IsHasInstanceType()) { | 982 } else if (v->IsHasInstanceType()) { |
| 1224 HHasInstanceType* compare = HHasInstanceType::cast(v); | 983 HHasInstanceType* compare = HHasInstanceType::cast(v); |
| 1225 ASSERT(compare->value()->representation().IsTagged()); | 984 ASSERT(compare->value()->representation().IsTagged()); |
| 1226 | 985 |
| 1227 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()), | 986 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()), |
| 1228 TempRegister(), | |
| 1229 first_id, | 987 first_id, |
| 1230 second_id); | 988 second_id); |
| 1231 } else if (v->IsHasCachedArrayIndex()) { | 989 } else if (v->IsHasCachedArrayIndex()) { |
| 1232 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v); | 990 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v); |
| 1233 ASSERT(compare->value()->representation().IsTagged()); | 991 ASSERT(compare->value()->representation().IsTagged()); |
| 1234 | 992 |
| 1235 return new LHasCachedArrayIndexAndBranch( | 993 return new LHasCachedArrayIndexAndBranch( |
| 1236 UseRegisterAtStart(compare->value()), first_id, second_id); | 994 UseRegisterAtStart(compare->value()), first_id, second_id); |
| 1237 } else if (v->IsIsNull()) { | 995 } else if (v->IsIsNull()) { |
| 1238 HIsNull* compare = HIsNull::cast(v); | 996 HIsNull* compare = HIsNull::cast(v); |
| 1239 ASSERT(compare->value()->representation().IsTagged()); | 997 ASSERT(compare->value()->representation().IsTagged()); |
| 1240 | 998 |
| 1241 // We only need a temp register for non-strict compare. | |
| 1242 LOperand* temp = compare->is_strict() ? NULL : TempRegister(); | |
| 1243 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()), | 999 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()), |
| 1244 compare->is_strict(), | |
| 1245 temp, | |
| 1246 first_id, | 1000 first_id, |
| 1247 second_id); | 1001 second_id); |
| 1248 } else if (v->IsIsObject()) { | 1002 } else if (v->IsIsObject()) { |
| 1249 HIsObject* compare = HIsObject::cast(v); | 1003 HIsObject* compare = HIsObject::cast(v); |
| 1250 ASSERT(compare->value()->representation().IsTagged()); | 1004 ASSERT(compare->value()->representation().IsTagged()); |
| 1251 | 1005 |
| 1252 LOperand* temp1 = TempRegister(); | 1006 LOperand* temp1 = TempRegister(); |
| 1253 LOperand* temp2 = TempRegister(); | 1007 LOperand* temp2 = TempRegister(); |
| 1254 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), | 1008 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), |
| 1255 temp1, | 1009 temp1, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1288 } | 1042 } |
| 1289 } | 1043 } |
| 1290 return new LBranch(UseRegisterAtStart(v), first_id, second_id); | 1044 return new LBranch(UseRegisterAtStart(v), first_id, second_id); |
| 1291 } | 1045 } |
| 1292 | 1046 |
| 1293 | 1047 |
| 1294 LInstruction* LChunkBuilder::DoCompareMapAndBranch( | 1048 LInstruction* LChunkBuilder::DoCompareMapAndBranch( |
| 1295 HCompareMapAndBranch* instr) { | 1049 HCompareMapAndBranch* instr) { |
| 1296 ASSERT(instr->value()->representation().IsTagged()); | 1050 ASSERT(instr->value()->representation().IsTagged()); |
| 1297 LOperand* value = UseRegisterAtStart(instr->value()); | 1051 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1298 HBasicBlock* first = instr->FirstSuccessor(); | 1052 LOperand* temp = TempRegister(); |
| 1299 HBasicBlock* second = instr->SecondSuccessor(); | 1053 return new LCmpMapAndBranch(value, temp); |
| 1300 return new LCmpMapAndBranch(value, | |
| 1301 instr->map(), | |
| 1302 first->block_id(), | |
| 1303 second->block_id()); | |
| 1304 } | 1054 } |
| 1305 | 1055 |
| 1306 | 1056 |
| 1307 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { | 1057 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { |
| 1308 return DefineAsRegister(new LArgumentsLength(Use(length->value()))); | 1058 return DefineAsRegister(new LArgumentsLength(UseRegister(length->value()))); |
| 1309 } | 1059 } |
| 1310 | 1060 |
| 1311 | 1061 |
| 1312 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { | 1062 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { |
| 1313 return DefineAsRegister(new LArgumentsElements); | 1063 return DefineAsRegister(new LArgumentsElements); |
| 1314 } | 1064 } |
| 1315 | 1065 |
| 1316 | 1066 |
| 1317 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { | 1067 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { |
| 1318 LInstruction* result = | 1068 LInstruction* result = |
| 1319 new LInstanceOf(UseFixed(instr->left(), r1), | 1069 new LInstanceOf(UseFixed(instr->left(), r0), |
| 1320 UseFixed(instr->right(), r0)); | 1070 UseFixed(instr->right(), r1)); |
| 1071 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1072 } |
| 1073 |
| 1074 |
| 1075 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( |
| 1076 HInstanceOfKnownGlobal* instr) { |
| 1077 LInstruction* result = |
| 1078 new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0)); |
| 1321 return MarkAsCall(DefineFixed(result, r0), instr); | 1079 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1322 } | 1080 } |
| 1323 | 1081 |
| 1324 | 1082 |
| 1325 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { | 1083 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { |
| 1326 LOperand* function = UseFixed(instr->function(), r1); | 1084 LOperand* function = UseFixed(instr->function(), r1); |
| 1327 LOperand* receiver = UseFixed(instr->receiver(), r0); | 1085 LOperand* receiver = UseFixed(instr->receiver(), r0); |
| 1328 LOperand* length = UseRegisterAtStart(instr->length()); | 1086 LOperand* length = UseRegisterAtStart(instr->length()); |
| 1329 LOperand* elements = UseRegisterAtStart(instr->elements()); | 1087 LOperand* elements = UseRegisterAtStart(instr->elements()); |
| 1330 LInstruction* result = new LApplyArguments(function, | 1088 LInstruction* result = new LApplyArguments(function, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1355 LInstruction* LChunkBuilder::DoCallConstantFunction( | 1113 LInstruction* LChunkBuilder::DoCallConstantFunction( |
| 1356 HCallConstantFunction* instr) { | 1114 HCallConstantFunction* instr) { |
| 1357 argument_count_ -= instr->argument_count(); | 1115 argument_count_ -= instr->argument_count(); |
| 1358 return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr); | 1116 return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr); |
| 1359 } | 1117 } |
| 1360 | 1118 |
| 1361 | 1119 |
| 1362 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { | 1120 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { |
| 1363 BuiltinFunctionId op = instr->op(); | 1121 BuiltinFunctionId op = instr->op(); |
| 1364 LOperand* input = UseRegisterAtStart(instr->value()); | 1122 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1365 LInstruction* result = new LUnaryMathOperation(input); | 1123 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL; |
| 1124 LInstruction* result = new LUnaryMathOperation(input, temp); |
| 1366 switch (op) { | 1125 switch (op) { |
| 1367 case kMathAbs: | 1126 case kMathAbs: |
| 1368 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1127 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 1369 case kMathFloor: | 1128 case kMathFloor: |
| 1370 return AssignEnvironment(DefineAsRegister(result)); | 1129 return AssignEnvironment(DefineAsRegister(result)); |
| 1371 case kMathSqrt: | 1130 case kMathSqrt: |
| 1372 return DefineSameAsFirst(result); | 1131 return DefineSameAsFirst(result); |
| 1132 case kMathRound: |
| 1133 Abort("MathRound LUnaryMathOperation not implemented"); |
| 1134 return NULL; |
| 1373 case kMathPowHalf: | 1135 case kMathPowHalf: |
| 1374 Abort("MathPowHalf LUnaryMathOperation not implemented"); | 1136 Abort("MathPowHalf LUnaryMathOperation not implemented"); |
| 1375 return NULL; | 1137 return NULL; |
| 1376 case kMathLog: | 1138 case kMathLog: |
| 1377 Abort("MathLog LUnaryMathOperation not implemented"); | 1139 Abort("MathLog LUnaryMathOperation not implemented"); |
| 1378 return NULL; | 1140 return NULL; |
| 1379 case kMathCos: | 1141 case kMathCos: |
| 1380 Abort("MathCos LUnaryMathOperation not implemented"); | 1142 Abort("MathCos LUnaryMathOperation not implemented"); |
| 1381 return NULL; | 1143 return NULL; |
| 1382 case kMathSin: | 1144 case kMathSin: |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1580 | 1342 |
| 1581 | 1343 |
| 1582 LInstruction* LChunkBuilder::DoPower(HPower* instr) { | 1344 LInstruction* LChunkBuilder::DoPower(HPower* instr) { |
| 1583 Abort("LPower instruction not implemented on ARM"); | 1345 Abort("LPower instruction not implemented on ARM"); |
| 1584 return NULL; | 1346 return NULL; |
| 1585 } | 1347 } |
| 1586 | 1348 |
| 1587 | 1349 |
| 1588 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { | 1350 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { |
| 1589 Token::Value op = instr->token(); | 1351 Token::Value op = instr->token(); |
| 1590 if (instr->left()->representation().IsInteger32()) { | 1352 Representation r = instr->GetInputRepresentation(); |
| 1353 if (r.IsInteger32()) { |
| 1354 ASSERT(instr->left()->representation().IsInteger32()); |
| 1591 ASSERT(instr->right()->representation().IsInteger32()); | 1355 ASSERT(instr->right()->representation().IsInteger32()); |
| 1592 LOperand* left = UseRegisterAtStart(instr->left()); | 1356 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1593 LOperand* right = UseOrConstantAtStart(instr->right()); | 1357 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1594 return DefineAsRegister(new LCmpID(op, left, right, false)); | 1358 return DefineAsRegister(new LCmpID(left, right)); |
| 1595 } else if (instr->left()->representation().IsDouble()) { | 1359 } else if (r.IsDouble()) { |
| 1360 ASSERT(instr->left()->representation().IsDouble()); |
| 1596 ASSERT(instr->right()->representation().IsDouble()); | 1361 ASSERT(instr->right()->representation().IsDouble()); |
| 1597 LOperand* left = UseRegisterAtStart(instr->left()); | 1362 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1598 LOperand* right = UseRegisterAtStart(instr->right()); | 1363 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1599 return DefineAsRegister(new LCmpID(op, left, right, true)); | 1364 return DefineAsRegister(new LCmpID(left, right)); |
| 1600 } else { | 1365 } else { |
| 1366 ASSERT(instr->left()->representation().IsTagged()); |
| 1367 ASSERT(instr->right()->representation().IsTagged()); |
| 1601 bool reversed = (op == Token::GT || op == Token::LTE); | 1368 bool reversed = (op == Token::GT || op == Token::LTE); |
| 1602 LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1); | 1369 LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1); |
| 1603 LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0); | 1370 LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0); |
| 1604 LInstruction* result = new LCmpT(left, right); | 1371 LInstruction* result = new LCmpT(left, right); |
| 1605 return MarkAsCall(DefineFixed(result, r0), instr); | 1372 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1606 } | 1373 } |
| 1607 } | 1374 } |
| 1608 | 1375 |
| 1609 | 1376 |
| 1610 LInstruction* LChunkBuilder::DoCompareJSObjectEq( | 1377 LInstruction* LChunkBuilder::DoCompareJSObjectEq( |
| 1611 HCompareJSObjectEq* instr) { | 1378 HCompareJSObjectEq* instr) { |
| 1612 LOperand* left = UseRegisterAtStart(instr->left()); | 1379 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1613 LOperand* right = UseRegisterAtStart(instr->right()); | 1380 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1614 LInstruction* result = new LCmpJSObjectEq(left, right); | 1381 LInstruction* result = new LCmpJSObjectEq(left, right); |
| 1615 return DefineAsRegister(result); | 1382 return DefineAsRegister(result); |
| 1616 } | 1383 } |
| 1617 | 1384 |
| 1618 | 1385 |
| 1619 LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) { | 1386 LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) { |
| 1620 ASSERT(instr->value()->representation().IsTagged()); | 1387 ASSERT(instr->value()->representation().IsTagged()); |
| 1621 LOperand* value = UseRegisterAtStart(instr->value()); | 1388 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1622 | 1389 |
| 1623 return DefineAsRegister(new LIsNull(value, | 1390 return DefineAsRegister(new LIsNull(value)); |
| 1624 instr->is_strict())); | |
| 1625 } | 1391 } |
| 1626 | 1392 |
| 1627 | 1393 |
| 1628 LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) { | 1394 LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) { |
| 1629 ASSERT(instr->value()->representation().IsTagged()); | 1395 ASSERT(instr->value()->representation().IsTagged()); |
| 1630 LOperand* value = UseRegisterAtStart(instr->value()); | 1396 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1631 | 1397 |
| 1632 return DefineAsRegister(new LIsObject(value, TempRegister())); | 1398 return DefineAsRegister(new LIsObject(value, TempRegister())); |
| 1633 } | 1399 } |
| 1634 | 1400 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1654 ASSERT(instr->value()->representation().IsTagged()); | 1420 ASSERT(instr->value()->representation().IsTagged()); |
| 1655 LOperand* value = UseRegister(instr->value()); | 1421 LOperand* value = UseRegister(instr->value()); |
| 1656 | 1422 |
| 1657 return DefineAsRegister(new LHasCachedArrayIndex(value)); | 1423 return DefineAsRegister(new LHasCachedArrayIndex(value)); |
| 1658 } | 1424 } |
| 1659 | 1425 |
| 1660 | 1426 |
| 1661 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) { | 1427 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) { |
| 1662 ASSERT(instr->value()->representation().IsTagged()); | 1428 ASSERT(instr->value()->representation().IsTagged()); |
| 1663 LOperand* value = UseTempRegister(instr->value()); | 1429 LOperand* value = UseTempRegister(instr->value()); |
| 1664 | 1430 return DefineSameAsFirst(new LClassOfTest(value)); |
| 1665 return DefineSameAsFirst(new LClassOfTest(value, TempRegister())); | |
| 1666 } | 1431 } |
| 1667 | 1432 |
| 1668 | 1433 |
| 1669 LInstruction* LChunkBuilder::DoArrayLength(HArrayLength* instr) { | 1434 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { |
| 1670 LOperand* array = NULL; | 1435 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1671 LOperand* temporary = NULL; | 1436 return DefineAsRegister(new LJSArrayLength(array)); |
| 1672 | |
| 1673 if (instr->value()->IsLoadElements()) { | |
| 1674 array = UseRegisterAtStart(instr->value()); | |
| 1675 } else { | |
| 1676 array = UseRegister(instr->value()); | |
| 1677 temporary = TempRegister(); | |
| 1678 } | |
| 1679 | |
| 1680 LInstruction* result = new LArrayLength(array, temporary); | |
| 1681 return AssignEnvironment(DefineAsRegister(result)); | |
| 1682 } | 1437 } |
| 1683 | 1438 |
| 1684 | 1439 |
| 1440 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { |
| 1441 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1442 return DefineAsRegister(new LFixedArrayLength(array)); |
| 1443 } |
| 1444 |
| 1445 |
| 1685 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { | 1446 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { |
| 1686 LOperand* object = UseRegister(instr->value()); | 1447 LOperand* object = UseRegister(instr->value()); |
| 1687 LInstruction* result = new LValueOf(object, TempRegister()); | 1448 LInstruction* result = new LValueOf(object, TempRegister()); |
| 1688 return AssignEnvironment(DefineSameAsFirst(result)); | 1449 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1689 } | 1450 } |
| 1690 | 1451 |
| 1691 | 1452 |
| 1692 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1453 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
| 1693 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), | 1454 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), |
| 1694 Use(instr->length()))); | 1455 UseRegister(instr->length()))); |
| 1695 } | 1456 } |
| 1696 | 1457 |
| 1697 | 1458 |
| 1698 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { | 1459 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { |
| 1699 LOperand* value = UseFixed(instr->value(), r0); | 1460 LOperand* value = UseFixed(instr->value(), r0); |
| 1700 return MarkAsCall(new LThrow(value), instr); | 1461 return MarkAsCall(new LThrow(value), instr); |
| 1701 } | 1462 } |
| 1702 | 1463 |
| 1703 | 1464 |
| 1704 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1465 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1764 | 1525 |
| 1765 | 1526 |
| 1766 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { | 1527 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { |
| 1767 LOperand* value = UseRegisterAtStart(instr->value()); | 1528 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1768 return AssignEnvironment(new LCheckSmi(value, eq)); | 1529 return AssignEnvironment(new LCheckSmi(value, eq)); |
| 1769 } | 1530 } |
| 1770 | 1531 |
| 1771 | 1532 |
| 1772 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 1533 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
| 1773 LOperand* value = UseRegisterAtStart(instr->value()); | 1534 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1774 LOperand* temp = TempRegister(); | 1535 LInstruction* result = new LCheckInstanceType(value); |
| 1775 LInstruction* result = new LCheckInstanceType(value, temp); | |
| 1776 return AssignEnvironment(result); | 1536 return AssignEnvironment(result); |
| 1777 } | 1537 } |
| 1778 | 1538 |
| 1779 | 1539 |
| 1780 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { | 1540 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { |
| 1781 LOperand* temp = TempRegister(); | 1541 LOperand* temp1 = TempRegister(); |
| 1782 LInstruction* result = | 1542 LOperand* temp2 = TempRegister(); |
| 1783 new LCheckPrototypeMaps(temp, | 1543 LInstruction* result = new LCheckPrototypeMaps(temp1, temp2); |
| 1784 instr->holder(), | |
| 1785 instr->receiver_map()); | |
| 1786 return AssignEnvironment(result); | 1544 return AssignEnvironment(result); |
| 1787 } | 1545 } |
| 1788 | 1546 |
| 1789 | 1547 |
| 1790 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { | 1548 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { |
| 1791 LOperand* value = UseRegisterAtStart(instr->value()); | 1549 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1792 return AssignEnvironment(new LCheckSmi(value, ne)); | 1550 return AssignEnvironment(new LCheckSmi(value, ne)); |
| 1793 } | 1551 } |
| 1794 | 1552 |
| 1795 | 1553 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1847 } | 1605 } |
| 1848 | 1606 |
| 1849 | 1607 |
| 1850 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { | 1608 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { |
| 1851 LOperand* object = UseFixed(instr->object(), r0); | 1609 LOperand* object = UseFixed(instr->object(), r0); |
| 1852 LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0); | 1610 LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0); |
| 1853 return MarkAsCall(result, instr); | 1611 return MarkAsCall(result, instr); |
| 1854 } | 1612 } |
| 1855 | 1613 |
| 1856 | 1614 |
| 1615 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( |
| 1616 HLoadFunctionPrototype* instr) { |
| 1617 return AssignEnvironment(DefineAsRegister( |
| 1618 new LLoadFunctionPrototype(UseRegister(instr->function())))); |
| 1619 } |
| 1620 |
| 1621 |
| 1857 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) { | 1622 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) { |
| 1858 LOperand* input = UseRegisterAtStart(instr->value()); | 1623 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1859 return DefineSameAsFirst(new LLoadElements(input)); | 1624 return DefineSameAsFirst(new LLoadElements(input)); |
| 1860 } | 1625 } |
| 1861 | 1626 |
| 1862 | 1627 |
| 1863 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( | 1628 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( |
| 1864 HLoadKeyedFastElement* instr) { | 1629 HLoadKeyedFastElement* instr) { |
| 1865 Representation r = instr->representation(); | 1630 ASSERT(instr->representation().IsTagged()); |
| 1631 ASSERT(instr->key()->representation().IsInteger32()); |
| 1866 LOperand* obj = UseRegisterAtStart(instr->object()); | 1632 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 1867 ASSERT(instr->key()->representation().IsInteger32()); | |
| 1868 LOperand* key = UseRegisterAtStart(instr->key()); | 1633 LOperand* key = UseRegisterAtStart(instr->key()); |
| 1869 LOperand* load_result = NULL; | 1634 LInstruction* result = new LLoadKeyedFastElement(obj, key); |
| 1870 // Double needs an extra temp, because the result is converted from heap | 1635 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1871 // number to a double register. | |
| 1872 if (r.IsDouble()) load_result = TempRegister(); | |
| 1873 LInstruction* result = new LLoadKeyedFastElement(obj, | |
| 1874 key, | |
| 1875 load_result); | |
| 1876 if (r.IsDouble()) { | |
| 1877 result = DefineAsRegister(result); | |
| 1878 } else { | |
| 1879 result = DefineSameAsFirst(result); | |
| 1880 } | |
| 1881 return AssignEnvironment(result); | |
| 1882 } | 1636 } |
| 1883 | 1637 |
| 1884 | 1638 |
| 1885 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 1639 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
| 1886 LOperand* object = UseFixed(instr->object(), r1); | 1640 LOperand* object = UseFixed(instr->object(), r1); |
| 1887 LOperand* key = UseFixed(instr->key(), r0); | 1641 LOperand* key = UseFixed(instr->key(), r0); |
| 1888 | 1642 |
| 1889 LInstruction* result = | 1643 LInstruction* result = |
| 1890 DefineFixed(new LLoadKeyedGeneric(object, key), r0); | 1644 DefineFixed(new LLoadKeyedGeneric(object, key), r0); |
| 1891 return MarkAsCall(result, instr); | 1645 return MarkAsCall(result, instr); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1918 | 1672 |
| 1919 ASSERT(instr->object()->representation().IsTagged()); | 1673 ASSERT(instr->object()->representation().IsTagged()); |
| 1920 ASSERT(instr->key()->representation().IsTagged()); | 1674 ASSERT(instr->key()->representation().IsTagged()); |
| 1921 ASSERT(instr->value()->representation().IsTagged()); | 1675 ASSERT(instr->value()->representation().IsTagged()); |
| 1922 | 1676 |
| 1923 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr); | 1677 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr); |
| 1924 } | 1678 } |
| 1925 | 1679 |
| 1926 | 1680 |
| 1927 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { | 1681 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { |
| 1928 bool needs_write_barrier = !instr->value()->type().IsSmi(); | 1682 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 1929 | 1683 |
| 1930 LOperand* obj = needs_write_barrier | 1684 LOperand* obj = needs_write_barrier |
| 1931 ? UseTempRegister(instr->object()) | 1685 ? UseTempRegister(instr->object()) |
| 1932 : UseRegisterAtStart(instr->object()); | 1686 : UseRegisterAtStart(instr->object()); |
| 1933 | 1687 |
| 1934 LOperand* val = needs_write_barrier | 1688 LOperand* val = needs_write_barrier |
| 1935 ? UseTempRegister(instr->value()) | 1689 ? UseTempRegister(instr->value()) |
| 1936 : UseRegister(instr->value()); | 1690 : UseRegister(instr->value()); |
| 1937 | 1691 |
| 1938 // We only need a scratch register if we have a write barrier or we | 1692 return new LStoreNamedField(obj, val); |
| 1939 // have a store into the properties array (not in-object-property). | |
| 1940 LOperand* temp = (!instr->is_in_object() || needs_write_barrier) | |
| 1941 ? TempRegister() : NULL; | |
| 1942 | |
| 1943 return new LStoreNamedField(obj, | |
| 1944 instr->name(), | |
| 1945 val, | |
| 1946 instr->is_in_object(), | |
| 1947 instr->offset(), | |
| 1948 temp, | |
| 1949 needs_write_barrier, | |
| 1950 instr->transition()); | |
| 1951 } | 1693 } |
| 1952 | 1694 |
| 1953 | 1695 |
| 1954 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 1696 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
| 1955 LOperand* obj = UseFixed(instr->object(), r1); | 1697 LOperand* obj = UseFixed(instr->object(), r1); |
| 1956 LOperand* val = UseFixed(instr->value(), r0); | 1698 LOperand* val = UseFixed(instr->value(), r0); |
| 1957 | 1699 |
| 1958 LInstruction* result = new LStoreNamedGeneric(obj, instr->name(), val); | 1700 LInstruction* result = new LStoreNamedGeneric(obj, val); |
| 1959 return MarkAsCall(result, instr); | 1701 return MarkAsCall(result, instr); |
| 1960 } | 1702 } |
| 1961 | 1703 |
| 1962 | 1704 |
| 1963 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { | 1705 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { |
| 1964 return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr); | 1706 return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr); |
| 1965 } | 1707 } |
| 1966 | 1708 |
| 1967 | 1709 |
| 1968 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) { | 1710 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) { |
| 1969 return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr); | 1711 return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr); |
| 1970 } | 1712 } |
| 1971 | 1713 |
| 1972 | 1714 |
| 1973 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { | 1715 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { |
| 1974 return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr); | 1716 return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr); |
| 1975 } | 1717 } |
| 1976 | 1718 |
| 1977 | 1719 |
| 1978 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { | 1720 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { |
| 1979 return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr); | 1721 return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr); |
| 1980 } | 1722 } |
| 1981 | 1723 |
| 1982 | 1724 |
| 1983 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { | 1725 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { |
| 1984 LInstruction* result = new LDeleteProperty(Use(instr->object()), | 1726 LOperand* object = UseRegisterAtStart(instr->object()); |
| 1985 UseOrConstant(instr->key())); | 1727 LOperand* key = UseRegisterAtStart(instr->key()); |
| 1728 LInstruction* result = new LDeleteProperty(object, key); |
| 1986 return MarkAsCall(DefineFixed(result, r0), instr); | 1729 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1987 } | 1730 } |
| 1988 | 1731 |
| 1989 | 1732 |
| 1990 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { | 1733 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { |
| 1991 allocator_->MarkAsOsrEntry(); | 1734 allocator_->MarkAsOsrEntry(); |
| 1992 current_block_->last_environment()->set_ast_id(instr->ast_id()); | 1735 current_block_->last_environment()->set_ast_id(instr->ast_id()); |
| 1993 return AssignEnvironment(new LOsrEntry); | 1736 return AssignEnvironment(new LOsrEntry); |
| 1994 } | 1737 } |
| 1995 | 1738 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2015 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { | 1758 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { |
| 2016 // There are no real uses of the arguments object (we bail out in all other | 1759 // There are no real uses of the arguments object (we bail out in all other |
| 2017 // cases). | 1760 // cases). |
| 2018 return NULL; | 1761 return NULL; |
| 2019 } | 1762 } |
| 2020 | 1763 |
| 2021 | 1764 |
| 2022 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { | 1765 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { |
| 2023 LOperand* arguments = UseRegister(instr->arguments()); | 1766 LOperand* arguments = UseRegister(instr->arguments()); |
| 2024 LOperand* length = UseTempRegister(instr->length()); | 1767 LOperand* length = UseTempRegister(instr->length()); |
| 2025 LOperand* index = Use(instr->index()); | 1768 LOperand* index = UseRegister(instr->index()); |
| 2026 LInstruction* result = new LAccessArgumentsAt(arguments, length, index); | 1769 LInstruction* result = new LAccessArgumentsAt(arguments, length, index); |
| 2027 return DefineAsRegister(AssignEnvironment(result)); | 1770 return DefineAsRegister(AssignEnvironment(result)); |
| 2028 } | 1771 } |
| 2029 | 1772 |
| 2030 | 1773 |
| 2031 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { | 1774 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { |
| 2032 LInstruction* result = new LTypeof(Use(instr->value())); | 1775 LInstruction* result = new LTypeof(UseRegisterAtStart(instr->value())); |
| 2033 return MarkAsCall(DefineFixed(result, r0), instr); | 1776 return MarkAsCall(DefineFixed(result, r0), instr); |
| 2034 } | 1777 } |
| 2035 | 1778 |
| 2036 | 1779 |
| 2037 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { | 1780 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { |
| 2038 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); | 1781 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); |
| 2039 } | 1782 } |
| 2040 | 1783 |
| 2041 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 1784 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
| 2042 HEnvironment* env = current_block_->last_environment(); | 1785 HEnvironment* env = current_block_->last_environment(); |
| 2043 ASSERT(env != NULL); | 1786 ASSERT(env != NULL); |
| 2044 | 1787 |
| 2045 env->set_ast_id(instr->ast_id()); | 1788 env->set_ast_id(instr->ast_id()); |
| 2046 | 1789 |
| 2047 env->Drop(instr->pop_count()); | 1790 env->Drop(instr->pop_count()); |
| 2048 for (int i = 0; i < instr->values()->length(); ++i) { | 1791 for (int i = 0; i < instr->values()->length(); ++i) { |
| 2049 HValue* value = instr->values()->at(i); | 1792 HValue* value = instr->values()->at(i); |
| 2050 if (instr->HasAssignedIndexAt(i)) { | 1793 if (instr->HasAssignedIndexAt(i)) { |
| 2051 env->Bind(instr->GetAssignedIndexAt(i), value); | 1794 env->Bind(instr->GetAssignedIndexAt(i), value); |
| 2052 } else { | 1795 } else { |
| 2053 env->Push(value); | 1796 env->Push(value); |
| 2054 } | 1797 } |
| 2055 } | 1798 } |
| 2056 | 1799 |
| 2057 if (FLAG_trace_environment) { | 1800 ASSERT(env->length() == instr->environment_length()); |
| 2058 PrintF("Reconstructed environment ast_id=%d, instr_id=%d\n", | |
| 2059 instr->ast_id(), | |
| 2060 instr->id()); | |
| 2061 env->PrintToStd(); | |
| 2062 } | |
| 2063 ASSERT(env->values()->length() == instr->environment_height()); | |
| 2064 | 1801 |
| 2065 // If there is an instruction pending deoptimization environment create a | 1802 // If there is an instruction pending deoptimization environment create a |
| 2066 // lazy bailout instruction to capture the environment. | 1803 // lazy bailout instruction to capture the environment. |
| 2067 if (pending_deoptimization_ast_id_ == instr->ast_id()) { | 1804 if (pending_deoptimization_ast_id_ == instr->ast_id()) { |
| 2068 LInstruction* result = new LLazyBailout; | 1805 LInstruction* result = new LLazyBailout; |
| 2069 result = AssignEnvironment(result); | 1806 result = AssignEnvironment(result); |
| 2070 instructions_pending_deoptimization_environment_-> | 1807 instructions_pending_deoptimization_environment_-> |
| 2071 set_deoptimization_environment(result->environment()); | 1808 set_deoptimization_environment(result->environment()); |
| 2072 ClearInstructionPendingDeoptimizationEnvironment(); | 1809 ClearInstructionPendingDeoptimizationEnvironment(); |
| 2073 return result; | 1810 return result; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2095 } | 1832 } |
| 2096 | 1833 |
| 2097 | 1834 |
| 2098 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 1835 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 2099 HEnvironment* outer = current_block_->last_environment()->outer(); | 1836 HEnvironment* outer = current_block_->last_environment()->outer(); |
| 2100 current_block_->UpdateEnvironment(outer); | 1837 current_block_->UpdateEnvironment(outer); |
| 2101 return NULL; | 1838 return NULL; |
| 2102 } | 1839 } |
| 2103 | 1840 |
| 2104 | 1841 |
| 2105 void LPointerMap::RecordPointer(LOperand* op) { | |
| 2106 // Do not record arguments as pointers. | |
| 2107 if (op->IsStackSlot() && op->index() < 0) return; | |
| 2108 ASSERT(!op->IsDoubleRegister() && !op->IsDoubleStackSlot()); | |
| 2109 pointer_operands_.Add(op); | |
| 2110 } | |
| 2111 | |
| 2112 | |
| 2113 void LPointerMap::PrintTo(StringStream* stream) const { | |
| 2114 stream->Add("{"); | |
| 2115 for (int i = 0; i < pointer_operands_.length(); ++i) { | |
| 2116 if (i != 0) stream->Add(";"); | |
| 2117 pointer_operands_[i]->PrintTo(stream); | |
| 2118 } | |
| 2119 stream->Add("} @%d", position()); | |
| 2120 } | |
| 2121 | |
| 2122 } } // namespace v8::internal | 1842 } } // namespace v8::internal |
| OLD | NEW |