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/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" |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 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 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 24 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 25 computation()->EmitNativeCode(compiler); | 25 computation()->EmitNativeCode(compiler); |
| 26 if (locs()->out().kind() == Location::kRegister) { | 26 if (locs()->out().kind() == Location::kRegister) { |
| 27 // TODO(vegorov): this should really happen only for comparisons fused | 27 // TODO(vegorov): this should really happen only for comparisons fused |
| 28 // with branches. Currrently IR does not provide an easy way to remove | 28 // 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 | 29 // instructions from the graph so we just leave fused comparison in it |
| 30 // but change its result location to be NoLocation. | 30 // but change its result location to be NoLocation. |
| 31 __ pushq(locs()->out().reg()); | 31 compiler->frame_register_allocator()->Push(locs()->out().reg(), this); |
| 32 } | 32 } |
| 33 } | 33 } |
| 34 | 34 |
| 35 | 35 |
| 36 LocationSummary* ReturnInstr::MakeLocationSummary() const { | 36 LocationSummary* ReturnInstr::MakeLocationSummary() const { |
| 37 const intptr_t kNumInputs = 1; | 37 const intptr_t kNumInputs = 1; |
| 38 const intptr_t kNumTemps = 1; | 38 const intptr_t kNumTemps = 1; |
| 39 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 39 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 40 locs->set_in(0, Location::RegisterLocation(RAX)); | 40 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 41 locs->set_temp(0, Location::RequiresRegister()); | 41 locs->set_temp(0, Location::RequiresRegister()); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 98 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 99 cid(), | 99 cid(), |
| 100 token_index(), | 100 token_index(), |
| 101 CatchClauseNode::kInvalidTryIndex); | 101 CatchClauseNode::kInvalidTryIndex); |
| 102 } | 102 } |
| 103 | 103 |
| 104 | 104 |
| 105 // Generic summary for call instructions that have all arguments pushed | 105 // Generic summary for call instructions that have all arguments pushed |
| 106 // on the stack and return the result in a fixed register RAX. | 106 // on the stack and return the result in a fixed register RAX. |
| 107 LocationSummary* Computation::MakeCallSummary() { | 107 LocationSummary* Computation::MakeCallSummary() { |
| 108 LocationSummary* result = new LocationSummary(0, 0); | 108 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); |
| 109 result->set_out(Location::RegisterLocation(RAX)); | 109 result->set_out(Location::RegisterLocation(RAX)); |
| 110 return result; | 110 return result; |
| 111 } | 111 } |
| 112 | 112 |
| 113 | 113 |
| 114 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 114 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
| 115 const intptr_t kNumInputs = 0; | 115 const intptr_t kNumInputs = 0; |
| 116 const intptr_t kNumTemps = 1; | 116 const intptr_t kNumTemps = 1; |
| 117 LocationSummary* result = new LocationSummary(kNumInputs, kNumTemps); | 117 LocationSummary* result = new LocationSummary(kNumInputs, |
| 118 kNumTemps, | |
| 119 LocationSummary::kCall); | |
| 118 result->set_out(Location::RegisterLocation(RAX)); | 120 result->set_out(Location::RegisterLocation(RAX)); |
| 119 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. | 121 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. |
| 120 return result; | 122 return result; |
| 121 } | 123 } |
| 122 | 124 |
| 123 | 125 |
| 124 LocationSummary* LoadLocalComp::MakeLocationSummary() const { | 126 LocationSummary* LoadLocalComp::MakeLocationSummary() const { |
| 125 return LocationSummary::Make(0, Location::RequiresRegister()); | 127 return LocationSummary::Make(0, Location::RequiresRegister()); |
| 126 } | 128 } |
| 127 | 129 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 191 kConditionTypeErrorRuntimeEntry); | 193 kConditionTypeErrorRuntimeEntry); |
| 192 // We should never return here. | 194 // We should never return here. |
| 193 __ int3(); | 195 __ int3(); |
| 194 | 196 |
| 195 __ Bind(&done); | 197 __ Bind(&done); |
| 196 ASSERT(obj == result); | 198 ASSERT(obj == result); |
| 197 } | 199 } |
| 198 | 200 |
| 199 | 201 |
| 200 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 202 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
| 203 const LocationSummary::ContainsBranch contains_branch = | |
| 204 is_fused_with_branch() ? LocationSummary::kBranch | |
| 205 : LocationSummary::kNoBranch; | |
| 206 | |
| 201 const intptr_t kNumInputs = 2; | 207 const intptr_t kNumInputs = 2; |
| 202 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { | 208 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { |
| 203 const intptr_t kNumTemps = 1; | 209 const intptr_t kNumTemps = 1; |
| 204 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 210 LocationSummary* locs = new LocationSummary(kNumInputs, |
| 211 kNumTemps, | |
| 212 LocationSummary::kNoCall, | |
| 213 contains_branch); | |
| 205 locs->set_in(0, Location::RequiresRegister()); | 214 locs->set_in(0, Location::RequiresRegister()); |
| 206 locs->set_in(1, Location::RequiresRegister()); | 215 locs->set_in(1, Location::RequiresRegister()); |
| 207 locs->set_temp(0, Location::RequiresRegister()); | 216 locs->set_temp(0, Location::RequiresRegister()); |
| 208 if (!is_fused_with_branch()) { | 217 if (!is_fused_with_branch()) { |
| 209 locs->set_out(Location::RequiresRegister()); | 218 locs->set_out(Location::RequiresRegister()); |
| 210 } | 219 } |
| 211 return locs; | 220 return locs; |
| 212 } | 221 } |
| 213 if (NumTargets() > 0) { | 222 if (NumTargets() > 0) { |
| 214 const intptr_t kNumTemps = 1; | 223 const intptr_t kNumTemps = 1; |
| 215 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 224 LocationSummary* locs = new LocationSummary(kNumInputs, |
| 225 kNumTemps, | |
| 226 LocationSummary::kCall, | |
| 227 contains_branch); | |
| 216 locs->set_in(0, Location::RequiresRegister()); | 228 locs->set_in(0, Location::RequiresRegister()); |
| 217 locs->set_in(1, Location::RequiresRegister()); | 229 locs->set_in(1, Location::RequiresRegister()); |
| 218 locs->set_temp(0, Location::RequiresRegister()); | 230 locs->set_temp(0, Location::RequiresRegister()); |
| 219 if (!is_fused_with_branch()) { | 231 if (!is_fused_with_branch()) { |
| 220 locs->set_out(Location::RegisterLocation(RAX)); | 232 locs->set_out(Location::RegisterLocation(RAX)); |
| 221 } | 233 } |
| 222 return locs; | 234 return locs; |
| 223 } | 235 } |
| 224 const intptr_t kNumTemps = 0; | 236 const intptr_t kNumTemps = 0; |
| 225 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 237 LocationSummary* locs = new LocationSummary(kNumInputs, |
| 238 kNumTemps, | |
| 239 LocationSummary::kCall, | |
| 240 contains_branch); | |
| 226 locs->set_in(0, Location::RequiresRegister()); | 241 locs->set_in(0, Location::RequiresRegister()); |
| 227 locs->set_in(1, Location::RequiresRegister()); | 242 locs->set_in(1, Location::RequiresRegister()); |
| 228 if (!is_fused_with_branch()) { | 243 if (!is_fused_with_branch()) { |
| 229 locs->set_out(Location::RegisterLocation(RAX)); | 244 locs->set_out(Location::RegisterLocation(RAX)); |
| 230 } | 245 } |
| 231 return locs; | 246 return locs; |
| 232 } | 247 } |
| 233 | 248 |
| 234 | 249 |
| 235 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 250 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 406 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 421 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 407 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { | 422 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { |
| 408 EmitSmiEqualityCompare(compiler, this); | 423 EmitSmiEqualityCompare(compiler, this); |
| 409 return; | 424 return; |
| 410 } | 425 } |
| 411 EmitGenericEqualityCompare(compiler, this); | 426 EmitGenericEqualityCompare(compiler, this); |
| 412 } | 427 } |
| 413 | 428 |
| 414 | 429 |
| 415 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 430 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
| 431 const LocationSummary::ContainsBranch contains_branch = | |
| 432 is_fused_with_branch() ? LocationSummary::kBranch | |
| 433 : LocationSummary::kNoBranch; | |
| 434 | |
| 416 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { | 435 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { |
| 417 const intptr_t kNumInputs = 2; | 436 const intptr_t kNumInputs = 2; |
| 418 const intptr_t kNumTemps = 1; | 437 const intptr_t kNumTemps = 1; |
| 419 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 438 LocationSummary* summary = new LocationSummary(kNumInputs, |
| 439 kNumTemps, | |
| 440 LocationSummary::kCall, | |
| 441 contains_branch); | |
| 420 summary->set_in(0, Location::RequiresRegister()); | 442 summary->set_in(0, Location::RequiresRegister()); |
| 421 summary->set_in(1, Location::RequiresRegister()); | 443 summary->set_in(1, Location::RequiresRegister()); |
| 422 if (!is_fused_with_branch()) { | 444 if (!is_fused_with_branch()) { |
| 423 summary->set_out(Location::RequiresRegister()); | 445 summary->set_out(Location::RequiresRegister()); |
| 424 } | 446 } |
| 425 summary->set_temp(0, Location::RequiresRegister()); | 447 summary->set_temp(0, Location::RequiresRegister()); |
| 426 return summary; | 448 return summary; |
| 427 } | 449 } |
| 428 ASSERT(!is_fused_with_branch()); | 450 ASSERT(!is_fused_with_branch()); |
| 429 ASSERT(operands_class_id() == kObject); | 451 ASSERT(operands_class_id() == kObject); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 553 try_index(), | 575 try_index(), |
| 554 function_name, | 576 function_name, |
| 555 kNumArguments, | 577 kNumArguments, |
| 556 Array::ZoneHandle(), // No optional arguments. | 578 Array::ZoneHandle(), // No optional arguments. |
| 557 kNumArgsChecked); | 579 kNumArgsChecked); |
| 558 ASSERT(locs()->out().reg() == RAX); | 580 ASSERT(locs()->out().reg() == RAX); |
| 559 } | 581 } |
| 560 | 582 |
| 561 | 583 |
| 562 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 584 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
| 563 LocationSummary* locs = new LocationSummary(0, 3); | 585 const intptr_t kNumInputs = 0; |
| 586 const intptr_t kNumTemps = 3; | |
| 587 LocationSummary* locs = new LocationSummary(kNumInputs, | |
| 588 kNumTemps, | |
| 589 LocationSummary::kCall); | |
| 564 locs->set_temp(0, Location::RegisterLocation(RAX)); | 590 locs->set_temp(0, Location::RegisterLocation(RAX)); |
| 565 locs->set_temp(1, Location::RegisterLocation(RBX)); | 591 locs->set_temp(1, Location::RegisterLocation(RBX)); |
| 566 locs->set_temp(2, Location::RegisterLocation(R10)); | 592 locs->set_temp(2, Location::RegisterLocation(R10)); |
| 567 locs->set_out(Location::RequiresRegister()); | 593 locs->set_out(Location::RequiresRegister()); |
| 568 return locs; | 594 return locs; |
| 569 } | 595 } |
| 570 | 596 |
| 571 | 597 |
| 572 void NativeCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 598 void NativeCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 573 ASSERT(locs()->temp(0).reg() == RAX); | 599 ASSERT(locs()->temp(0).reg() == RAX); |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 772 } | 798 } |
| 773 | 799 |
| 774 default: | 800 default: |
| 775 UNREACHABLE(); | 801 UNREACHABLE(); |
| 776 break; | 802 break; |
| 777 } | 803 } |
| 778 } | 804 } |
| 779 | 805 |
| 780 | 806 |
| 781 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { | 807 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { |
| 782 const intptr_t kNumInputs = 2; | 808 return MakeCallSummary(); |
| 783 return LocationSummary::Make(kNumInputs, Location::NoLocation()); | |
| 784 return NULL; | |
| 785 } | 809 } |
| 786 | 810 |
| 787 | 811 |
| 788 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 812 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 789 Register receiver = locs()->in(0).reg(); | |
| 790 Register value = locs()->in(1).reg(); | |
| 791 | |
| 792 // Preserve the value (second argument) under the arguments as the result | |
| 793 // of the computation, then call the setter. | |
| 794 const String& function_name = | 813 const String& function_name = |
| 795 String::ZoneHandle(Field::SetterSymbol(field_name())); | 814 String::ZoneHandle(Field::SetterSymbol(field_name())); |
| 796 | 815 |
| 797 __ pushq(receiver); | |
| 798 __ pushq(value); | |
| 799 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 816 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 800 cid(), | 817 cid(), |
| 801 token_index(), | 818 token_index(), |
| 802 try_index()); | 819 try_index()); |
| 803 const intptr_t kArgumentCount = 2; | 820 const intptr_t kArgumentCount = 2; |
| 804 const intptr_t kCheckedArgumentCount = 1; | 821 const intptr_t kCheckedArgumentCount = 1; |
| 805 compiler->GenerateInstanceCall(cid(), | 822 compiler->GenerateInstanceCall(cid(), |
| 806 token_index(), | 823 token_index(), |
| 807 try_index(), | 824 try_index(), |
| 808 function_name, | 825 function_name, |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 904 } | 921 } |
| 905 | 922 |
| 906 | 923 |
| 907 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 924 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
| 908 // TODO(regis): The elements of the array could be considered as arguments to | 925 // TODO(regis): The elements of the array could be considered as arguments to |
| 909 // CreateArrayComp, thereby making CreateArrayComp a call. | 926 // CreateArrayComp, thereby making CreateArrayComp a call. |
| 910 // For VerifyCallComputation to work, CreateArrayComp would need an | 927 // For VerifyCallComputation to work, CreateArrayComp would need an |
| 911 // ArgumentCount getter and an ArgumentAt getter. | 928 // ArgumentCount getter and an ArgumentAt getter. |
| 912 const intptr_t kNumInputs = 1; | 929 const intptr_t kNumInputs = 1; |
| 913 const intptr_t kNumTemps = 1; | 930 const intptr_t kNumTemps = 1; |
| 914 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 931 LocationSummary* locs = new LocationSummary(kNumInputs, |
| 932 kNumTemps, | |
| 933 LocationSummary::kCall); | |
| 915 locs->set_in(0, Location::RegisterLocation(RBX)); | 934 locs->set_in(0, Location::RegisterLocation(RBX)); |
| 916 locs->set_temp(0, Location::RegisterLocation(R10)); | 935 locs->set_temp(0, Location::RegisterLocation(R10)); |
| 917 locs->set_out(Location::RegisterLocation(RAX)); | 936 locs->set_out(Location::RegisterLocation(RAX)); |
| 918 return locs; | 937 return locs; |
| 919 } | 938 } |
| 920 | 939 |
| 921 | 940 |
| 922 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 941 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 923 Register temp_reg = locs()->temp(0).reg(); | 942 Register temp_reg = locs()->temp(0).reg(); |
| 924 Register result_reg = locs()->out().reg(); | 943 Register result_reg = locs()->out().reg(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 936 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); | 955 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); |
| 937 for (int i = ElementCount() - 1; i >= 0; --i) { | 956 for (int i = ElementCount() - 1; i >= 0; --i) { |
| 938 ASSERT(ElementAt(i)->IsUse()); | 957 ASSERT(ElementAt(i)->IsUse()); |
| 939 __ popq(Address(temp_reg, i * kWordSize)); | 958 __ popq(Address(temp_reg, i * kWordSize)); |
| 940 } | 959 } |
| 941 } | 960 } |
| 942 | 961 |
| 943 | 962 |
| 944 LocationSummary* AllocateObjectWithBoundsCheckComp:: | 963 LocationSummary* AllocateObjectWithBoundsCheckComp:: |
| 945 MakeLocationSummary() const { | 964 MakeLocationSummary() const { |
| 946 return LocationSummary::Make(2, Location::RequiresRegister()); | 965 return LocationSummary::Make(2, |
| 966 Location::RequiresRegister(), | |
| 967 LocationSummary::kCall); | |
| 947 } | 968 } |
| 948 | 969 |
| 949 | 970 |
| 950 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 971 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( |
| 951 FlowGraphCompiler* compiler) { | 972 FlowGraphCompiler* compiler) { |
| 952 const Class& cls = Class::ZoneHandle(constructor().owner()); | 973 const Class& cls = Class::ZoneHandle(constructor().owner()); |
| 953 Register type_arguments = locs()->in(0).reg(); | 974 Register type_arguments = locs()->in(0).reg(); |
| 954 Register instantiator_type_arguments = locs()->in(1).reg(); | 975 Register instantiator_type_arguments = locs()->in(1).reg(); |
| 955 Register result = locs()->out().reg(); | 976 Register result = locs()->out().reg(); |
| 956 | 977 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 992 compiler->EmitClassChecksNoSmi(*class_ids(), instance, result, deopt); | 1013 compiler->EmitClassChecksNoSmi(*class_ids(), instance, result, deopt); |
| 993 } | 1014 } |
| 994 | 1015 |
| 995 __ movq(result, FieldAddress(instance, offset_in_bytes())); | 1016 __ movq(result, FieldAddress(instance, offset_in_bytes())); |
| 996 } | 1017 } |
| 997 | 1018 |
| 998 | 1019 |
| 999 LocationSummary* InstantiateTypeArgumentsComp::MakeLocationSummary() const { | 1020 LocationSummary* InstantiateTypeArgumentsComp::MakeLocationSummary() const { |
| 1000 const intptr_t kNumInputs = 1; | 1021 const intptr_t kNumInputs = 1; |
| 1001 const intptr_t kNumTemps = 0; | 1022 const intptr_t kNumTemps = 0; |
| 1002 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1023 LocationSummary* locs = new LocationSummary(kNumInputs, |
| 1024 kNumTemps, | |
| 1025 LocationSummary::kCall); | |
| 1003 locs->set_in(0, Location::RequiresRegister()); | 1026 locs->set_in(0, Location::RequiresRegister()); |
| 1004 locs->set_out(Location::SameAsFirstInput()); | 1027 locs->set_out(Location::SameAsFirstInput()); |
| 1005 return locs; | 1028 return locs; |
| 1006 } | 1029 } |
| 1007 | 1030 |
| 1008 | 1031 |
| 1009 void InstantiateTypeArgumentsComp::EmitNativeCode( | 1032 void InstantiateTypeArgumentsComp::EmitNativeCode( |
| 1010 FlowGraphCompiler* compiler) { | 1033 FlowGraphCompiler* compiler) { |
| 1011 Register instantiator_reg = locs()->in(0).reg(); | 1034 Register instantiator_reg = locs()->in(0).reg(); |
| 1012 Register result_reg = locs()->out().reg(); | 1035 Register result_reg = locs()->out().reg(); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1171 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1194 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 1172 } | 1195 } |
| 1173 __ Bind(&done); | 1196 __ Bind(&done); |
| 1174 // instantiator_reg: instantiator or kNoInstantiator. | 1197 // instantiator_reg: instantiator or kNoInstantiator. |
| 1175 } | 1198 } |
| 1176 | 1199 |
| 1177 | 1200 |
| 1178 LocationSummary* AllocateContextComp::MakeLocationSummary() const { | 1201 LocationSummary* AllocateContextComp::MakeLocationSummary() const { |
| 1179 const intptr_t kNumInputs = 0; | 1202 const intptr_t kNumInputs = 0; |
| 1180 const intptr_t kNumTemps = 1; | 1203 const intptr_t kNumTemps = 1; |
| 1181 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1204 LocationSummary* locs = new LocationSummary(kNumInputs, |
| 1205 kNumTemps, | |
| 1206 LocationSummary::kCall); | |
| 1182 locs->set_temp(0, Location::RegisterLocation(R10)); | 1207 locs->set_temp(0, Location::RegisterLocation(R10)); |
| 1183 locs->set_out(Location::RegisterLocation(RAX)); | 1208 locs->set_out(Location::RegisterLocation(RAX)); |
| 1184 return locs; | 1209 return locs; |
| 1185 } | 1210 } |
| 1186 | 1211 |
| 1187 | 1212 |
| 1188 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1213 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1189 ASSERT(locs()->temp(0).reg() == R10); | 1214 ASSERT(locs()->temp(0).reg() == R10); |
| 1190 | 1215 |
| 1191 __ movq(R10, Immediate(num_context_variables())); | 1216 __ movq(R10, Immediate(num_context_variables())); |
| 1192 const ExternalLabel label("alloc_context", | 1217 const ExternalLabel label("alloc_context", |
| 1193 StubCode::AllocateContextEntryPoint()); | 1218 StubCode::AllocateContextEntryPoint()); |
| 1194 compiler->GenerateCall(token_index(), | 1219 compiler->GenerateCall(token_index(), |
| 1195 try_index(), | 1220 try_index(), |
| 1196 &label, | 1221 &label, |
| 1197 PcDescriptors::kOther); | 1222 PcDescriptors::kOther); |
| 1198 } | 1223 } |
| 1199 | 1224 |
| 1200 | 1225 |
| 1201 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1226 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
| 1202 return LocationSummary::Make(1, Location::RequiresRegister()); | 1227 return LocationSummary::Make(1, |
| 1228 Location::RequiresRegister(), | |
| 1229 LocationSummary::kCall); | |
| 1203 } | 1230 } |
| 1204 | 1231 |
| 1205 | 1232 |
| 1206 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1233 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1207 Register context_value = locs()->in(0).reg(); | 1234 Register context_value = locs()->in(0).reg(); |
| 1208 Register result = locs()->out().reg(); | 1235 Register result = locs()->out().reg(); |
| 1209 | 1236 |
| 1210 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1237 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1211 __ pushq(context_value); | 1238 __ pushq(context_value); |
| 1212 compiler->GenerateCallRuntime(cid(), | 1239 compiler->GenerateCallRuntime(cid(), |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1239 __ movq(Address(RBP, exception_var().index() * kWordSize), | 1266 __ movq(Address(RBP, exception_var().index() * kWordSize), |
| 1240 kExceptionObjectReg); | 1267 kExceptionObjectReg); |
| 1241 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), | 1268 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), |
| 1242 kStackTraceObjectReg); | 1269 kStackTraceObjectReg); |
| 1243 } | 1270 } |
| 1244 | 1271 |
| 1245 | 1272 |
| 1246 LocationSummary* CheckStackOverflowComp::MakeLocationSummary() const { | 1273 LocationSummary* CheckStackOverflowComp::MakeLocationSummary() const { |
| 1247 const intptr_t kNumInputs = 0; | 1274 const intptr_t kNumInputs = 0; |
| 1248 const intptr_t kNumTemps = 1; | 1275 const intptr_t kNumTemps = 1; |
| 1249 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 1276 // TODO(vegorov): spilling is required only on infrequently executed path. |
|
srdjan
2012/06/18 16:33:20
A quick fix could be to use the deoptimization stu
Vyacheslav Egorov (Google)
2012/06/18 17:51:16
Yes, I agree.
In V8 we have a generic "deferred
| |
| 1277 LocationSummary* summary = new LocationSummary(kNumInputs, | |
| 1278 kNumTemps, | |
| 1279 LocationSummary::kCall); | |
| 1250 summary->set_temp(0, Location::RequiresRegister()); | 1280 summary->set_temp(0, Location::RequiresRegister()); |
| 1251 return summary; | 1281 return summary; |
| 1252 } | 1282 } |
| 1253 | 1283 |
| 1254 | 1284 |
| 1255 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1285 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1256 Register temp = locs()->temp(0).reg(); | 1286 Register temp = locs()->temp(0).reg(); |
| 1257 // Generate stack overflow check. | 1287 // Generate stack overflow check. |
| 1258 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 1288 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); |
| 1259 __ cmpq(RSP, Address(temp, 0)); | 1289 __ cmpq(RSP, Address(temp, 0)); |
| 1260 Label no_stack_overflow; | 1290 Label no_stack_overflow; |
| 1261 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 1291 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
| 1262 compiler->GenerateCallRuntime(cid(), | 1292 compiler->GenerateCallRuntime(cid(), |
| 1263 token_index(), | 1293 token_index(), |
| 1264 try_index(), | 1294 try_index(), |
| 1265 kStackOverflowRuntimeEntry); | 1295 kStackOverflowRuntimeEntry); |
| 1266 __ Bind(&no_stack_overflow); | 1296 __ Bind(&no_stack_overflow); |
| 1267 } | 1297 } |
| 1268 | 1298 |
| 1269 | 1299 |
| 1270 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1300 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
| 1271 const intptr_t kNumInputs = 2; | 1301 const intptr_t kNumInputs = 2; |
| 1272 | 1302 |
| 1273 if (operands_type() == kDoubleOperands) { | 1303 if (operands_type() == kDoubleOperands) { |
| 1274 const intptr_t kNumTemps = 1; | 1304 return MakeCallSummary(); // Calls into a stub for allocation. |
| 1275 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | |
| 1276 summary->set_in(0, Location::RequiresRegister()); | |
| 1277 summary->set_in(1, Location::RequiresRegister()); | |
| 1278 summary->set_out(Location::RegisterLocation(RAX)); | |
| 1279 summary->set_temp(0, Location::RequiresRegister()); | |
| 1280 return summary; | |
| 1281 } | 1305 } |
| 1282 | 1306 |
| 1283 ASSERT(operands_type() == kSmiOperands); | 1307 ASSERT(operands_type() == kSmiOperands); |
| 1284 | 1308 |
| 1285 if (op_kind() == Token::kTRUNCDIV) { | 1309 if (op_kind() == Token::kTRUNCDIV) { |
| 1286 const intptr_t kNumTemps = 3; | 1310 const intptr_t kNumTemps = 3; |
| 1287 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 1311 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
| 1288 summary->set_in(0, Location::RegisterLocation(RAX)); | 1312 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 1289 summary->set_in(1, Location::RegisterLocation(RCX)); | 1313 summary->set_in(1, Location::RegisterLocation(RCX)); |
| 1290 summary->set_out(Location::SameAsFirstInput()); | 1314 summary->set_out(Location::SameAsFirstInput()); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1449 } | 1473 } |
| 1450 default: | 1474 default: |
| 1451 UNREACHABLE(); | 1475 UNREACHABLE(); |
| 1452 break; | 1476 break; |
| 1453 } | 1477 } |
| 1454 } | 1478 } |
| 1455 | 1479 |
| 1456 | 1480 |
| 1457 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1481 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, |
| 1458 BinaryOpComp* comp) { | 1482 BinaryOpComp* comp) { |
| 1459 Register left = comp->locs()->in(0).reg(); | 1483 Register left = RBX; |
| 1460 Register right = comp->locs()->in(1).reg(); | 1484 Register right = RCX; |
| 1461 Register temp = comp->locs()->temp(0).reg(); | 1485 Register temp = RDX; |
| 1462 Register result = comp->locs()->out().reg(); | 1486 Register result = comp->locs()->out().reg(); |
| 1463 | 1487 |
| 1464 const Class& double_class = compiler->double_class(); | 1488 const Class& double_class = compiler->double_class(); |
| 1465 const Code& stub = | 1489 const Code& stub = |
| 1466 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1490 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1467 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1491 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1468 __ pushq(left); | |
| 1469 __ pushq(right); | |
| 1470 compiler->GenerateCall(comp->instance_call()->token_index(), | 1492 compiler->GenerateCall(comp->instance_call()->token_index(), |
| 1471 comp->instance_call()->try_index(), | 1493 comp->instance_call()->try_index(), |
| 1472 &label, | 1494 &label, |
| 1473 PcDescriptors::kOther); | 1495 PcDescriptors::kOther); |
| 1474 // Newly allocated object is now in the result register (RAX). | 1496 // Newly allocated object is now in the result register (RAX). |
| 1475 ASSERT(result == RAX); | 1497 ASSERT(result == RAX); |
| 1476 __ popq(right); | 1498 __ popq(right); |
| 1477 __ popq(left); | 1499 __ popq(left); |
| 1478 | 1500 |
| 1479 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1501 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1559 } | 1581 } |
| 1560 } else { | 1582 } else { |
| 1561 UNREACHABLE(); | 1583 UNREACHABLE(); |
| 1562 } | 1584 } |
| 1563 } | 1585 } |
| 1564 | 1586 |
| 1565 | 1587 |
| 1566 LocationSummary* NumberNegateComp::MakeLocationSummary() const { | 1588 LocationSummary* NumberNegateComp::MakeLocationSummary() const { |
| 1567 const intptr_t kNumInputs = 1; | 1589 const intptr_t kNumInputs = 1; |
| 1568 const intptr_t kNumTemps = 1; // Needed for doubles. | 1590 const intptr_t kNumTemps = 1; // Needed for doubles. |
| 1569 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 1591 LocationSummary* summary = new LocationSummary(kNumInputs, |
| 1592 kNumTemps, | |
| 1593 LocationSummary::kCall); | |
| 1570 summary->set_in(0, Location::RequiresRegister()); | 1594 summary->set_in(0, Location::RequiresRegister()); |
| 1571 summary->set_out(Location::SameAsFirstInput()); | 1595 summary->set_out(Location::SameAsFirstInput()); |
| 1572 summary->set_temp(0, Location::RequiresRegister()); | 1596 summary->set_temp(0, Location::RequiresRegister()); |
| 1573 return summary; | 1597 return summary; |
| 1574 } | 1598 } |
| 1575 | 1599 |
| 1576 | 1600 |
| 1577 void NumberNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1601 void NumberNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1578 const ICData& ic_data = *instance_call()->ic_data(); | 1602 const ICData& ic_data = *instance_call()->ic_data(); |
| 1579 ASSERT(!ic_data.IsNull()); | 1603 ASSERT(!ic_data.IsNull()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1625 LocationSummary* ToDoubleComp::MakeLocationSummary() const { | 1649 LocationSummary* ToDoubleComp::MakeLocationSummary() const { |
| 1626 const intptr_t kNumInputs = 1; | 1650 const intptr_t kNumInputs = 1; |
| 1627 if (from() == kDouble) { | 1651 if (from() == kDouble) { |
| 1628 const intptr_t kNumTemps = 0; | 1652 const intptr_t kNumTemps = 0; |
| 1629 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1653 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 1630 locs->set_in(0, Location::RequiresRegister()); | 1654 locs->set_in(0, Location::RequiresRegister()); |
| 1631 locs->set_out(Location::SameAsFirstInput()); | 1655 locs->set_out(Location::SameAsFirstInput()); |
| 1632 return locs; | 1656 return locs; |
| 1633 } else { | 1657 } else { |
| 1634 ASSERT(from() == kSmi); | 1658 ASSERT(from() == kSmi); |
| 1635 return LocationSummary::Make(kNumInputs, Location::RegisterLocation(RAX)); | 1659 return MakeCallSummary(); |
| 1636 } | 1660 } |
| 1637 } | 1661 } |
| 1638 | 1662 |
| 1639 | 1663 |
| 1640 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1664 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1641 Register value = locs()->in(0).reg(); | 1665 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; |
| 1642 Register result = locs()->out().reg(); | 1666 Register result = locs()->out().reg(); |
| 1643 | 1667 |
| 1644 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1668 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
| 1645 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1669 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
| 1646 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1670 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1647 instance_call()->token_index(), | 1671 instance_call()->token_index(), |
| 1648 instance_call()->try_index(), | 1672 instance_call()->try_index(), |
| 1649 deopt_reason, | 1673 deopt_reason, |
| 1650 value); | 1674 value); |
| 1651 | 1675 |
| 1652 if (from() == kDouble) { | 1676 if (from() == kDouble) { |
| 1653 __ testq(value, Immediate(kSmiTagMask)); | 1677 __ testq(value, Immediate(kSmiTagMask)); |
| 1654 __ j(ZERO, deopt); // Deoptimize if Smi. | 1678 __ j(ZERO, deopt); // Deoptimize if Smi. |
| 1655 __ CompareClassId(value, kDouble); | 1679 __ CompareClassId(value, kDouble); |
| 1656 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1680 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
| 1657 ASSERT(value == result); | 1681 ASSERT(value == result); |
| 1658 return; | 1682 return; |
| 1659 } | 1683 } |
| 1660 | 1684 |
| 1661 ASSERT(from() == kSmi); | 1685 ASSERT(from() == kSmi); |
| 1662 | 1686 |
| 1663 const Class& double_class = compiler->double_class(); | 1687 const Class& double_class = compiler->double_class(); |
| 1664 const Code& stub = | 1688 const Code& stub = |
| 1665 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1689 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1666 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1690 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1667 | 1691 |
| 1668 // TODO(vegorov): allocate box in the driver loop to avoid pushing and poping. | 1692 // TODO(vegorov): allocate box in the driver loop to avoid pushing and poping. |
| 1669 __ pushq(value); | |
| 1670 compiler->GenerateCall(instance_call()->token_index(), | 1693 compiler->GenerateCall(instance_call()->token_index(), |
| 1671 instance_call()->try_index(), | 1694 instance_call()->try_index(), |
| 1672 &label, | 1695 &label, |
| 1673 PcDescriptors::kOther); | 1696 PcDescriptors::kOther); |
| 1674 ASSERT(result == RAX); | 1697 ASSERT(result == RAX); |
| 1675 __ popq(value); | 1698 __ popq(value); |
| 1676 | 1699 |
| 1677 __ testq(value, Immediate(kSmiTagMask)); | 1700 __ testq(value, Immediate(kSmiTagMask)); |
| 1678 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 1701 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
| 1679 __ SmiUntag(value); | 1702 __ SmiUntag(value); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1728 instance_call()->argument_names()); | 1751 instance_call()->argument_names()); |
| 1729 } | 1752 } |
| 1730 __ Bind(&done); | 1753 __ Bind(&done); |
| 1731 } | 1754 } |
| 1732 | 1755 |
| 1733 } // namespace dart | 1756 } // namespace dart |
| 1734 | 1757 |
| 1735 #undef __ | 1758 #undef __ |
| 1736 | 1759 |
| 1737 #endif // defined TARGET_ARCH_X64 | 1760 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |