Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
| 9 #include "vm/flow_graph_compiler.h" | 9 #include "vm/flow_graph_compiler.h" |
| 10 #include "vm/locations.h" | 10 #include "vm/locations.h" |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 30 Instruction* ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \ | 30 Instruction* ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \ |
| 31 visitor->Visit##ShortName(this); \ | 31 visitor->Visit##ShortName(this); \ |
| 32 return StraightLineSuccessor(); \ | 32 return StraightLineSuccessor(); \ |
| 33 } | 33 } |
| 34 | 34 |
| 35 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT) | 35 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT) |
| 36 | 36 |
| 37 #undef DEFINE_ACCEPT | 37 #undef DEFINE_ACCEPT |
| 38 | 38 |
| 39 | 39 |
| 40 // Truee iff. the v2 is above v1 on stack, or one of them is constant. | |
| 41 static bool VerifyValues(Value* v1, Value* v2) { | |
| 42 ASSERT(v1->IsUse() && v2->IsUse()); | |
| 43 return (v1->AsUse()->definition()->temp_index() + 1) == | |
| 44 v2->AsUse()->definition()->temp_index(); | |
| 45 } | |
| 46 | |
| 47 | |
| 40 // Default implementation of visiting basic blocks. Can be overridden. | 48 // Default implementation of visiting basic blocks. Can be overridden. |
| 41 void FlowGraphVisitor::VisitBlocks() { | 49 void FlowGraphVisitor::VisitBlocks() { |
| 42 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 50 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 43 Instruction* current = block_order_[i]->Accept(this); | 51 Instruction* current = block_order_[i]->Accept(this); |
| 44 while ((current != NULL) && !current->IsBlockEntry()) { | 52 while ((current != NULL) && !current->IsBlockEntry()) { |
| 45 current = current->Accept(this); | 53 current = current->Accept(this); |
| 46 } | 54 } |
| 47 } | 55 } |
| 48 } | 56 } |
| 49 | 57 |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 609 intptr_t current = val->AsUse()->definition()->temp_index(); | 617 intptr_t current = val->AsUse()->definition()->temp_index(); |
| 610 if (i != 0) { | 618 if (i != 0) { |
| 611 if (current != (previous + 1)) return false; | 619 if (current != (previous + 1)) return false; |
| 612 } | 620 } |
| 613 previous = current; | 621 previous = current; |
| 614 } | 622 } |
| 615 return true; | 623 return true; |
| 616 } | 624 } |
| 617 | 625 |
| 618 | 626 |
| 619 // Truee iff. the v2 is above v1 on stack, or one of them is constant. | |
| 620 static bool VerifyValues(Value* v1, Value* v2) { | |
| 621 ASSERT(v1->IsUse() && v2->IsUse()); | |
| 622 return (v1->AsUse()->definition()->temp_index() + 1) == | |
| 623 v2->AsUse()->definition()->temp_index(); | |
| 624 } | |
| 625 | |
| 626 | |
| 627 #define __ compiler->assembler()-> | 627 #define __ compiler->assembler()-> |
| 628 | 628 |
| 629 void GraphEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { | 629 void GraphEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { |
| 630 // Nothing to do. | 630 // Nothing to do. |
| 631 } | 631 } |
| 632 | 632 |
| 633 | 633 |
| 634 void JoinEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { | 634 void JoinEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { |
| 635 __ Bind(compiler->GetBlockLabel(this)); | 635 __ Bind(compiler->GetBlockLabel(this)); |
| 636 } | 636 } |
| 637 | 637 |
| 638 | 638 |
| 639 void TargetEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { | 639 void TargetEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { |
| 640 __ Bind(compiler->GetBlockLabel(this)); | 640 __ Bind(compiler->GetBlockLabel(this)); |
| 641 if (HasTryIndex()) { | 641 if (HasTryIndex()) { |
| 642 compiler->AddExceptionHandler(try_index(), | 642 compiler->AddExceptionHandler(try_index(), |
| 643 compiler->assembler()->CodeSize()); | 643 compiler->assembler()->CodeSize()); |
| 644 } | 644 } |
| 645 } | 645 } |
| 646 | 646 |
| 647 | 647 |
| 648 LocationSummary* StoreInstanceFieldComp::MakeLocationSummary() const { | |
| 649 const intptr_t kNumInputs = 2; | |
| 650 intptr_t num_temps = (class_ids() == NULL) ? 0 : 1; | |
| 651 LocationSummary* summary = new LocationSummary(kNumInputs, num_temps); | |
| 652 summary->set_in(0, Location::RequiresRegister()); | |
| 653 summary->set_in(1, Location::RequiresRegister()); | |
| 654 if (class_ids() != NULL) { | |
| 655 summary->set_temp(0, Location::RequiresRegister()); | |
| 656 } | |
| 657 return summary; | |
| 658 } | |
| 659 | |
| 660 | |
| 661 void StoreInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 662 ASSERT(VerifyValues(instance(), value())); | |
| 663 Register instance = locs()->in(0).reg(); | |
| 664 Register value = locs()->in(1).reg(); | |
| 665 | |
| 666 if (class_ids() != NULL) { | |
| 667 ASSERT(original() != NULL); | |
| 668 Label* deopt = compiler->AddDeoptStub(original()->cid(), | |
| 669 original()->token_index(), | |
| 670 original()->try_index(), | |
| 671 kDeoptInstanceGetterSameTarget, | |
| 672 instance, | |
| 673 value); | |
| 674 // Smis do not have instance fields (Smi class is always first). | |
| 675 // Use 'result' as temporary register. | |
|
Florian Schneider
2012/06/07 08:47:59
Comment seems out of date: There is no 'result' re
srdjan
2012/06/07 18:24:50
Done.
| |
| 676 Register temp = locs()->temp(0).reg(); | |
| 677 ASSERT(temp != instance); | |
| 678 ASSERT(temp != value); | |
| 679 compiler->EmitClassChecksNoSmi(*class_ids(), instance, temp, deopt); | |
| 680 } | |
| 681 __ StoreIntoObject(instance, FieldAddress(instance, field().Offset()), | |
| 682 value); | |
| 683 } | |
| 684 | |
| 685 | |
| 648 LocationSummary* ThrowInstr::MakeLocationSummary() const { | 686 LocationSummary* ThrowInstr::MakeLocationSummary() const { |
| 649 const int kNumInputs = 0; | 687 const int kNumInputs = 0; |
| 650 const int kNumTemps = 0; | 688 const int kNumTemps = 0; |
| 651 return new LocationSummary(kNumInputs, kNumTemps); | 689 return new LocationSummary(kNumInputs, kNumTemps); |
| 652 } | 690 } |
| 653 | 691 |
| 654 | 692 |
| 655 | 693 |
| 656 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 694 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 657 ASSERT(exception()->IsUse()); | 695 ASSERT(exception()->IsUse()); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 835 dst_name()); | 873 dst_name()); |
| 836 ASSERT(locs()->in(0).reg() == locs()->out().reg()); | 874 ASSERT(locs()->in(0).reg() == locs()->out().reg()); |
| 837 } | 875 } |
| 838 | 876 |
| 839 | 877 |
| 840 LocationSummary* AssertBooleanComp::MakeLocationSummary() const { | 878 LocationSummary* AssertBooleanComp::MakeLocationSummary() const { |
| 841 return LocationSummary::Make(1, Location::SameAsFirstInput()); | 879 return LocationSummary::Make(1, Location::SameAsFirstInput()); |
| 842 } | 880 } |
| 843 | 881 |
| 844 | 882 |
| 845 LocationSummary* StoreInstanceFieldComp::MakeLocationSummary() const { | |
| 846 return LocationSummary::Make(2, Location::RequiresRegister()); | |
| 847 } | |
| 848 | |
| 849 | |
| 850 void StoreInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 851 ASSERT(VerifyValues(instance(), value())); | |
| 852 Register instance = locs()->in(0).reg(); | |
| 853 Register value = locs()->in(1).reg(); | |
| 854 Register result = locs()->out().reg(); | |
| 855 | |
| 856 __ StoreIntoObject(instance, FieldAddress(instance, field().Offset()), | |
| 857 value); | |
| 858 // TODO(fschneider): Consider eliminating this move by specifying a | |
| 859 // SameAsSecondInput for the result. | |
| 860 __ MoveRegister(result, value); | |
| 861 } | |
| 862 | |
| 863 | |
| 864 LocationSummary* StoreStaticFieldComp::MakeLocationSummary() const { | 883 LocationSummary* StoreStaticFieldComp::MakeLocationSummary() const { |
| 865 LocationSummary* locs = new LocationSummary(1, 1); | 884 LocationSummary* locs = new LocationSummary(1, 1); |
| 866 locs->set_in(0, Location::RequiresRegister()); | 885 locs->set_in(0, Location::RequiresRegister()); |
| 867 locs->set_temp(0, Location::RequiresRegister()); | 886 locs->set_temp(0, Location::RequiresRegister()); |
| 868 locs->set_out(Location::SameAsFirstInput()); | 887 locs->set_out(Location::SameAsFirstInput()); |
| 869 return locs; | 888 return locs; |
| 870 } | 889 } |
| 871 | 890 |
| 872 | 891 |
| 873 void StoreStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 892 void StoreStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 960 StubCode::GetAllocationStubForClosure(closure_function)); | 979 StubCode::GetAllocationStubForClosure(closure_function)); |
| 961 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); | 980 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); |
| 962 compiler->GenerateCall(token_index(), try_index(), &label, | 981 compiler->GenerateCall(token_index(), try_index(), &label, |
| 963 PcDescriptors::kOther); | 982 PcDescriptors::kOther); |
| 964 __ Drop(2); // Discard type arguments and receiver. | 983 __ Drop(2); // Discard type arguments and receiver. |
| 965 } | 984 } |
| 966 | 985 |
| 967 #undef __ | 986 #undef __ |
| 968 | 987 |
| 969 } // namespace dart | 988 } // namespace dart |
| OLD | NEW |