OLD | NEW |
1 // Copyright (c) 2012, 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" |
| 11 #include "vm/dart_entry.h" |
11 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
12 #include "vm/locations.h" | 13 #include "vm/locations.h" |
13 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
14 #include "vm/parser.h" | 15 #include "vm/parser.h" |
15 #include "vm/stub_code.h" | 16 #include "vm/stub_code.h" |
16 #include "vm/symbols.h" | 17 #include "vm/symbols.h" |
17 | 18 |
18 #define __ compiler->assembler()-> | 19 #define __ compiler->assembler()-> |
19 | 20 |
20 namespace dart { | 21 namespace dart { |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 | 268 |
268 | 269 |
269 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { | 270 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { |
270 const intptr_t kNumInputs = 2; | 271 const intptr_t kNumInputs = 2; |
271 const bool is_checked_strict_equal = | 272 const bool is_checked_strict_equal = |
272 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 273 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
273 if (receiver_class_id() == kDoubleCid) { | 274 if (receiver_class_id() == kDoubleCid) { |
274 const intptr_t kNumTemps = 0; | 275 const intptr_t kNumTemps = 0; |
275 LocationSummary* locs = | 276 LocationSummary* locs = |
276 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 277 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
277 locs->set_in(0, Location::RequiresXmmRegister()); | 278 locs->set_in(0, Location::RequiresFpuRegister()); |
278 locs->set_in(1, Location::RequiresXmmRegister()); | 279 locs->set_in(1, Location::RequiresFpuRegister()); |
279 locs->set_out(Location::RequiresRegister()); | 280 locs->set_out(Location::RequiresRegister()); |
280 return locs; | 281 return locs; |
281 } | 282 } |
282 if (receiver_class_id() == kSmiCid) { | 283 if (receiver_class_id() == kSmiCid) { |
283 const intptr_t kNumTemps = 0; | 284 const intptr_t kNumTemps = 0; |
284 LocationSummary* locs = | 285 LocationSummary* locs = |
285 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 286 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
286 locs->set_in(0, Location::RegisterOrConstant(left())); | 287 locs->set_in(0, Location::RegisterOrConstant(left())); |
287 // Only one input can be a constant operand. The case of two constant | 288 // Only one input can be a constant operand. The case of two constant |
288 // operands should be handled by constant propagation. | 289 // operands should be handled by constant propagation. |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 UNREACHABLE(); | 655 UNREACHABLE(); |
655 return OVERFLOW; | 656 return OVERFLOW; |
656 } | 657 } |
657 } | 658 } |
658 | 659 |
659 | 660 |
660 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 661 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
661 const LocationSummary& locs, | 662 const LocationSummary& locs, |
662 Token::Kind kind, | 663 Token::Kind kind, |
663 BranchInstr* branch) { | 664 BranchInstr* branch) { |
664 XmmRegister left = locs.in(0).xmm_reg(); | 665 XmmRegister left = locs.in(0).fpu_reg(); |
665 XmmRegister right = locs.in(1).xmm_reg(); | 666 XmmRegister right = locs.in(1).fpu_reg(); |
666 | 667 |
667 Condition true_condition = TokenKindToDoubleCondition(kind); | 668 Condition true_condition = TokenKindToDoubleCondition(kind); |
668 if (branch != NULL) { | 669 if (branch != NULL) { |
669 compiler->EmitDoubleCompareBranch( | 670 compiler->EmitDoubleCompareBranch( |
670 true_condition, left, right, branch); | 671 true_condition, left, right, branch); |
671 } else { | 672 } else { |
672 compiler->EmitDoubleCompareBool( | 673 compiler->EmitDoubleCompareBool( |
673 true_condition, left, right, locs.out().reg()); | 674 true_condition, left, right, locs.out().reg()); |
674 } | 675 } |
675 } | 676 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 branch->EmitBranchOnCondition(compiler, branch_condition); | 758 branch->EmitBranchOnCondition(compiler, branch_condition); |
758 } | 759 } |
759 | 760 |
760 | 761 |
761 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 762 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
762 const intptr_t kNumInputs = 2; | 763 const intptr_t kNumInputs = 2; |
763 const intptr_t kNumTemps = 0; | 764 const intptr_t kNumTemps = 0; |
764 if (operands_class_id() == kDoubleCid) { | 765 if (operands_class_id() == kDoubleCid) { |
765 LocationSummary* summary = | 766 LocationSummary* summary = |
766 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 767 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
767 summary->set_in(0, Location::RequiresXmmRegister()); | 768 summary->set_in(0, Location::RequiresFpuRegister()); |
768 summary->set_in(1, Location::RequiresXmmRegister()); | 769 summary->set_in(1, Location::RequiresFpuRegister()); |
769 summary->set_out(Location::RequiresRegister()); | 770 summary->set_out(Location::RequiresRegister()); |
770 return summary; | 771 return summary; |
771 } else if (operands_class_id() == kSmiCid) { | 772 } else if (operands_class_id() == kSmiCid) { |
772 LocationSummary* summary = | 773 LocationSummary* summary = |
773 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 774 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
774 summary->set_in(0, Location::RegisterOrConstant(left())); | 775 summary->set_in(0, Location::RegisterOrConstant(left())); |
775 // Only one input can be a constant operand. The case of two constant | 776 // Only one input can be a constant operand. The case of two constant |
776 // operands should be handled by constant propagation. | 777 // operands should be handled by constant propagation. |
777 summary->set_in(1, summary->in(0).IsConstant() | 778 summary->set_in(1, summary->in(0).IsConstant() |
778 ? Location::RequiresRegister() | 779 ? Location::RequiresRegister() |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { | 1003 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { |
1003 const intptr_t kNumInputs = 2; | 1004 const intptr_t kNumInputs = 2; |
1004 const intptr_t kNumTemps = 0; | 1005 const intptr_t kNumTemps = 0; |
1005 LocationSummary* locs = | 1006 LocationSummary* locs = |
1006 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1007 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1007 locs->set_in(0, Location::RequiresRegister()); | 1008 locs->set_in(0, Location::RequiresRegister()); |
1008 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1009 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
1009 ? Location::RegisterOrSmiConstant(index()) | 1010 ? Location::RegisterOrSmiConstant(index()) |
1010 : Location::RequiresRegister()); | 1011 : Location::RequiresRegister()); |
1011 if (representation() == kUnboxedDouble) { | 1012 if (representation() == kUnboxedDouble) { |
1012 locs->set_out(Location::RequiresXmmRegister()); | 1013 locs->set_out(Location::RequiresFpuRegister()); |
1013 } else { | 1014 } else { |
1014 locs->set_out(Location::RequiresRegister()); | 1015 locs->set_out(Location::RequiresRegister()); |
1015 } | 1016 } |
1016 return locs; | 1017 return locs; |
1017 } | 1018 } |
1018 | 1019 |
1019 | 1020 |
1020 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1021 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1021 Register array = locs()->in(0).reg(); | 1022 Register array = locs()->in(0).reg(); |
1022 Location index = locs()->in(1); | 1023 Location index = locs()->in(1); |
(...skipping 18 matching lines...) Expand all Loading... |
1041 return; | 1042 return; |
1042 } | 1043 } |
1043 | 1044 |
1044 FieldAddress element_address = index.IsRegister() ? | 1045 FieldAddress element_address = index.IsRegister() ? |
1045 FlowGraphCompiler::ElementAddressForRegIndex( | 1046 FlowGraphCompiler::ElementAddressForRegIndex( |
1046 class_id(), array, index.reg()) : | 1047 class_id(), array, index.reg()) : |
1047 FlowGraphCompiler::ElementAddressForIntIndex( | 1048 FlowGraphCompiler::ElementAddressForIntIndex( |
1048 class_id(), array, Smi::Cast(index.constant()).Value()); | 1049 class_id(), array, Smi::Cast(index.constant()).Value()); |
1049 | 1050 |
1050 if (representation() == kUnboxedDouble) { | 1051 if (representation() == kUnboxedDouble) { |
1051 XmmRegister result = locs()->out().xmm_reg(); | 1052 XmmRegister result = locs()->out().fpu_reg(); |
1052 if (class_id() == kFloat32ArrayCid) { | 1053 if (class_id() == kFloat32ArrayCid) { |
1053 // Load single precision float. | 1054 // Load single precision float. |
1054 __ movss(result, element_address); | 1055 __ movss(result, element_address); |
1055 // Promote to double. | 1056 // Promote to double. |
1056 __ cvtss2sd(result, locs()->out().xmm_reg()); | 1057 __ cvtss2sd(result, locs()->out().fpu_reg()); |
1057 } else { | 1058 } else { |
1058 ASSERT(class_id() == kFloat64ArrayCid); | 1059 ASSERT(class_id() == kFloat64ArrayCid); |
1059 __ movsd(result, element_address); | 1060 __ movsd(result, element_address); |
1060 } | 1061 } |
1061 return; | 1062 return; |
1062 } | 1063 } |
1063 | 1064 |
1064 Register result = locs()->out().reg(); | 1065 Register result = locs()->out().reg(); |
1065 if ((class_id() == kUint8ArrayCid) || | 1066 if ((class_id() == kUint8ArrayCid) || |
1066 (class_id() == kUint8ClampedArrayCid)) { | 1067 (class_id() == kUint8ClampedArrayCid)) { |
(...skipping 28 matching lines...) Expand all Loading... |
1095 ? Location::WritableRegister() | 1096 ? Location::WritableRegister() |
1096 : Location::RegisterOrConstant(value())); | 1097 : Location::RegisterOrConstant(value())); |
1097 break; | 1098 break; |
1098 case kUint8ArrayCid: | 1099 case kUint8ArrayCid: |
1099 // TODO(fschneider): Add location constraint for byte registers (RAX, | 1100 // TODO(fschneider): Add location constraint for byte registers (RAX, |
1100 // RBX, RCX, RDX) instead of using a fixed register. | 1101 // RBX, RCX, RDX) instead of using a fixed register. |
1101 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); | 1102 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); |
1102 break; | 1103 break; |
1103 case kFloat32ArrayCid: | 1104 case kFloat32ArrayCid: |
1104 // Need temp register for float-to-double conversion. | 1105 // Need temp register for float-to-double conversion. |
1105 locs->AddTemp(Location::RequiresXmmRegister()); | 1106 locs->AddTemp(Location::RequiresFpuRegister()); |
1106 // Fall through. | 1107 // Fall through. |
1107 case kFloat64ArrayCid: | 1108 case kFloat64ArrayCid: |
1108 // TODO(srdjan): Support Float64 constants. | 1109 // TODO(srdjan): Support Float64 constants. |
1109 locs->set_in(2, Location::RequiresXmmRegister()); | 1110 locs->set_in(2, Location::RequiresFpuRegister()); |
1110 break; | 1111 break; |
1111 default: | 1112 default: |
1112 UNREACHABLE(); | 1113 UNREACHABLE(); |
1113 return NULL; | 1114 return NULL; |
1114 } | 1115 } |
1115 return locs; | 1116 return locs; |
1116 } | 1117 } |
1117 | 1118 |
1118 | 1119 |
1119 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1120 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1151 ASSERT(locs()->in(2).reg() == RAX); | 1152 ASSERT(locs()->in(2).reg() == RAX); |
1152 __ SmiUntag(RAX); | 1153 __ SmiUntag(RAX); |
1153 __ movb(element_address, RAX); | 1154 __ movb(element_address, RAX); |
1154 } | 1155 } |
1155 if (index.IsRegister()) { | 1156 if (index.IsRegister()) { |
1156 __ SmiTag(index.reg()); // Re-tag. | 1157 __ SmiTag(index.reg()); // Re-tag. |
1157 } | 1158 } |
1158 break; | 1159 break; |
1159 case kFloat32ArrayCid: | 1160 case kFloat32ArrayCid: |
1160 // Convert to single precision. | 1161 // Convert to single precision. |
1161 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg()); | 1162 __ cvtsd2ss(locs()->temp(0).fpu_reg(), locs()->in(2).fpu_reg()); |
1162 // Store. | 1163 // Store. |
1163 __ movss(element_address, locs()->temp(0).xmm_reg()); | 1164 __ movss(element_address, locs()->temp(0).fpu_reg()); |
1164 break; | 1165 break; |
1165 case kFloat64ArrayCid: | 1166 case kFloat64ArrayCid: |
1166 __ movsd(element_address, locs()->in(2).xmm_reg()); | 1167 __ movsd(element_address, locs()->in(2).fpu_reg()); |
1167 break; | 1168 break; |
1168 default: | 1169 default: |
1169 UNREACHABLE(); | 1170 UNREACHABLE(); |
1170 } | 1171 } |
1171 } | 1172 } |
1172 | 1173 |
1173 | 1174 |
1174 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { | 1175 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { |
1175 const intptr_t kNumInputs = 2; | 1176 const intptr_t kNumInputs = 2; |
1176 const intptr_t num_temps = 0; | 1177 const intptr_t num_temps = 0; |
(...skipping 785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1962 } | 1963 } |
1963 | 1964 |
1964 | 1965 |
1965 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const { | 1966 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const { |
1966 const intptr_t kNumInputs = 1; | 1967 const intptr_t kNumInputs = 1; |
1967 const intptr_t kNumTemps = 0; | 1968 const intptr_t kNumTemps = 0; |
1968 LocationSummary* summary = | 1969 LocationSummary* summary = |
1969 new LocationSummary(kNumInputs, | 1970 new LocationSummary(kNumInputs, |
1970 kNumTemps, | 1971 kNumTemps, |
1971 LocationSummary::kCallOnSlowPath); | 1972 LocationSummary::kCallOnSlowPath); |
1972 summary->set_in(0, Location::RequiresXmmRegister()); | 1973 summary->set_in(0, Location::RequiresFpuRegister()); |
1973 summary->set_out(Location::RequiresRegister()); | 1974 summary->set_out(Location::RequiresRegister()); |
1974 return summary; | 1975 return summary; |
1975 } | 1976 } |
1976 | 1977 |
1977 | 1978 |
1978 class BoxDoubleSlowPath : public SlowPathCode { | 1979 class BoxDoubleSlowPath : public SlowPathCode { |
1979 public: | 1980 public: |
1980 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction) | 1981 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction) |
1981 : instruction_(instruction) { } | 1982 : instruction_(instruction) { } |
1982 | 1983 |
(...skipping 22 matching lines...) Expand all Loading... |
2005 private: | 2006 private: |
2006 BoxDoubleInstr* instruction_; | 2007 BoxDoubleInstr* instruction_; |
2007 }; | 2008 }; |
2008 | 2009 |
2009 | 2010 |
2010 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2011 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2011 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 2012 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
2012 compiler->AddSlowPathCode(slow_path); | 2013 compiler->AddSlowPathCode(slow_path); |
2013 | 2014 |
2014 Register out_reg = locs()->out().reg(); | 2015 Register out_reg = locs()->out().reg(); |
2015 XmmRegister value = locs()->in(0).xmm_reg(); | 2016 XmmRegister value = locs()->in(0).fpu_reg(); |
2016 | 2017 |
2017 AssemblerMacros::TryAllocate(compiler->assembler(), | 2018 AssemblerMacros::TryAllocate(compiler->assembler(), |
2018 compiler->double_class(), | 2019 compiler->double_class(), |
2019 slow_path->entry_label(), | 2020 slow_path->entry_label(), |
2020 Assembler::kFarJump, | 2021 Assembler::kFarJump, |
2021 out_reg); | 2022 out_reg); |
2022 __ Bind(slow_path->exit_label()); | 2023 __ Bind(slow_path->exit_label()); |
2023 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); | 2024 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
2024 } | 2025 } |
2025 | 2026 |
2026 | 2027 |
2027 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { | 2028 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { |
2028 const intptr_t kNumInputs = 1; | 2029 const intptr_t kNumInputs = 1; |
2029 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | 2030 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; |
2030 LocationSummary* summary = | 2031 LocationSummary* summary = |
2031 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2032 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2032 summary->set_in(0, Location::RequiresRegister()); | 2033 summary->set_in(0, Location::RequiresRegister()); |
2033 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); | 2034 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); |
2034 summary->set_out(Location::RequiresXmmRegister()); | 2035 summary->set_out(Location::RequiresFpuRegister()); |
2035 return summary; | 2036 return summary; |
2036 } | 2037 } |
2037 | 2038 |
2038 | 2039 |
2039 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2040 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2040 const intptr_t value_cid = value()->ResultCid(); | 2041 const intptr_t value_cid = value()->ResultCid(); |
2041 const Register value = locs()->in(0).reg(); | 2042 const Register value = locs()->in(0).reg(); |
2042 const XmmRegister result = locs()->out().xmm_reg(); | 2043 const XmmRegister result = locs()->out().fpu_reg(); |
2043 | 2044 |
2044 if (value_cid == kDoubleCid) { | 2045 if (value_cid == kDoubleCid) { |
2045 __ movsd(result, FieldAddress(value, Double::value_offset())); | 2046 __ movsd(result, FieldAddress(value, Double::value_offset())); |
2046 } else if (value_cid == kSmiCid) { | 2047 } else if (value_cid == kSmiCid) { |
2047 __ SmiUntag(value); // Untag input before conversion. | 2048 __ SmiUntag(value); // Untag input before conversion. |
2048 __ cvtsi2sd(result, value); | 2049 __ cvtsi2sd(result, value); |
2049 __ SmiTag(value); // Restore input register. | 2050 __ SmiTag(value); // Restore input register. |
2050 } else { | 2051 } else { |
2051 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); | 2052 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
2052 compiler->LoadDoubleOrSmiToXmm(result, | 2053 compiler->LoadDoubleOrSmiToFpu(result, |
2053 value, | 2054 value, |
2054 locs()->temp(0).reg(), | 2055 locs()->temp(0).reg(), |
2055 deopt); | 2056 deopt); |
2056 } | 2057 } |
2057 } | 2058 } |
2058 | 2059 |
2059 | 2060 |
2060 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { | 2061 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { |
2061 const intptr_t kNumInputs = 2; | 2062 const intptr_t kNumInputs = 2; |
2062 const intptr_t kNumTemps = 0; | 2063 const intptr_t kNumTemps = 0; |
2063 LocationSummary* summary = | 2064 LocationSummary* summary = |
2064 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2065 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2065 summary->set_in(0, Location::RequiresXmmRegister()); | 2066 summary->set_in(0, Location::RequiresFpuRegister()); |
2066 summary->set_in(1, Location::RequiresXmmRegister()); | 2067 summary->set_in(1, Location::RequiresFpuRegister()); |
2067 summary->set_out(Location::SameAsFirstInput()); | 2068 summary->set_out(Location::SameAsFirstInput()); |
2068 return summary; | 2069 return summary; |
2069 } | 2070 } |
2070 | 2071 |
2071 | 2072 |
2072 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2073 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2073 XmmRegister left = locs()->in(0).xmm_reg(); | 2074 XmmRegister left = locs()->in(0).fpu_reg(); |
2074 XmmRegister right = locs()->in(1).xmm_reg(); | 2075 XmmRegister right = locs()->in(1).fpu_reg(); |
2075 | 2076 |
2076 ASSERT(locs()->out().xmm_reg() == left); | 2077 ASSERT(locs()->out().fpu_reg() == left); |
2077 | 2078 |
2078 switch (op_kind()) { | 2079 switch (op_kind()) { |
2079 case Token::kADD: __ addsd(left, right); break; | 2080 case Token::kADD: __ addsd(left, right); break; |
2080 case Token::kSUB: __ subsd(left, right); break; | 2081 case Token::kSUB: __ subsd(left, right); break; |
2081 case Token::kMUL: __ mulsd(left, right); break; | 2082 case Token::kMUL: __ mulsd(left, right); break; |
2082 case Token::kDIV: __ divsd(left, right); break; | 2083 case Token::kDIV: __ divsd(left, right); break; |
2083 default: UNREACHABLE(); | 2084 default: UNREACHABLE(); |
2084 } | 2085 } |
2085 } | 2086 } |
2086 | 2087 |
2087 | 2088 |
2088 LocationSummary* MathSqrtInstr::MakeLocationSummary() const { | 2089 LocationSummary* MathSqrtInstr::MakeLocationSummary() const { |
2089 const intptr_t kNumInputs = 1; | 2090 const intptr_t kNumInputs = 1; |
2090 const intptr_t kNumTemps = 0; | 2091 const intptr_t kNumTemps = 0; |
2091 LocationSummary* summary = | 2092 LocationSummary* summary = |
2092 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2093 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2093 summary->set_in(0, Location::RequiresXmmRegister()); | 2094 summary->set_in(0, Location::RequiresFpuRegister()); |
2094 summary->set_out(Location::RequiresXmmRegister()); | 2095 summary->set_out(Location::RequiresFpuRegister()); |
2095 return summary; | 2096 return summary; |
2096 } | 2097 } |
2097 | 2098 |
2098 | 2099 |
2099 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2100 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2100 __ sqrtsd(locs()->out().xmm_reg(), locs()->in(0).xmm_reg()); | 2101 __ sqrtsd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); |
2101 } | 2102 } |
2102 | 2103 |
2103 | 2104 |
2104 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { | 2105 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { |
2105 const intptr_t kNumInputs = 1; | 2106 const intptr_t kNumInputs = 1; |
2106 const intptr_t kNumTemps = 0; | 2107 const intptr_t kNumTemps = 0; |
2107 LocationSummary* summary = | 2108 LocationSummary* summary = |
2108 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2109 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2109 summary->set_in(0, Location::RequiresRegister()); | 2110 summary->set_in(0, Location::RequiresRegister()); |
2110 summary->set_out(Location::SameAsFirstInput()); | 2111 summary->set_out(Location::SameAsFirstInput()); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2215 locs()); | 2216 locs()); |
2216 __ Bind(&done); | 2217 __ Bind(&done); |
2217 } | 2218 } |
2218 | 2219 |
2219 | 2220 |
2220 LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const { | 2221 LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const { |
2221 const intptr_t kNumInputs = 1; | 2222 const intptr_t kNumInputs = 1; |
2222 const intptr_t kNumTemps = 1; | 2223 const intptr_t kNumTemps = 1; |
2223 LocationSummary* result = new LocationSummary( | 2224 LocationSummary* result = new LocationSummary( |
2224 kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2225 kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2225 result->set_in(0, Location::RequiresXmmRegister()); | 2226 result->set_in(0, Location::RequiresFpuRegister()); |
2226 result->set_out(Location:: Location::RequiresRegister()); | 2227 result->set_out(Location:: Location::RequiresRegister()); |
2227 result->set_temp(0, Location::RequiresRegister()); | 2228 result->set_temp(0, Location::RequiresRegister()); |
2228 return result; | 2229 return result; |
2229 } | 2230 } |
2230 | 2231 |
2231 | 2232 |
2232 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2233 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2233 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); | 2234 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); |
2234 Register result = locs()->out().reg(); | 2235 Register result = locs()->out().reg(); |
2235 XmmRegister value = locs()->in(0).xmm_reg(); | 2236 XmmRegister value = locs()->in(0).fpu_reg(); |
2236 Register temp = locs()->temp(0).reg(); | 2237 Register temp = locs()->temp(0).reg(); |
2237 | 2238 |
2238 __ cvttsd2siq(result, value); | 2239 __ cvttsd2siq(result, value); |
2239 // Overflow is signalled with minint. | 2240 // Overflow is signalled with minint. |
2240 Label do_call, done; | 2241 Label do_call, done; |
2241 // Check for overflow and that it fits into Smi. | 2242 // Check for overflow and that it fits into Smi. |
2242 __ movq(temp, result); | 2243 __ movq(temp, result); |
2243 __ shlq(temp, Immediate(1)); | 2244 __ shlq(temp, Immediate(1)); |
2244 __ j(OVERFLOW, deopt); | 2245 __ j(OVERFLOW, deopt); |
2245 __ SmiTag(result); | 2246 __ SmiTag(result); |
2246 } | 2247 } |
2247 | 2248 |
2248 | 2249 |
2249 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { | 2250 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { |
2250 const intptr_t kNumInputs = 1; | 2251 const intptr_t kNumInputs = 1; |
2251 const intptr_t kNumTemps = | 2252 const intptr_t kNumTemps = |
2252 (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0; | 2253 (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0; |
2253 LocationSummary* result = | 2254 LocationSummary* result = |
2254 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2255 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2255 result->set_in(0, Location::RequiresXmmRegister()); | 2256 result->set_in(0, Location::RequiresFpuRegister()); |
2256 result->set_out(Location::RequiresXmmRegister()); | 2257 result->set_out(Location::RequiresFpuRegister()); |
2257 if (recognized_kind() == MethodRecognizer::kDoubleRound) { | 2258 if (recognized_kind() == MethodRecognizer::kDoubleRound) { |
2258 result->set_temp(0, Location::RequiresXmmRegister()); | 2259 result->set_temp(0, Location::RequiresFpuRegister()); |
2259 } | 2260 } |
2260 return result; | 2261 return result; |
2261 } | 2262 } |
2262 | 2263 |
2263 | 2264 |
2264 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2265 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2265 XmmRegister value = locs()->in(0).xmm_reg(); | 2266 XmmRegister value = locs()->in(0).fpu_reg(); |
2266 XmmRegister result = locs()->out().xmm_reg(); | 2267 XmmRegister result = locs()->out().fpu_reg(); |
2267 if (recognized_kind() == MethodRecognizer::kDoubleTruncate) { | 2268 if (recognized_kind() == MethodRecognizer::kDoubleTruncate) { |
2268 __ roundsd(result, value, Assembler::kRoundToZero); | 2269 __ roundsd(result, value, Assembler::kRoundToZero); |
2269 } else { | 2270 } else { |
2270 XmmRegister temp = locs()->temp(0).xmm_reg(); | 2271 XmmRegister temp = locs()->temp(0).fpu_reg(); |
2271 __ DoubleRound(result, value, temp); | 2272 __ DoubleRound(result, value, temp); |
2272 } | 2273 } |
2273 } | 2274 } |
2274 | 2275 |
2275 | 2276 |
2276 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { | 2277 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { |
2277 return MakeCallSummary(); | 2278 return MakeCallSummary(); |
2278 } | 2279 } |
2279 | 2280 |
2280 | 2281 |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2499 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { | 2500 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { |
2500 UNIMPLEMENTED(); | 2501 UNIMPLEMENTED(); |
2501 return NULL; | 2502 return NULL; |
2502 } | 2503 } |
2503 | 2504 |
2504 | 2505 |
2505 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2506 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2506 UNIMPLEMENTED(); | 2507 UNIMPLEMENTED(); |
2507 } | 2508 } |
2508 | 2509 |
| 2510 |
| 2511 LocationSummary* ThrowInstr::MakeLocationSummary() const { |
| 2512 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 2513 } |
| 2514 |
| 2515 |
| 2516 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2517 compiler->GenerateCallRuntime(token_pos(), |
| 2518 kThrowRuntimeEntry, |
| 2519 locs()); |
| 2520 __ int3(); |
| 2521 } |
| 2522 |
| 2523 |
| 2524 LocationSummary* ReThrowInstr::MakeLocationSummary() const { |
| 2525 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 2526 } |
| 2527 |
| 2528 |
| 2529 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2530 compiler->GenerateCallRuntime(token_pos(), |
| 2531 kReThrowRuntimeEntry, |
| 2532 locs()); |
| 2533 __ int3(); |
| 2534 } |
| 2535 |
| 2536 |
| 2537 LocationSummary* GotoInstr::MakeLocationSummary() const { |
| 2538 return new LocationSummary(0, 0, LocationSummary::kNoCall); |
| 2539 } |
| 2540 |
| 2541 |
| 2542 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2543 // Add deoptimization descriptor for deoptimizing instructions |
| 2544 // that may be inserted before this instruction. |
| 2545 if (!compiler->is_optimizing()) { |
| 2546 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
| 2547 GetDeoptId(), |
| 2548 0); // No token position. |
| 2549 } |
| 2550 |
| 2551 if (HasParallelMove()) { |
| 2552 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 2553 } |
| 2554 |
| 2555 // We can fall through if the successor is the next block in the list. |
| 2556 // Otherwise, we need a jump. |
| 2557 if (!compiler->IsNextBlock(successor())) { |
| 2558 __ jmp(compiler->GetBlockLabel(successor())); |
| 2559 } |
| 2560 } |
| 2561 |
| 2562 |
| 2563 static Condition NegateCondition(Condition condition) { |
| 2564 switch (condition) { |
| 2565 case EQUAL: return NOT_EQUAL; |
| 2566 case NOT_EQUAL: return EQUAL; |
| 2567 case LESS: return GREATER_EQUAL; |
| 2568 case LESS_EQUAL: return GREATER; |
| 2569 case GREATER: return LESS_EQUAL; |
| 2570 case GREATER_EQUAL: return LESS; |
| 2571 case BELOW: return ABOVE_EQUAL; |
| 2572 case BELOW_EQUAL: return ABOVE; |
| 2573 case ABOVE: return BELOW_EQUAL; |
| 2574 case ABOVE_EQUAL: return BELOW; |
| 2575 default: |
| 2576 OS::Print("Error %d\n", condition); |
| 2577 UNIMPLEMENTED(); |
| 2578 return EQUAL; |
| 2579 } |
| 2580 } |
| 2581 |
| 2582 |
| 2583 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, |
| 2584 bool value) { |
| 2585 if (value && compiler->IsNextBlock(false_successor())) { |
| 2586 __ jmp(compiler->GetBlockLabel(true_successor())); |
| 2587 } else if (!value && compiler->IsNextBlock(true_successor())) { |
| 2588 __ jmp(compiler->GetBlockLabel(false_successor())); |
| 2589 } |
| 2590 } |
| 2591 |
| 2592 |
| 2593 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 2594 Condition true_condition) { |
| 2595 if (compiler->IsNextBlock(false_successor())) { |
| 2596 // If the next block is the false successor we will fall through to it. |
| 2597 __ j(true_condition, compiler->GetBlockLabel(true_successor())); |
| 2598 } else { |
| 2599 // If the next block is the true successor we negate comparison and fall |
| 2600 // through to it. |
| 2601 ASSERT(compiler->IsNextBlock(true_successor())); |
| 2602 Condition false_condition = NegateCondition(true_condition); |
| 2603 __ j(false_condition, compiler->GetBlockLabel(false_successor())); |
| 2604 } |
| 2605 } |
| 2606 |
| 2607 |
| 2608 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { |
| 2609 return LocationSummary::Make(0, |
| 2610 Location::RequiresRegister(), |
| 2611 LocationSummary::kNoCall); |
| 2612 } |
| 2613 |
| 2614 |
| 2615 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2616 __ MoveRegister(locs()->out().reg(), CTX); |
| 2617 } |
| 2618 |
| 2619 |
| 2620 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { |
| 2621 const intptr_t kNumInputs = 2; |
| 2622 const intptr_t kNumTemps = 0; |
| 2623 LocationSummary* locs = |
| 2624 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2625 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 2626 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 2627 locs->set_out(Location::RequiresRegister()); |
| 2628 return locs; |
| 2629 } |
| 2630 |
| 2631 |
| 2632 // Special code for numbers (compare values instead of references.) |
| 2633 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2634 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 2635 Location left = locs()->in(0); |
| 2636 Location right = locs()->in(1); |
| 2637 if (left.IsConstant() && right.IsConstant()) { |
| 2638 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 2639 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 2640 left.constant().raw() == right.constant().raw() : |
| 2641 left.constant().raw() != right.constant().raw(); |
| 2642 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False()); |
| 2643 return; |
| 2644 } |
| 2645 if (left.IsConstant()) { |
| 2646 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 2647 left.constant(), |
| 2648 needs_number_check()); |
| 2649 } else if (right.IsConstant()) { |
| 2650 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 2651 right.constant(), |
| 2652 needs_number_check()); |
| 2653 } else { |
| 2654 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 2655 right.reg(), |
| 2656 needs_number_check()); |
| 2657 } |
| 2658 |
| 2659 Register result = locs()->out().reg(); |
| 2660 Label load_true, done; |
| 2661 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 2662 __ j(true_condition, &load_true, Assembler::kNearJump); |
| 2663 __ LoadObject(result, Bool::False()); |
| 2664 __ jmp(&done, Assembler::kNearJump); |
| 2665 __ Bind(&load_true); |
| 2666 __ LoadObject(result, Bool::True()); |
| 2667 __ Bind(&done); |
| 2668 } |
| 2669 |
| 2670 |
| 2671 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 2672 BranchInstr* branch) { |
| 2673 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 2674 Location left = locs()->in(0); |
| 2675 Location right = locs()->in(1); |
| 2676 if (left.IsConstant() && right.IsConstant()) { |
| 2677 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 2678 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 2679 left.constant().raw() == right.constant().raw() : |
| 2680 left.constant().raw() != right.constant().raw(); |
| 2681 branch->EmitBranchOnValue(compiler, result); |
| 2682 return; |
| 2683 } |
| 2684 if (left.IsConstant()) { |
| 2685 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 2686 left.constant(), |
| 2687 needs_number_check()); |
| 2688 } else if (right.IsConstant()) { |
| 2689 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 2690 right.constant(), |
| 2691 needs_number_check()); |
| 2692 } else { |
| 2693 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 2694 right.reg(), |
| 2695 needs_number_check()); |
| 2696 } |
| 2697 |
| 2698 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 2699 branch->EmitBranchOnCondition(compiler, true_condition); |
| 2700 } |
| 2701 |
| 2702 |
| 2703 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2704 // The arguments to the stub include the closure, as does the arguments |
| 2705 // descriptor. |
| 2706 Register temp_reg = locs()->temp(0).reg(); |
| 2707 int argument_count = ArgumentCount(); |
| 2708 const Array& arguments_descriptor = |
| 2709 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
| 2710 argument_names())); |
| 2711 __ LoadObject(temp_reg, arguments_descriptor); |
| 2712 compiler->GenerateDartCall(deopt_id(), |
| 2713 token_pos(), |
| 2714 &StubCode::CallClosureFunctionLabel(), |
| 2715 PcDescriptors::kOther, |
| 2716 locs()); |
| 2717 __ Drop(argument_count); |
| 2718 } |
| 2719 |
| 2720 |
| 2721 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
| 2722 return LocationSummary::Make(1, |
| 2723 Location::RequiresRegister(), |
| 2724 LocationSummary::kNoCall); |
| 2725 } |
| 2726 |
| 2727 |
| 2728 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2729 Register value = locs()->in(0).reg(); |
| 2730 Register result = locs()->out().reg(); |
| 2731 |
| 2732 Label done; |
| 2733 __ LoadObject(result, Bool::True()); |
| 2734 __ CompareRegisters(result, value); |
| 2735 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 2736 __ LoadObject(result, Bool::False()); |
| 2737 __ Bind(&done); |
| 2738 } |
| 2739 |
| 2740 |
| 2741 LocationSummary* ChainContextInstr::MakeLocationSummary() const { |
| 2742 return LocationSummary::Make(1, |
| 2743 Location::NoLocation(), |
| 2744 LocationSummary::kNoCall); |
| 2745 } |
| 2746 |
| 2747 |
| 2748 void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2749 Register context_value = locs()->in(0).reg(); |
| 2750 |
| 2751 // Chain the new context in context_value to its parent in CTX. |
| 2752 __ StoreIntoObject(context_value, |
| 2753 FieldAddress(context_value, Context::parent_offset()), |
| 2754 CTX); |
| 2755 // Set new context as current context. |
| 2756 __ MoveRegister(CTX, context_value); |
| 2757 } |
| 2758 |
| 2759 |
| 2760 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const { |
| 2761 const intptr_t kNumInputs = 2; |
| 2762 const intptr_t kNumTemps = 0; |
| 2763 LocationSummary* locs = |
| 2764 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2765 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 2766 : Location::RequiresRegister()); |
| 2767 locs->set_in(1, Location::RequiresRegister()); |
| 2768 return locs; |
| 2769 } |
| 2770 |
| 2771 |
| 2772 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2773 Register value_reg = locs()->in(0).reg(); |
| 2774 Register dest_reg = locs()->in(1).reg(); |
| 2775 |
| 2776 if (value()->NeedsStoreBuffer()) { |
| 2777 __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()), |
| 2778 value_reg); |
| 2779 } else { |
| 2780 __ StoreIntoObjectNoBarrier( |
| 2781 dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg); |
| 2782 } |
| 2783 } |
| 2784 |
| 2785 |
| 2786 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { |
| 2787 return MakeCallSummary(); |
| 2788 } |
| 2789 |
| 2790 |
| 2791 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2792 const Class& cls = Class::ZoneHandle(constructor().Owner()); |
| 2793 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 2794 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 2795 compiler->GenerateCall(token_pos(), |
| 2796 &label, |
| 2797 PcDescriptors::kOther, |
| 2798 locs()); |
| 2799 __ Drop(ArgumentCount()); // Discard arguments. |
| 2800 } |
| 2801 |
| 2802 |
| 2803 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { |
| 2804 return MakeCallSummary(); |
| 2805 } |
| 2806 |
| 2807 |
| 2808 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2809 const Function& closure_function = function(); |
| 2810 ASSERT(!closure_function.IsImplicitStaticClosureFunction()); |
| 2811 const Code& stub = Code::Handle( |
| 2812 StubCode::GetAllocationStubForClosure(closure_function)); |
| 2813 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); |
| 2814 compiler->GenerateCall(token_pos(), |
| 2815 &label, |
| 2816 PcDescriptors::kOther, |
| 2817 locs()); |
| 2818 __ Drop(2); // Discard type arguments and receiver. |
| 2819 } |
| 2820 |
2509 } // namespace dart | 2821 } // namespace dart |
2510 | 2822 |
2511 #undef __ | 2823 #undef __ |
2512 | 2824 |
2513 #endif // defined TARGET_ARCH_X64 | 2825 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |