Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: runtime/vm/intermediate_language_x64.cc

Issue 10651008: Minimize differences between ia32 and x64 sources to facilitate maintenance. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/globals.h" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
11 #include "vm/flow_graph_compiler.h" 11 #include "vm/flow_graph_compiler.h"
12 #include "vm/locations.h" 12 #include "vm/locations.h"
13 #include "vm/object_store.h" 13 #include "vm/object_store.h"
14 #include "vm/parser.h" 14 #include "vm/parser.h"
15 #include "vm/stub_code.h" 15 #include "vm/stub_code.h"
16 16
17 #define __ compiler->assembler()-> 17 #define __ compiler->assembler()->
18 18
19 namespace dart { 19 namespace dart {
20 20
21 DECLARE_FLAG(int, optimization_counter_threshold); 21 DECLARE_FLAG(int, optimization_counter_threshold);
22 DECLARE_FLAG(bool, trace_functions); 22 DECLARE_FLAG(bool, trace_functions);
23 23
24 // Generic summary for call instructions that have all arguments pushed
25 // on the stack and return the result in a fixed register RAX.
26 LocationSummary* Computation::MakeCallSummary() {
27 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall);
28 result->set_out(Location::RegisterLocation(RAX));
29 return result;
30 }
31
32
24 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 33 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
25 computation()->EmitNativeCode(compiler); 34 computation()->EmitNativeCode(compiler);
26 if (locs()->out().kind() == Location::kRegister) { 35 if (locs()->out().kind() == Location::kRegister) {
27 // TODO(vegorov): this should really happen only for comparisons fused 36 // TODO(vegorov): this should really happen only for comparisons fused
28 // with branches. Currrently IR does not provide an easy way to remove 37 // with branches. Currrently IR does not provide an easy way to remove
29 // instructions from the graph so we just leave fused comparison in it 38 // instructions from the graph so we just leave fused comparison in it
30 // but change its result location to be NoLocation. 39 // but change its result location to be NoLocation.
31 compiler->frame_register_allocator()->Push(locs()->out().reg(), this); 40 compiler->frame_register_allocator()->Push(locs()->out().reg(), this);
32 } 41 }
33 } 42 }
(...skipping 29 matching lines...) Expand all
63 __ j(LESS_EQUAL, &not_yet_hot, Assembler::kNearJump); 72 __ j(LESS_EQUAL, &not_yet_hot, Assembler::kNearJump);
64 __ pushq(result); // Preserve result. 73 __ pushq(result); // Preserve result.
65 __ pushq(temp); // Argument for runtime: function to optimize. 74 __ pushq(temp); // Argument for runtime: function to optimize.
66 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); 75 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry);
67 __ popq(temp); // Remove argument. 76 __ popq(temp); // Remove argument.
68 __ popq(result); // Restore result. 77 __ popq(result); // Restore result.
69 __ Bind(&not_yet_hot); 78 __ Bind(&not_yet_hot);
70 } 79 }
71 } 80 }
72 if (FLAG_trace_functions) { 81 if (FLAG_trace_functions) {
73 __ pushq(result); // Preserve result.
74 const Function& function = 82 const Function& function =
75 Function::ZoneHandle(compiler->parsed_function().function().raw()); 83 Function::ZoneHandle(compiler->parsed_function().function().raw());
76 __ LoadObject(temp, function); 84 __ LoadObject(temp, function);
85 __ pushq(result); // Preserve result.
77 __ pushq(temp); 86 __ pushq(temp);
78 compiler->GenerateCallRuntime(AstNode::kNoId, 87 compiler->GenerateCallRuntime(AstNode::kNoId,
79 0, 88 0,
80 CatchClauseNode::kInvalidTryIndex, 89 CatchClauseNode::kInvalidTryIndex,
81 kTraceFunctionExitRuntimeEntry); 90 kTraceFunctionExitRuntimeEntry);
82 __ popq(temp); // Remove argument. 91 __ popq(temp); // Remove argument.
83 __ popq(result); // Restore result. 92 __ popq(result); // Restore result.
84 } 93 }
85 __ LeaveFrame(); 94 __ LeaveFrame();
86 __ ret(); 95 __ ret();
87 96
88 // Generate 8 bytes of NOPs so that the debugger can patch the 97 // Generate 8 bytes of NOPs so that the debugger can patch the
89 // return pattern with a call to the debug stub. 98 // return pattern with a call to the debug stub.
99 // Note that the nop(8) byte pattern is not recognized by the debugger.
90 __ nop(1); 100 __ nop(1);
91 __ nop(1); 101 __ nop(1);
92 __ nop(1); 102 __ nop(1);
93 __ nop(1); 103 __ nop(1);
94 __ nop(1); 104 __ nop(1);
95 __ nop(1); 105 __ nop(1);
96 __ nop(1); 106 __ nop(1);
97 __ nop(1); 107 __ nop(1);
98 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, 108 compiler->AddCurrentDescriptor(PcDescriptors::kReturn,
99 cid(), 109 cid(),
100 token_index(), 110 token_index(),
101 CatchClauseNode::kInvalidTryIndex); 111 CatchClauseNode::kInvalidTryIndex);
102 } 112 }
103 113
104 114
105 // Generic summary for call instructions that have all arguments pushed
106 // on the stack and return the result in a fixed register RAX.
107 LocationSummary* Computation::MakeCallSummary() {
108 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall);
109 result->set_out(Location::RegisterLocation(RAX));
110 return result;
111 }
112
113
114 LocationSummary* ClosureCallComp::MakeLocationSummary() const { 115 LocationSummary* ClosureCallComp::MakeLocationSummary() const {
115 const intptr_t kNumInputs = 0; 116 const intptr_t kNumInputs = 0;
116 const intptr_t kNumTemps = 1; 117 const intptr_t kNumTemps = 1;
117 LocationSummary* result = new LocationSummary(kNumInputs, 118 LocationSummary* result = new LocationSummary(kNumInputs,
118 kNumTemps, 119 kNumTemps,
119 LocationSummary::kCall); 120 LocationSummary::kCall);
120 result->set_out(Location::RegisterLocation(RAX)); 121 result->set_out(Location::RegisterLocation(RAX));
121 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. 122 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor.
122 return result; 123 return result;
123 } 124 }
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 __ jmp(deopt); 382 __ jmp(deopt);
382 __ Bind(&done); 383 __ Bind(&done);
383 } 384 }
384 385
385 386
386 // First test if receiver is NULL, in which case === is applied. 387 // First test if receiver is NULL, in which case === is applied.
387 // If type feedback was provided (lists of <class-id, target>), do a 388 // If type feedback was provided (lists of <class-id, target>), do a
388 // type by type check (either === or static call to the operator. 389 // type by type check (either === or static call to the operator.
389 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, 390 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
390 EqualityCompareComp* comp) { 391 EqualityCompareComp* comp) {
391 const Immediate raw_null =
392 Immediate(reinterpret_cast<intptr_t>(Object::null()));
393 Register left = comp->locs()->in(0).reg(); 392 Register left = comp->locs()->in(0).reg();
394 Register right = comp->locs()->in(1).reg(); 393 Register right = comp->locs()->in(1).reg();
394 const Immediate raw_null =
395 Immediate(reinterpret_cast<intptr_t>(Object::null()));
395 Label done, non_null_compare; 396 Label done, non_null_compare;
396 __ cmpq(left, raw_null); 397 __ cmpq(left, raw_null);
397 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); 398 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump);
398 // Comparison with NULL is "===". 399 // Comparison with NULL is "===".
399 __ cmpq(left, right); 400 __ cmpq(left, right);
400 if (comp->is_fused_with_branch()) { 401 if (comp->is_fused_with_branch()) {
401 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); 402 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
402 } else { 403 } else {
403 Register result = comp->locs()->out().reg(); 404 Register result = comp->locs()->out().reg();
404 Label load_true; 405 Label load_true;
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 543
543 if (comp->is_fused_with_branch()) { 544 if (comp->is_fused_with_branch()) {
544 BranchInstr* branch = comp->fused_with_branch(); 545 BranchInstr* branch = comp->fused_with_branch();
545 BlockEntryInstr* nan_result = branch->is_negated() ? 546 BlockEntryInstr* nan_result = branch->is_negated() ?
546 branch->true_successor() : branch->false_successor(); 547 branch->true_successor() : branch->false_successor();
547 __ j(PARITY_EVEN, compiler->GetBlockLabel(nan_result)); 548 __ j(PARITY_EVEN, compiler->GetBlockLabel(nan_result));
548 branch->EmitBranchOnCondition(compiler, true_condition); 549 branch->EmitBranchOnCondition(compiler, true_condition);
549 } else { 550 } else {
550 Register result = comp->locs()->out().reg(); 551 Register result = comp->locs()->out().reg();
551 Label is_false, is_true, done; 552 Label is_false, is_true, done;
552 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); 553 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false;
553 __ j(true_condition, &is_true, Assembler::kNearJump); 554 __ j(true_condition, &is_true, Assembler::kNearJump);
554 __ Bind(&is_false); 555 __ Bind(&is_false);
555 __ LoadObject(result, compiler->bool_false()); 556 __ LoadObject(result, compiler->bool_false());
556 __ jmp(&done); 557 __ jmp(&done);
557 __ Bind(&is_true); 558 __ Bind(&is_true);
558 __ LoadObject(result, compiler->bool_true()); 559 __ LoadObject(result, compiler->bool_true());
559 __ Bind(&done); 560 __ Bind(&done);
560 } 561 }
561 } 562 }
562 563
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { 636 LocationSummary* LoadIndexedComp::MakeLocationSummary() const {
636 const intptr_t kNumInputs = 2; 637 const intptr_t kNumInputs = 2;
637 if (receiver_type() == kGrowableObjectArray) { 638 if (receiver_type() == kGrowableObjectArray) {
638 const intptr_t kNumTemps = 1; 639 const intptr_t kNumTemps = 1;
639 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); 640 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps);
640 locs->set_in(0, Location::RequiresRegister()); 641 locs->set_in(0, Location::RequiresRegister());
641 locs->set_in(1, Location::RequiresRegister()); 642 locs->set_in(1, Location::RequiresRegister());
642 locs->set_temp(0, Location::RequiresRegister()); 643 locs->set_temp(0, Location::RequiresRegister());
643 locs->set_out(Location::RequiresRegister()); 644 locs->set_out(Location::RequiresRegister());
644 return locs; 645 return locs;
645 } else if (receiver_type() == kArray || receiver_type() == kImmutableArray) { 646 } else if ((receiver_type() == kArray) ||
647 (receiver_type() == kImmutableArray)) {
646 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); 648 return LocationSummary::Make(kNumInputs, Location::RequiresRegister());
647 } else { 649 } else {
648 ASSERT(receiver_type() == kIllegalObjectKind); 650 ASSERT(receiver_type() == kIllegalObjectKind);
649 return MakeCallSummary(); 651 return MakeCallSummary();
650 } 652 }
651 } 653 }
652 654
653 655
654 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, 656 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler,
655 LoadIndexedComp* comp) { 657 LoadIndexedComp* comp) {
(...skipping 22 matching lines...) Expand all
678 kNumArguments, 680 kNumArguments,
679 Array::Handle(), // No named arguments. 681 Array::Handle(), // No named arguments.
680 deopt, &done, // Labels. 682 deopt, &done, // Labels.
681 comp->cid(), 683 comp->cid(),
682 comp->token_index(), 684 comp->token_index(),
683 comp->try_index()); 685 comp->try_index());
684 __ Bind(&done); 686 __ Bind(&done);
685 } 687 }
686 688
687 689
688
689 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { 690 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) {
690 if (receiver_type() == kIllegalObjectKind) { 691 if (receiver_type() == kIllegalObjectKind) {
691 if (HasICData()) { 692 if (HasICData()) {
692 EmitLoadIndexedPolymorphic(compiler, this); 693 EmitLoadIndexedPolymorphic(compiler, this);
693 } else { 694 } else {
694 compiler->EmitLoadIndexedGeneric(this); 695 compiler->EmitLoadIndexedGeneric(this);
695 } 696 }
696 ASSERT(locs()->out().reg() == RAX); 697 ASSERT(locs()->out().reg() == RAX);
697 return; 698 return;
698 } 699 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 return locs; 763 return locs;
763 } else if (receiver_type() == kArray) { 764 } else if (receiver_type() == kArray) {
764 return LocationSummary::Make(kNumInputs, Location::NoLocation()); 765 return LocationSummary::Make(kNumInputs, Location::NoLocation());
765 } else { 766 } else {
766 ASSERT(receiver_type() == kIllegalObjectKind); 767 ASSERT(receiver_type() == kIllegalObjectKind);
767 return MakeCallSummary(); 768 return MakeCallSummary();
768 } 769 }
769 } 770 }
770 771
771 772
772
773 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, 773 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler,
774 StoreIndexedComp* comp) { 774 StoreIndexedComp* comp) {
775 const String& function_name = 775 const String& function_name =
776 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); 776 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX)));
777 777
778 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 778 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
779 comp->cid(), 779 comp->cid(),
780 comp->token_index(), 780 comp->token_index(),
781 comp->try_index()); 781 comp->try_index());
782 782
783 const intptr_t kNumArguments = 3; 783 const intptr_t kNumArguments = 3;
784 const intptr_t kNumArgsChecked = 1; // Type-feedback. 784 const intptr_t kNumArgsChecked = 1; // Type-feedback.
785 compiler->GenerateInstanceCall(comp->cid(), 785 compiler->GenerateInstanceCall(comp->cid(),
786 comp->token_index(), 786 comp->token_index(),
787 comp->try_index(), 787 comp->try_index(),
788 function_name, 788 function_name,
789 kNumArguments, 789 kNumArguments,
790 Array::ZoneHandle(), // No names arguments. 790 Array::ZoneHandle(), // No named arguments.
791 kNumArgsChecked); 791 kNumArgsChecked);
792 } 792 }
793 793
794 794
795 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, 795 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler,
796 StoreIndexedComp* comp) { 796 StoreIndexedComp* comp) {
797 Label* deopt = compiler->AddDeoptStub(comp->cid(), 797 Label* deopt = compiler->AddDeoptStub(comp->cid(),
798 comp->token_index(), 798 comp->token_index(),
799 comp->try_index(), 799 comp->try_index(),
800 kDeoptStoreIndexedPolymorphic); 800 kDeoptStoreIndexedPolymorphic);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 } else { 833 } else {
834 EmitStoreIndexedGeneric(compiler, this); 834 EmitStoreIndexedGeneric(compiler, this);
835 } 835 }
836 return; 836 return;
837 } 837 }
838 838
839 Register receiver = locs()->in(0).reg(); 839 Register receiver = locs()->in(0).reg();
840 Register index = locs()->in(1).reg(); 840 Register index = locs()->in(1).reg();
841 Register value = locs()->in(2).reg(); 841 Register value = locs()->in(2).reg();
842 842
843 const Class& receiver_class =
844 Class::ZoneHandle(Isolate::Current()->class_table()->At(
845 receiver_type()));
846
847 Label* deopt = compiler->AddDeoptStub(cid(), 843 Label* deopt = compiler->AddDeoptStub(cid(),
848 token_index(), 844 token_index(),
849 try_index(), 845 try_index(),
850 kDeoptStoreIndexed, 846 kDeoptStoreIndexed,
851 receiver, 847 receiver,
852 index, 848 index,
853 value); 849 value);
854 850
855 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. 851 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi.
856 __ j(ZERO, deopt); 852 __ j(ZERO, deopt);
857 __ CompareClassId(receiver, receiver_class.id()); 853 __ CompareClassId(receiver, receiver_type());
858 __ j(NOT_EQUAL, deopt); 854 __ j(NOT_EQUAL, deopt);
859 855
860 __ testq(index, Immediate(kSmiTagMask)); 856 __ testq(index, Immediate(kSmiTagMask));
861 __ j(NOT_ZERO, deopt); 857 __ j(NOT_ZERO, deopt);
862 858
863 switch (receiver_type()) { 859 switch (receiver_type()) {
864 case kArray: 860 case kArray:
865 case kImmutableArray: 861 case kImmutableArray:
866 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); 862 __ cmpq(index, FieldAddress(receiver, Array::length_offset()));
867 __ j(ABOVE_EQUAL, deopt); 863 __ j(ABOVE_EQUAL, deopt);
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 locs->set_temp(0, Location::RegisterLocation(R10)); 1021 locs->set_temp(0, Location::RegisterLocation(R10));
1026 locs->set_out(Location::RegisterLocation(RAX)); 1022 locs->set_out(Location::RegisterLocation(RAX));
1027 return locs; 1023 return locs;
1028 } 1024 }
1029 1025
1030 1026
1031 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1027 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1032 Register temp_reg = locs()->temp(0).reg(); 1028 Register temp_reg = locs()->temp(0).reg();
1033 Register result_reg = locs()->out().reg(); 1029 Register result_reg = locs()->out().reg();
1034 1030
1035 // 1. Allocate the array. R10 = length, RBX = element type. 1031 // Allocate the array. R10 = length, RBX = element type.
1036 ASSERT(temp_reg == R10); 1032 ASSERT(temp_reg == R10);
1037 ASSERT(locs()->in(0).reg() == RBX); 1033 ASSERT(locs()->in(0).reg() == RBX);
1038 __ movq(temp_reg, Immediate(Smi::RawValue(ElementCount()))); 1034 __ movq(temp_reg, Immediate(Smi::RawValue(ElementCount())));
1039 compiler->GenerateCall(token_index(), 1035 compiler->GenerateCall(token_index(),
1040 try_index(), 1036 try_index(),
1041 &StubCode::AllocateArrayLabel(), 1037 &StubCode::AllocateArrayLabel(),
1042 PcDescriptors::kOther); 1038 PcDescriptors::kOther);
1043 ASSERT(result_reg == RAX); 1039 ASSERT(result_reg == RAX);
1044 // 2. Initialize the array in result_reg with the element values. 1040
1041 // Pop the element values from the stack into the array.
1045 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); 1042 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset()));
1046 for (int i = ElementCount() - 1; i >= 0; --i) { 1043 for (int i = ElementCount() - 1; i >= 0; --i) {
1047 ASSERT(ElementAt(i)->IsUse()); 1044 ASSERT(ElementAt(i)->IsUse());
1048 __ popq(Address(temp_reg, i * kWordSize)); 1045 __ popq(Address(temp_reg, i * kWordSize));
1049 } 1046 }
1050 } 1047 }
1051 1048
1052 1049
1053 LocationSummary* AllocateObjectWithBoundsCheckComp:: 1050 LocationSummary*
1054 MakeLocationSummary() const { 1051 AllocateObjectWithBoundsCheckComp::MakeLocationSummary() const {
1055 return LocationSummary::Make(2, 1052 return LocationSummary::Make(2,
1056 Location::RequiresRegister(), 1053 Location::RequiresRegister(),
1057 LocationSummary::kCall); 1054 LocationSummary::kCall);
1058 } 1055 }
1059 1056
1060 1057
1061 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( 1058 void AllocateObjectWithBoundsCheckComp::EmitNativeCode(
1062 FlowGraphCompiler* compiler) { 1059 FlowGraphCompiler* compiler) {
1063 const Class& cls = Class::ZoneHandle(constructor().owner()); 1060 const Class& cls = Class::ZoneHandle(constructor().owner());
1064 Register type_arguments = locs()->in(0).reg(); 1061 Register type_arguments = locs()->in(0).reg();
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 Label type_arguments_instantiated; 1130 Label type_arguments_instantiated;
1134 const intptr_t len = type_arguments().Length(); 1131 const intptr_t len = type_arguments().Length();
1135 if (type_arguments().IsRawInstantiatedRaw(len)) { 1132 if (type_arguments().IsRawInstantiatedRaw(len)) {
1136 const Immediate raw_null = 1133 const Immediate raw_null =
1137 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1134 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1138 __ cmpq(instantiator_reg, raw_null); 1135 __ cmpq(instantiator_reg, raw_null);
1139 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 1136 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
1140 } 1137 }
1141 // Instantiate non-null type arguments. 1138 // Instantiate non-null type arguments.
1142 if (type_arguments().IsUninstantiatedIdentity()) { 1139 if (type_arguments().IsUninstantiatedIdentity()) {
1143 Label type_arguments_uninstantiated;
1144 // Check if the instantiator type argument vector is a TypeArguments of a 1140 // Check if the instantiator type argument vector is a TypeArguments of a
1145 // matching length and, if so, use it as the instantiated type_arguments. 1141 // matching length and, if so, use it as the instantiated type_arguments.
1146 // No need to check the instantiator ('instantiator_reg') for null here, 1142 // No need to check the instantiator ('instantiator_reg') for null here,
1147 // because a null instantiator will have the wrong class (Null instead of 1143 // because a null instantiator will have the wrong class (Null instead of
1148 // TypeArguments). 1144 // TypeArguments).
1145 Label type_arguments_uninstantiated;
1149 __ CompareClassId(instantiator_reg, kTypeArguments); 1146 __ CompareClassId(instantiator_reg, kTypeArguments);
1150 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); 1147 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump);
1151 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), 1148 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()),
1152 Immediate(Smi::RawValue(len))); 1149 Immediate(Smi::RawValue(len)));
1153 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 1150 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
1154 __ Bind(&type_arguments_uninstantiated); 1151 __ Bind(&type_arguments_uninstantiated);
1155 } 1152 }
1156 // A runtime call to instantiate the type arguments is required. 1153 // A runtime call to instantiate the type arguments is required.
1157 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1154 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1158 __ PushObject(type_arguments()); 1155 __ PushObject(type_arguments());
1159 __ pushq(instantiator_reg); // Push instantiator type arguments. 1156 __ pushq(instantiator_reg); // Push instantiator type arguments.
1160 compiler->GenerateCallRuntime(cid(), 1157 compiler->GenerateCallRuntime(cid(),
1161 token_index(), 1158 token_index(),
1162 try_index(), 1159 try_index(),
1163 kInstantiateTypeArgumentsRuntimeEntry); 1160 kInstantiateTypeArgumentsRuntimeEntry);
1164 __ Drop(2); // Drop instantiator and uninstantiated type arguments. 1161 __ Drop(2); // Drop instantiator and uninstantiated type arguments.
1165 __ popq(result_reg); // Pop instantiated type arguments. 1162 __ popq(result_reg); // Pop instantiated type arguments.
1166 __ Bind(&type_arguments_instantiated); 1163 __ Bind(&type_arguments_instantiated);
1167 ASSERT(instantiator_reg == result_reg); 1164 ASSERT(instantiator_reg == result_reg);
1168 // 'result_reg': Instantiated type arguments. 1165 // 'result_reg': Instantiated type arguments.
1169 } 1166 }
1170 1167
1171 1168
1172 LocationSummary* ExtractConstructorTypeArgumentsComp:: 1169 LocationSummary*
1173 MakeLocationSummary() const { 1170 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const {
1174 const intptr_t kNumInputs = 1; 1171 const intptr_t kNumInputs = 1;
1175 const intptr_t kNumTemps = 0; 1172 const intptr_t kNumTemps = 0;
1176 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); 1173 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps);
1177 locs->set_in(0, Location::RequiresRegister()); 1174 locs->set_in(0, Location::RequiresRegister());
1178 locs->set_out(Location::SameAsFirstInput()); 1175 locs->set_out(Location::SameAsFirstInput());
1179 return locs; 1176 return locs;
1180 } 1177 }
1181 1178
1182 1179
1183 void ExtractConstructorTypeArgumentsComp::EmitNativeCode( 1180 void ExtractConstructorTypeArgumentsComp::EmitNativeCode(
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1217 } 1214 }
1218 // In the non-factory case, we rely on the allocation stub to 1215 // In the non-factory case, we rely on the allocation stub to
1219 // instantiate the type arguments. 1216 // instantiate the type arguments.
1220 __ LoadObject(result_reg, type_arguments()); 1217 __ LoadObject(result_reg, type_arguments());
1221 // result_reg: uninstantiated type arguments. 1218 // result_reg: uninstantiated type arguments.
1222 __ Bind(&type_arguments_instantiated); 1219 __ Bind(&type_arguments_instantiated);
1223 // result_reg: uninstantiated or instantiated type arguments. 1220 // result_reg: uninstantiated or instantiated type arguments.
1224 } 1221 }
1225 1222
1226 1223
1227 LocationSummary* ExtractConstructorInstantiatorComp:: 1224 LocationSummary*
1228 MakeLocationSummary() const { 1225 ExtractConstructorInstantiatorComp::MakeLocationSummary() const {
1229 const intptr_t kNumInputs = 1; 1226 const intptr_t kNumInputs = 1;
1230 const intptr_t kNumTemps = 0; 1227 const intptr_t kNumTemps = 0;
1231 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); 1228 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps);
1232 locs->set_in(0, Location::RequiresRegister()); 1229 locs->set_in(0, Location::RequiresRegister());
1233 locs->set_out(Location::SameAsFirstInput()); 1230 locs->set_out(Location::SameAsFirstInput());
1234 return locs; 1231 return locs;
1235 } 1232 }
1236 1233
1237 1234
1238 void ExtractConstructorInstantiatorComp::EmitNativeCode( 1235 void ExtractConstructorInstantiatorComp::EmitNativeCode(
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 kNumTemps, 1293 kNumTemps,
1297 LocationSummary::kCall); 1294 LocationSummary::kCall);
1298 locs->set_temp(0, Location::RegisterLocation(R10)); 1295 locs->set_temp(0, Location::RegisterLocation(R10));
1299 locs->set_out(Location::RegisterLocation(RAX)); 1296 locs->set_out(Location::RegisterLocation(RAX));
1300 return locs; 1297 return locs;
1301 } 1298 }
1302 1299
1303 1300
1304 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1301 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1305 ASSERT(locs()->temp(0).reg() == R10); 1302 ASSERT(locs()->temp(0).reg() == R10);
1303 ASSERT(locs()->out().reg() == RAX);
1306 1304
1307 __ movq(R10, Immediate(num_context_variables())); 1305 __ movq(R10, Immediate(num_context_variables()));
1308 const ExternalLabel label("alloc_context", 1306 const ExternalLabel label("alloc_context",
1309 StubCode::AllocateContextEntryPoint()); 1307 StubCode::AllocateContextEntryPoint());
1310 compiler->GenerateCall(token_index(), 1308 compiler->GenerateCall(token_index(),
1311 try_index(), 1309 try_index(),
1312 &label, 1310 &label,
1313 PcDescriptors::kOther); 1311 PcDescriptors::kOther);
1314 } 1312 }
1315 1313
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1421 return summary; 1419 return summary;
1422 } else if (op_kind() == Token::kSHR) { 1420 } else if (op_kind() == Token::kSHR) {
1423 const intptr_t kNumTemps = 1; 1421 const intptr_t kNumTemps = 1;
1424 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); 1422 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
1425 summary->set_in(0, Location::RequiresRegister()); 1423 summary->set_in(0, Location::RequiresRegister());
1426 summary->set_in(1, Location::RegisterLocation(RCX)); 1424 summary->set_in(1, Location::RegisterLocation(RCX));
1427 summary->set_out(Location::SameAsFirstInput()); 1425 summary->set_out(Location::SameAsFirstInput());
1428 summary->set_temp(0, Location::RequiresRegister()); 1426 summary->set_temp(0, Location::RequiresRegister());
1429 return summary; 1427 return summary;
1430 } else if (op_kind() == Token::kSHL) { 1428 } else if (op_kind() == Token::kSHL) {
1429 // Two Smi operands can easily overflow into Mint.
1431 const intptr_t kNumTemps = 2; 1430 const intptr_t kNumTemps = 2;
1432 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); 1431 LocationSummary* summary =
1433 summary->set_in(0, Location::RequiresRegister()); 1432 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
1433 summary->set_in(0, Location::RegisterLocation(RAX));
1434 summary->set_in(1, Location::RequiresRegister()); 1434 summary->set_in(1, Location::RequiresRegister());
1435 summary->set_out(Location::SameAsFirstInput()); 1435 summary->set_out(Location::SameAsFirstInput());
1436 summary->set_temp(0, Location::RequiresRegister()); 1436 summary->set_temp(0, Location::RequiresRegister());
1437 summary->set_temp(1, Location::RegisterLocation(RCX)); 1437 summary->set_temp(1, Location::RegisterLocation(RCX));
1438 return summary; 1438 return summary;
1439 } else { 1439 } else {
1440 const intptr_t kNumTemps = 1; 1440 const intptr_t kNumTemps = 1;
1441 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); 1441 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
1442 summary->set_in(0, Location::RequiresRegister()); 1442 summary->set_in(0, Location::RequiresRegister());
1443 summary->set_in(1, Location::RequiresRegister()); 1443 summary->set_in(1, Location::RequiresRegister());
1444 summary->set_out(Location::SameAsFirstInput()); 1444 summary->set_out(Location::SameAsFirstInput());
1445 summary->set_temp(0, Location::RequiresRegister()); 1445 summary->set_temp(0, Location::RequiresRegister());
1446 return summary; 1446 return summary;
1447 } 1447 }
1448 } 1448 }
1449 1449
1450 1450
1451 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { 1451 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) {
1452 Register left = comp->locs()->in(0).reg(); 1452 Register left = comp->locs()->in(0).reg();
1453 Register right = comp->locs()->in(1).reg(); 1453 Register right = comp->locs()->in(1).reg();
1454 Register result = comp->locs()->out().reg(); 1454 Register result = comp->locs()->out().reg();
1455 Register temp = comp->locs()->temp(0).reg(); 1455 Register temp = comp->locs()->temp(0).reg();
1456 ASSERT(left == result); 1456 ASSERT(left == result);
1457 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), 1457 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(),
1458 comp->instance_call()->token_index(), 1458 comp->instance_call()->token_index(),
1459 comp->instance_call()->try_index(), 1459 comp->instance_call()->try_index(),
1460 kDeoptSmiBinaryOp, 1460 kDeoptSmiBinaryOp,
1461 temp, 1461 temp,
1462 right); 1462 right);
1463 // TODO(vegorov): for many binary operations this pattern can be rearranged
1464 // to save one move.
1463 __ movq(temp, left); 1465 __ movq(temp, left);
1464 __ orq(left, right); 1466 __ orq(left, right);
1465 __ testq(left, Immediate(kSmiTagMask)); 1467 __ testq(left, Immediate(kSmiTagMask));
1466 __ j(NOT_ZERO, deopt); 1468 __ j(NOT_ZERO, deopt);
1467 __ movq(left, temp); 1469 __ movq(left, temp);
1468 switch (comp->op_kind()) { 1470 switch (comp->op_kind()) {
1469 case Token::kADD: { 1471 case Token::kADD: {
1470 __ addq(left, right); 1472 __ addq(left, right);
1471 __ j(OVERFLOW, deopt); 1473 __ j(OVERFLOW, deopt);
1472 break; 1474 break;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 __ j(LESS, &count_ok, Assembler::kNearJump); 1533 __ j(LESS, &count_ok, Assembler::kNearJump);
1532 __ movq(right, kCountLimit); 1534 __ movq(right, kCountLimit);
1533 __ Bind(&count_ok); 1535 __ Bind(&count_ok);
1534 ASSERT(right == RCX); // Count must be in RCX 1536 ASSERT(right == RCX); // Count must be in RCX
1535 __ SmiUntag(left); 1537 __ SmiUntag(left);
1536 __ sarq(left, right); 1538 __ sarq(left, right);
1537 __ SmiTag(left); 1539 __ SmiTag(left);
1538 break; 1540 break;
1539 } 1541 }
1540 case Token::kSHL: { 1542 case Token::kSHL: {
1543 Label call_method, done;
1541 // Check if count too large for handling it inlined. 1544 // Check if count too large for handling it inlined.
1542 __ cmpq(right, 1545 __ cmpq(right,
1543 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); 1546 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))));
1544 __ j(ABOVE_EQUAL, deopt); 1547 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump);
1545 Register right_temp = comp->locs()->temp(1).reg(); 1548 Register right_temp = comp->locs()->temp(1).reg();
1546 ASSERT(right_temp == RCX); // Count must be in RCX 1549 ASSERT(right_temp == RCX); // Count must be in RCX
1547 __ movq(right_temp, right); 1550 __ movq(right_temp, right);
1548 __ SmiUntag(right_temp); 1551 __ SmiUntag(right_temp);
1549 // Overflow test (preserve temp and right); 1552 // Overflow test (preserve temp and right);
1550 __ shlq(left, right_temp); 1553 __ shlq(left, right_temp);
1551 __ sarq(left, right_temp); 1554 __ sarq(left, right_temp);
1552 __ cmpq(left, temp); 1555 __ cmpq(left, temp);
1553 __ j(NOT_EQUAL, deopt); // Overflow. 1556 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow.
1554 // Shift for result now we know there is no overflow. 1557 // Shift for result now we know there is no overflow.
1555 __ shlq(left, right_temp); 1558 __ shlq(left, right_temp);
1559 __ jmp(&done);
1560 {
1561 __ Bind(&call_method);
1562 Function& target = Function::ZoneHandle(
1563 comp->ic_data()->GetTargetForReceiverClassId(kSmi));
1564 ASSERT(!target.IsNull());
1565 const intptr_t kArgumentCount = 2;
1566 __ pushq(temp);
1567 __ pushq(right);
1568 compiler->GenerateStaticCall(comp->instance_call()->cid(),
1569 comp->instance_call()->token_index(),
1570 comp->instance_call()->try_index(),
1571 target,
1572 kArgumentCount,
1573 Array::Handle()); // No argument names.
1574 ASSERT(result == RAX);
1575 }
1576 __ Bind(&done);
1556 break; 1577 break;
1557 } 1578 }
1558 case Token::kDIV: { 1579 case Token::kDIV: {
1559 // Dispatches to 'Double./'. 1580 // Dispatches to 'Double./'.
1560 // TODO(srdjan): Implement as conversion to double and double division. 1581 // TODO(srdjan): Implement as conversion to double and double division.
1561 UNREACHABLE(); 1582 UNREACHABLE();
1562 break; 1583 break;
1563 } 1584 }
1564 case Token::kMOD: { 1585 case Token::kMOD: {
1565 // TODO(srdjan): Implement. 1586 // TODO(srdjan): Implement.
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
1846 LocationSummary* ToDoubleComp::MakeLocationSummary() const { 1867 LocationSummary* ToDoubleComp::MakeLocationSummary() const {
1847 const intptr_t kNumInputs = 1; 1868 const intptr_t kNumInputs = 1;
1848 if (from() == kDouble) { 1869 if (from() == kDouble) {
1849 const intptr_t kNumTemps = 0; 1870 const intptr_t kNumTemps = 0;
1850 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); 1871 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps);
1851 locs->set_in(0, Location::RequiresRegister()); 1872 locs->set_in(0, Location::RequiresRegister());
1852 locs->set_out(Location::SameAsFirstInput()); 1873 locs->set_out(Location::SameAsFirstInput());
1853 return locs; 1874 return locs;
1854 } else { 1875 } else {
1855 ASSERT(from() == kSmi); 1876 ASSERT(from() == kSmi);
1856 return MakeCallSummary(); 1877 return MakeCallSummary(); // Calls a stub to allocate result.
1857 } 1878 }
1858 } 1879 }
1859 1880
1860 1881
1861 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1882 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1862 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; 1883 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX;
1863 Register result = locs()->out().reg(); 1884 Register result = locs()->out().reg();
1864 1885
1865 const DeoptReasonId deopt_reason = (from() == kDouble) ? 1886 const DeoptReasonId deopt_reason = (from() == kDouble) ?
1866 kDeoptDoubleToDouble : kDeoptIntegerToDouble; 1887 kDeoptDoubleToDouble : kDeoptIntegerToDouble;
(...skipping 12 matching lines...) Expand all
1879 return; 1900 return;
1880 } 1901 }
1881 1902
1882 ASSERT(from() == kSmi); 1903 ASSERT(from() == kSmi);
1883 1904
1884 const Class& double_class = compiler->double_class(); 1905 const Class& double_class = compiler->double_class();
1885 const Code& stub = 1906 const Code& stub =
1886 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); 1907 Code::Handle(StubCode::GetAllocationStubForClass(double_class));
1887 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); 1908 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
1888 1909
1889 // TODO(vegorov): allocate box in the driver loop to avoid pushing and poping. 1910 // TODO(vegorov): allocate box in the driver loop to avoid spilling.
1890 compiler->GenerateCall(instance_call()->token_index(), 1911 compiler->GenerateCall(instance_call()->token_index(),
1891 instance_call()->try_index(), 1912 instance_call()->try_index(),
1892 &label, 1913 &label,
1893 PcDescriptors::kOther); 1914 PcDescriptors::kOther);
1894 ASSERT(result == RAX); 1915 ASSERT(result == RAX);
1895 __ popq(value); 1916 __ popq(value);
1896 1917
1897 __ testq(value, Immediate(kSmiTagMask)); 1918 __ testq(value, Immediate(kSmiTagMask));
1898 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. 1919 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi.
1899 __ SmiUntag(value); 1920 __ SmiUntag(value);
(...skipping 15 matching lines...) Expand all
1915 kDeoptPolymorphicInstanceCallTestFail); 1936 kDeoptPolymorphicInstanceCallTestFail);
1916 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { 1937 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) {
1917 __ jmp(deopt); 1938 __ jmp(deopt);
1918 return; 1939 return;
1919 } 1940 }
1920 ASSERT(HasICData()); 1941 ASSERT(HasICData());
1921 ASSERT(ic_data()->num_args_tested() == 1); 1942 ASSERT(ic_data()->num_args_tested() == 1);
1922 Label handle_smi; 1943 Label handle_smi;
1923 Label* is_smi_label = 1944 Label* is_smi_label =
1924 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; 1945 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt;
1946
1925 // Load receiver into RAX. 1947 // Load receiver into RAX.
1926 __ movq(RAX, 1948 __ movq(RAX,
1927 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); 1949 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize));
1928 __ testq(RAX, Immediate(kSmiTagMask)); 1950 __ testq(RAX, Immediate(kSmiTagMask));
1929 __ j(ZERO, is_smi_label); 1951 __ j(ZERO, is_smi_label);
1930 Label done; 1952 Label done;
1931 __ LoadClassId(RDI, RAX); 1953 __ LoadClassId(RDI, RAX);
1932 compiler->EmitTestAndCall(*ic_data(), 1954 compiler->EmitTestAndCall(*ic_data(),
1933 RDI, // Class id register. 1955 RDI, // Class id register.
1934 instance_call()->ArgumentCount(), 1956 instance_call()->ArgumentCount(),
(...skipping 14 matching lines...) Expand all
1949 instance_call()->argument_names()); 1971 instance_call()->argument_names());
1950 } 1972 }
1951 __ Bind(&done); 1973 __ Bind(&done);
1952 } 1974 }
1953 1975
1954 } // namespace dart 1976 } // namespace dart
1955 1977
1956 #undef __ 1978 #undef __
1957 1979
1958 #endif // defined TARGET_ARCH_X64 1980 #endif // defined TARGET_ARCH_X64
OLDNEW
« runtime/vm/intermediate_language_ia32.cc ('K') | « runtime/vm/intermediate_language_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698