| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 locs->set_out(Location::RequiresRegister()); | 916 locs->set_out(Location::RequiresRegister()); |
| 917 return locs; | 917 return locs; |
| 918 } | 918 } |
| 919 if (operation_cid() == kDoubleCid) { | 919 if (operation_cid() == kDoubleCid) { |
| 920 LocationSummary* summary = | 920 LocationSummary* summary = |
| 921 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 921 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 922 summary->set_in(0, Location::RequiresFpuRegister()); | 922 summary->set_in(0, Location::RequiresFpuRegister()); |
| 923 summary->set_in(1, Location::RequiresFpuRegister()); | 923 summary->set_in(1, Location::RequiresFpuRegister()); |
| 924 summary->set_out(Location::RequiresRegister()); | 924 summary->set_out(Location::RequiresRegister()); |
| 925 return summary; | 925 return summary; |
| 926 } else if (operation_cid() == kSmiCid) { | |
| 927 LocationSummary* summary = | |
| 928 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 929 summary->set_in(0, Location::RegisterOrConstant(left())); | |
| 930 // Only one input can be a constant operand. The case of two constant | |
| 931 // operands should be handled by constant propagation. | |
| 932 summary->set_in(1, summary->in(0).IsConstant() | |
| 933 ? Location::RequiresRegister() | |
| 934 : Location::RegisterOrConstant(right())); | |
| 935 summary->set_out(Location::RequiresRegister()); | |
| 936 return summary; | |
| 937 } | 926 } |
| 938 LocationSummary* locs = | 927 ASSERT(operation_cid() == kSmiCid); |
| 939 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 928 LocationSummary* summary = |
| 940 // Pick arbitrary fixed input registers because this is a call. | 929 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 941 locs->set_in(0, Location::RegisterLocation(EAX)); | 930 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 942 locs->set_in(1, Location::RegisterLocation(ECX)); | 931 // Only one input can be a constant operand. The case of two constant |
| 943 locs->set_out(Location::RegisterLocation(EAX)); | 932 // operands should be handled by constant propagation. |
| 944 return locs; | 933 summary->set_in(1, summary->in(0).IsConstant() |
| 934 ? Location::RequiresRegister() |
| 935 : Location::RegisterOrConstant(right())); |
| 936 summary->set_out(Location::RequiresRegister()); |
| 937 return summary; |
| 945 } | 938 } |
| 946 | 939 |
| 947 | 940 |
| 948 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 941 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 949 if (operation_cid() == kSmiCid) { | 942 if (operation_cid() == kSmiCid) { |
| 950 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); | 943 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); |
| 951 return; | 944 return; |
| 952 } | 945 } |
| 953 if (operation_cid() == kMintCid) { | 946 if (operation_cid() == kMintCid) { |
| 954 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); | 947 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); |
| 955 return; | 948 return; |
| 956 } | 949 } |
| 957 if (operation_cid() == kDoubleCid) { | 950 ASSERT(operation_cid() == kDoubleCid); |
| 958 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); | 951 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); |
| 959 return; | |
| 960 } | |
| 961 | |
| 962 // Push arguments for the call. | |
| 963 // TODO(fschneider): Split this instruction into different types to avoid | |
| 964 // explicitly pushing arguments to the call here. | |
| 965 Register left = locs()->in(0).reg(); | |
| 966 Register right = locs()->in(1).reg(); | |
| 967 __ pushl(left); | |
| 968 __ pushl(right); | |
| 969 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | |
| 970 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptRelationalOp); | |
| 971 // Load class into EDI. Since this is a call, any register except | |
| 972 // the fixed input registers would be ok. | |
| 973 ASSERT((left != EDI) && (right != EDI)); | |
| 974 const intptr_t kNumArguments = 2; | |
| 975 LoadValueCid(compiler, EDI, left); | |
| 976 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | |
| 977 EDI, // Class id register. | |
| 978 kNumArguments, | |
| 979 Object::null_array(), // No named arguments. | |
| 980 deopt, // Deoptimize target. | |
| 981 deopt_id(), | |
| 982 token_pos(), | |
| 983 locs()); | |
| 984 return; | |
| 985 } | |
| 986 const String& function_name = | |
| 987 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | |
| 988 if (!compiler->is_optimizing()) { | |
| 989 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | |
| 990 deopt_id(), | |
| 991 token_pos()); | |
| 992 } | |
| 993 const intptr_t kNumArguments = 2; | |
| 994 const intptr_t kNumArgsChecked = 2; // Type-feedback. | |
| 995 ICData& relational_ic_data = ICData::ZoneHandle(ic_data()->raw()); | |
| 996 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { | |
| 997 ASSERT(!ic_data()->IsNull()); | |
| 998 if (ic_data()->NumberOfChecks() == 0) { | |
| 999 // IC call for reoptimization populates original ICData. | |
| 1000 relational_ic_data = ic_data()->raw(); | |
| 1001 } else { | |
| 1002 // Megamorphic call. | |
| 1003 relational_ic_data = ic_data()->AsUnaryClassChecks(); | |
| 1004 } | |
| 1005 } else { | |
| 1006 const Array& arguments_descriptor = | |
| 1007 Array::Handle(ArgumentsDescriptor::New(kNumArguments, | |
| 1008 Object::null_array())); | |
| 1009 relational_ic_data = ICData::New(compiler->parsed_function().function(), | |
| 1010 function_name, | |
| 1011 arguments_descriptor, | |
| 1012 deopt_id(), | |
| 1013 kNumArgsChecked); | |
| 1014 } | |
| 1015 compiler->GenerateInstanceCall(deopt_id(), | |
| 1016 token_pos(), | |
| 1017 kNumArguments, | |
| 1018 Object::null_array(), // No optional args. | |
| 1019 locs(), | |
| 1020 relational_ic_data); | |
| 1021 } | 952 } |
| 1022 | 953 |
| 1023 | 954 |
| 1024 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 955 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 1025 BranchInstr* branch) { | 956 BranchInstr* branch) { |
| 1026 if (operation_cid() == kSmiCid) { | 957 if (operation_cid() == kSmiCid) { |
| 1027 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 958 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 1028 return; | 959 return; |
| 1029 } | 960 } |
| 1030 if (operation_cid() == kMintCid) { | 961 if (operation_cid() == kMintCid) { |
| 1031 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); | 962 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); |
| 1032 return; | 963 return; |
| 1033 } | 964 } |
| 1034 if (operation_cid() == kDoubleCid) { | 965 ASSERT(operation_cid() == kDoubleCid); |
| 1035 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 966 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 1036 return; | |
| 1037 } | |
| 1038 EmitNativeCode(compiler); | |
| 1039 __ CompareObject(EAX, Bool::True()); | |
| 1040 branch->EmitBranchOnCondition(compiler, EQUAL); | |
| 1041 } | 967 } |
| 1042 | 968 |
| 1043 | 969 |
| 1044 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 970 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
| 1045 const intptr_t kNumInputs = 0; | 971 const intptr_t kNumInputs = 0; |
| 1046 const intptr_t kNumTemps = 3; | 972 const intptr_t kNumTemps = 3; |
| 1047 LocationSummary* locs = | 973 LocationSummary* locs = |
| 1048 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 974 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1049 locs->set_temp(0, Location::RegisterLocation(EAX)); | 975 locs->set_temp(0, Location::RegisterLocation(EAX)); |
| 1050 locs->set_temp(1, Location::RegisterLocation(ECX)); | 976 locs->set_temp(1, Location::RegisterLocation(ECX)); |
| (...skipping 4214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5265 PcDescriptors::kOther, | 5191 PcDescriptors::kOther, |
| 5266 locs()); | 5192 locs()); |
| 5267 __ Drop(2); // Discard type arguments and receiver. | 5193 __ Drop(2); // Discard type arguments and receiver. |
| 5268 } | 5194 } |
| 5269 | 5195 |
| 5270 } // namespace dart | 5196 } // namespace dart |
| 5271 | 5197 |
| 5272 #undef __ | 5198 #undef __ |
| 5273 | 5199 |
| 5274 #endif // defined TARGET_ARCH_IA32 | 5200 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |