| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 return true; | 162 return true; |
| 163 } | 163 } |
| 164 | 164 |
| 165 | 165 |
| 166 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, | 166 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, |
| 167 Value* v1, | 167 Value* v1, |
| 168 Value* v2) { | 168 Value* v2) { |
| 169 if (!(comparison->IsStrictCompare() && | 169 if (!(comparison->IsStrictCompare() && |
| 170 !comparison->AsStrictCompare()->needs_number_check()) && | 170 !comparison->AsStrictCompare()->needs_number_check()) && |
| 171 !(comparison->IsEqualityCompare() && | 171 !(comparison->IsEqualityCompare() && |
| 172 (comparison->AsEqualityCompare()->receiver_class_id() == kSmiCid))) { | 172 (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) { |
| 173 return false; | 173 return false; |
| 174 } | 174 } |
| 175 | 175 |
| 176 intptr_t v1_value, v2_value; | 176 intptr_t v1_value, v2_value; |
| 177 | 177 |
| 178 if (!BindsToSmiConstant(v1, &v1_value) || | 178 if (!BindsToSmiConstant(v1, &v1_value) || |
| 179 !BindsToSmiConstant(v2, &v2_value)) { | 179 !BindsToSmiConstant(v2, &v2_value)) { |
| 180 return false; | 180 return false; |
| 181 } | 181 } |
| 182 | 182 |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 case Token::kGTE: return GREATER_EQUAL; | 389 case Token::kGTE: return GREATER_EQUAL; |
| 390 default: | 390 default: |
| 391 UNREACHABLE(); | 391 UNREACHABLE(); |
| 392 return OVERFLOW; | 392 return OVERFLOW; |
| 393 } | 393 } |
| 394 } | 394 } |
| 395 | 395 |
| 396 | 396 |
| 397 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { | 397 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { |
| 398 const intptr_t kNumInputs = 2; | 398 const intptr_t kNumInputs = 2; |
| 399 if (receiver_class_id() == kDoubleCid) { | 399 if (operation_cid() == kDoubleCid) { |
| 400 const intptr_t kNumTemps = 0; | 400 const intptr_t kNumTemps = 0; |
| 401 LocationSummary* locs = | 401 LocationSummary* locs = |
| 402 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 402 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 403 locs->set_in(0, Location::RequiresFpuRegister()); | 403 locs->set_in(0, Location::RequiresFpuRegister()); |
| 404 locs->set_in(1, Location::RequiresFpuRegister()); | 404 locs->set_in(1, Location::RequiresFpuRegister()); |
| 405 locs->set_out(Location::RequiresRegister()); | 405 locs->set_out(Location::RequiresRegister()); |
| 406 return locs; | 406 return locs; |
| 407 } | 407 } |
| 408 if (receiver_class_id() == kSmiCid) { | 408 if (operation_cid() == kSmiCid) { |
| 409 const intptr_t kNumTemps = 0; | 409 const intptr_t kNumTemps = 0; |
| 410 LocationSummary* locs = | 410 LocationSummary* locs = |
| 411 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 411 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 412 locs->set_in(0, Location::RegisterOrConstant(left())); | 412 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 413 // Only one input can be a constant operand. The case of two constant | 413 // Only one input can be a constant operand. The case of two constant |
| 414 // operands should be handled by constant propagation. | 414 // operands should be handled by constant propagation. |
| 415 // Only right can be a stack slot. | 415 // Only right can be a stack slot. |
| 416 locs->set_in(1, locs->in(0).IsConstant() | 416 locs->set_in(1, locs->in(0).IsConstant() |
| 417 ? Location::RequiresRegister() | 417 ? Location::RequiresRegister() |
| 418 : Location::RegisterOrConstant(right())); | 418 : Location::RegisterOrConstant(right())); |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 } else { | 834 } else { |
| 835 compiler->EmitDoubleCompareBool( | 835 compiler->EmitDoubleCompareBool( |
| 836 true_condition, left, right, locs.out().reg()); | 836 true_condition, left, right, locs.out().reg()); |
| 837 } | 837 } |
| 838 } | 838 } |
| 839 | 839 |
| 840 | 840 |
| 841 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 841 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 842 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 842 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 843 BranchInstr* kNoBranch = NULL; | 843 BranchInstr* kNoBranch = NULL; |
| 844 if (receiver_class_id() == kSmiCid) { | 844 if (operation_cid() == kSmiCid) { |
| 845 // Deoptimizes if both arguments not Smi. | 845 // Deoptimizes if both arguments not Smi. |
| 846 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); | 846 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 847 return; | 847 return; |
| 848 } | 848 } |
| 849 if (receiver_class_id() == kDoubleCid) { | 849 if (operation_cid() == kDoubleCid) { |
| 850 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | 850 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. |
| 851 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); | 851 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 852 return; | 852 return; |
| 853 } | 853 } |
| 854 if (IsCheckedStrictEqual()) { | 854 if (IsCheckedStrictEqual()) { |
| 855 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, | 855 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, |
| 856 deopt_id()); | 856 deopt_id()); |
| 857 return; | 857 return; |
| 858 } | 858 } |
| 859 if (IsPolymorphic()) { | 859 if (IsPolymorphic()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 871 kind(), | 871 kind(), |
| 872 locs(), | 872 locs(), |
| 873 *ic_data()); | 873 *ic_data()); |
| 874 ASSERT(locs()->out().reg() == RAX); | 874 ASSERT(locs()->out().reg() == RAX); |
| 875 } | 875 } |
| 876 | 876 |
| 877 | 877 |
| 878 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 878 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 879 BranchInstr* branch) { | 879 BranchInstr* branch) { |
| 880 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 880 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 881 if (receiver_class_id() == kSmiCid) { | 881 if (operation_cid() == kSmiCid) { |
| 882 // Deoptimizes if both arguments not Smi. | 882 // Deoptimizes if both arguments not Smi. |
| 883 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 883 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 884 return; | 884 return; |
| 885 } | 885 } |
| 886 if (receiver_class_id() == kDoubleCid) { | 886 if (operation_cid() == kDoubleCid) { |
| 887 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | 887 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. |
| 888 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 888 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 889 return; | 889 return; |
| 890 } | 890 } |
| 891 if (IsCheckedStrictEqual()) { | 891 if (IsCheckedStrictEqual()) { |
| 892 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, | 892 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, |
| 893 deopt_id()); | 893 deopt_id()); |
| 894 return; | 894 return; |
| 895 } | 895 } |
| 896 if (IsPolymorphic()) { | 896 if (IsPolymorphic()) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 913 } | 913 } |
| 914 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 914 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
| 915 __ CompareObject(RAX, Bool::True()); | 915 __ CompareObject(RAX, Bool::True()); |
| 916 branch->EmitBranchOnCondition(compiler, branch_condition); | 916 branch->EmitBranchOnCondition(compiler, branch_condition); |
| 917 } | 917 } |
| 918 | 918 |
| 919 | 919 |
| 920 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 920 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 921 const intptr_t kNumInputs = 2; | 921 const intptr_t kNumInputs = 2; |
| 922 const intptr_t kNumTemps = 0; | 922 const intptr_t kNumTemps = 0; |
| 923 if (operands_class_id() == kDoubleCid) { | 923 if (operation_cid() == kDoubleCid) { |
| 924 LocationSummary* summary = | 924 LocationSummary* summary = |
| 925 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 925 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 926 summary->set_in(0, Location::RequiresFpuRegister()); | 926 summary->set_in(0, Location::RequiresFpuRegister()); |
| 927 summary->set_in(1, Location::RequiresFpuRegister()); | 927 summary->set_in(1, Location::RequiresFpuRegister()); |
| 928 summary->set_out(Location::RequiresRegister()); | 928 summary->set_out(Location::RequiresRegister()); |
| 929 return summary; | 929 return summary; |
| 930 } else if (operands_class_id() == kSmiCid) { | 930 } else if (operation_cid() == kSmiCid) { |
| 931 LocationSummary* summary = | 931 LocationSummary* summary = |
| 932 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 932 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 933 summary->set_in(0, Location::RegisterOrConstant(left())); | 933 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 934 // Only one input can be a constant operand. The case of two constant | 934 // Only one input can be a constant operand. The case of two constant |
| 935 // operands should be handled by constant propagation. | 935 // operands should be handled by constant propagation. |
| 936 summary->set_in(1, summary->in(0).IsConstant() | 936 summary->set_in(1, summary->in(0).IsConstant() |
| 937 ? Location::RequiresRegister() | 937 ? Location::RequiresRegister() |
| 938 : Location::RegisterOrConstant(right())); | 938 : Location::RegisterOrConstant(right())); |
| 939 summary->set_out(Location::RequiresRegister()); | 939 summary->set_out(Location::RequiresRegister()); |
| 940 return summary; | 940 return summary; |
| 941 } | 941 } |
| 942 LocationSummary* locs = | 942 LocationSummary* locs = |
| 943 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 943 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 944 // Pick arbitrary fixed input registers because this is a call. | 944 // Pick arbitrary fixed input registers because this is a call. |
| 945 locs->set_in(0, Location::RegisterLocation(RAX)); | 945 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 946 locs->set_in(1, Location::RegisterLocation(RCX)); | 946 locs->set_in(1, Location::RegisterLocation(RCX)); |
| 947 locs->set_out(Location::RegisterLocation(RAX)); | 947 locs->set_out(Location::RegisterLocation(RAX)); |
| 948 return locs; | 948 return locs; |
| 949 } | 949 } |
| 950 | 950 |
| 951 | 951 |
| 952 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 952 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 953 if (operands_class_id() == kSmiCid) { | 953 if (operation_cid() == kSmiCid) { |
| 954 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); | 954 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); |
| 955 return; | 955 return; |
| 956 } | 956 } |
| 957 if (operands_class_id() == kDoubleCid) { | 957 if (operation_cid() == kDoubleCid) { |
| 958 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); | 958 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); |
| 959 return; | 959 return; |
| 960 } | 960 } |
| 961 | 961 |
| 962 // Push arguments for the call. | 962 // Push arguments for the call. |
| 963 // TODO(fschneider): Split this instruction into different types to avoid | 963 // TODO(fschneider): Split this instruction into different types to avoid |
| 964 // explicitly pushing arguments to the call here. | 964 // explicitly pushing arguments to the call here. |
| 965 Register left = locs()->in(0).reg(); | 965 Register left = locs()->in(0).reg(); |
| 966 Register right = locs()->in(1).reg(); | 966 Register right = locs()->in(1).reg(); |
| 967 __ pushq(left); | 967 __ pushq(left); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1017 token_pos(), | 1017 token_pos(), |
| 1018 kNumArguments, | 1018 kNumArguments, |
| 1019 Object::null_array(), // No optional args. | 1019 Object::null_array(), // No optional args. |
| 1020 locs(), | 1020 locs(), |
| 1021 relational_ic_data); | 1021 relational_ic_data); |
| 1022 } | 1022 } |
| 1023 | 1023 |
| 1024 | 1024 |
| 1025 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 1025 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 1026 BranchInstr* branch) { | 1026 BranchInstr* branch) { |
| 1027 if (operands_class_id() == kSmiCid) { | 1027 if (operation_cid() == kSmiCid) { |
| 1028 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 1028 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 1029 return; | 1029 return; |
| 1030 } | 1030 } |
| 1031 if (operands_class_id() == kDoubleCid) { | 1031 if (operation_cid() == kDoubleCid) { |
| 1032 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 1032 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 1033 return; | 1033 return; |
| 1034 } | 1034 } |
| 1035 EmitNativeCode(compiler); | 1035 EmitNativeCode(compiler); |
| 1036 __ CompareObject(RAX, Bool::True()); | 1036 __ CompareObject(RAX, Bool::True()); |
| 1037 branch->EmitBranchOnCondition(compiler, EQUAL); | 1037 branch->EmitBranchOnCondition(compiler, EQUAL); |
| 1038 } | 1038 } |
| 1039 | 1039 |
| 1040 | 1040 |
| 1041 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 1041 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
| (...skipping 3470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4512 PcDescriptors::kOther, | 4512 PcDescriptors::kOther, |
| 4513 locs()); | 4513 locs()); |
| 4514 __ Drop(2); // Discard type arguments and receiver. | 4514 __ Drop(2); // Discard type arguments and receiver. |
| 4515 } | 4515 } |
| 4516 | 4516 |
| 4517 } // namespace dart | 4517 } // namespace dart |
| 4518 | 4518 |
| 4519 #undef __ | 4519 #undef __ |
| 4520 | 4520 |
| 4521 #endif // defined TARGET_ARCH_X64 | 4521 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |