| 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_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 "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 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 | 261 |
| 261 | 262 |
| 262 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { | 263 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { |
| 263 const intptr_t kNumInputs = 2; | 264 const intptr_t kNumInputs = 2; |
| 264 const bool is_checked_strict_equal = | 265 const bool is_checked_strict_equal = |
| 265 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 266 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 266 if (receiver_class_id() == kMintCid) { | 267 if (receiver_class_id() == kMintCid) { |
| 267 const intptr_t kNumTemps = 1; | 268 const intptr_t kNumTemps = 1; |
| 268 LocationSummary* locs = | 269 LocationSummary* locs = |
| 269 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 270 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 270 locs->set_in(0, Location::RequiresXmmRegister()); | 271 locs->set_in(0, Location::RequiresFpuRegister()); |
| 271 locs->set_in(1, Location::RequiresXmmRegister()); | 272 locs->set_in(1, Location::RequiresFpuRegister()); |
| 272 locs->set_temp(0, Location::RequiresRegister()); | 273 locs->set_temp(0, Location::RequiresRegister()); |
| 273 locs->set_out(Location::RequiresRegister()); | 274 locs->set_out(Location::RequiresRegister()); |
| 274 return locs; | 275 return locs; |
| 275 } | 276 } |
| 276 if (receiver_class_id() == kDoubleCid) { | 277 if (receiver_class_id() == kDoubleCid) { |
| 277 const intptr_t kNumTemps = 0; | 278 const intptr_t kNumTemps = 0; |
| 278 LocationSummary* locs = | 279 LocationSummary* locs = |
| 279 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 280 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 280 locs->set_in(0, Location::RequiresXmmRegister()); | 281 locs->set_in(0, Location::RequiresFpuRegister()); |
| 281 locs->set_in(1, Location::RequiresXmmRegister()); | 282 locs->set_in(1, Location::RequiresFpuRegister()); |
| 282 locs->set_out(Location::RequiresRegister()); | 283 locs->set_out(Location::RequiresRegister()); |
| 283 return locs; | 284 return locs; |
| 284 } | 285 } |
| 285 if (receiver_class_id() == kSmiCid) { | 286 if (receiver_class_id() == kSmiCid) { |
| 286 const intptr_t kNumTemps = 0; | 287 const intptr_t kNumTemps = 0; |
| 287 LocationSummary* locs = | 288 LocationSummary* locs = |
| 288 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 289 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 289 locs->set_in(0, Location::RegisterOrConstant(left())); | 290 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 290 // Only one input can be a constant operand. The case of two constant | 291 // Only one input can be a constant operand. The case of two constant |
| 291 // operands should be handled by constant propagation. | 292 // operands should be handled by constant propagation. |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 return OVERFLOW; | 658 return OVERFLOW; |
| 658 } | 659 } |
| 659 } | 660 } |
| 660 | 661 |
| 661 | 662 |
| 662 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 663 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 663 const LocationSummary& locs, | 664 const LocationSummary& locs, |
| 664 Token::Kind kind, | 665 Token::Kind kind, |
| 665 BranchInstr* branch) { | 666 BranchInstr* branch) { |
| 666 ASSERT(Token::IsEqualityOperator(kind)); | 667 ASSERT(Token::IsEqualityOperator(kind)); |
| 667 XmmRegister left = locs.in(0).xmm_reg(); | 668 XmmRegister left = locs.in(0).fpu_reg(); |
| 668 XmmRegister right = locs.in(1).xmm_reg(); | 669 XmmRegister right = locs.in(1).fpu_reg(); |
| 669 Register temp = locs.temp(0).reg(); | 670 Register temp = locs.temp(0).reg(); |
| 670 __ movaps(XMM0, left); | 671 __ movaps(XMM0, left); |
| 671 __ pcmpeqq(XMM0, right); | 672 __ pcmpeqq(XMM0, right); |
| 672 __ movd(temp, XMM0); | 673 __ movd(temp, XMM0); |
| 673 | 674 |
| 674 Condition true_condition = TokenKindToMintCondition(kind); | 675 Condition true_condition = TokenKindToMintCondition(kind); |
| 675 __ cmpl(temp, Immediate(-1)); | 676 __ cmpl(temp, Immediate(-1)); |
| 676 | 677 |
| 677 if (branch != NULL) { | 678 if (branch != NULL) { |
| 678 branch->EmitBranchOnCondition(compiler, true_condition); | 679 branch->EmitBranchOnCondition(compiler, true_condition); |
| 679 } else { | 680 } else { |
| 680 Register result = locs.out().reg(); | 681 Register result = locs.out().reg(); |
| 681 Label done, is_true; | 682 Label done, is_true; |
| 682 __ j(true_condition, &is_true); | 683 __ j(true_condition, &is_true); |
| 683 __ LoadObject(result, Bool::False()); | 684 __ LoadObject(result, Bool::False()); |
| 684 __ jmp(&done); | 685 __ jmp(&done); |
| 685 __ Bind(&is_true); | 686 __ Bind(&is_true); |
| 686 __ LoadObject(result, Bool::True()); | 687 __ LoadObject(result, Bool::True()); |
| 687 __ Bind(&done); | 688 __ Bind(&done); |
| 688 } | 689 } |
| 689 } | 690 } |
| 690 | 691 |
| 691 | 692 |
| 692 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 693 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
| 693 const LocationSummary& locs, | 694 const LocationSummary& locs, |
| 694 Token::Kind kind, | 695 Token::Kind kind, |
| 695 BranchInstr* branch) { | 696 BranchInstr* branch) { |
| 696 XmmRegister left = locs.in(0).xmm_reg(); | 697 XmmRegister left = locs.in(0).fpu_reg(); |
| 697 XmmRegister right = locs.in(1).xmm_reg(); | 698 XmmRegister right = locs.in(1).fpu_reg(); |
| 698 Register left_tmp = locs.temp(0).reg(); | 699 Register left_tmp = locs.temp(0).reg(); |
| 699 Register right_tmp = locs.temp(1).reg(); | 700 Register right_tmp = locs.temp(1).reg(); |
| 700 Register result = branch == NULL ? locs.out().reg() : kNoRegister; | 701 Register result = branch == NULL ? locs.out().reg() : kNoRegister; |
| 701 | 702 |
| 702 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; | 703 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; |
| 703 switch (kind) { | 704 switch (kind) { |
| 704 case Token::kLT: | 705 case Token::kLT: |
| 705 hi_cond = LESS; | 706 hi_cond = LESS; |
| 706 lo_cond = BELOW; | 707 lo_cond = BELOW; |
| 707 break; | 708 break; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 UNREACHABLE(); | 767 UNREACHABLE(); |
| 767 return OVERFLOW; | 768 return OVERFLOW; |
| 768 } | 769 } |
| 769 } | 770 } |
| 770 | 771 |
| 771 | 772 |
| 772 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 773 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 773 const LocationSummary& locs, | 774 const LocationSummary& locs, |
| 774 Token::Kind kind, | 775 Token::Kind kind, |
| 775 BranchInstr* branch) { | 776 BranchInstr* branch) { |
| 776 XmmRegister left = locs.in(0).xmm_reg(); | 777 XmmRegister left = locs.in(0).fpu_reg(); |
| 777 XmmRegister right = locs.in(1).xmm_reg(); | 778 XmmRegister right = locs.in(1).fpu_reg(); |
| 778 | 779 |
| 779 Condition true_condition = TokenKindToDoubleCondition(kind); | 780 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 780 if (branch != NULL) { | 781 if (branch != NULL) { |
| 781 compiler->EmitDoubleCompareBranch( | 782 compiler->EmitDoubleCompareBranch( |
| 782 true_condition, left, right, branch); | 783 true_condition, left, right, branch); |
| 783 } else { | 784 } else { |
| 784 compiler->EmitDoubleCompareBool( | 785 compiler->EmitDoubleCompareBool( |
| 785 true_condition, left, right, locs.out().reg()); | 786 true_condition, left, right, locs.out().reg()); |
| 786 } | 787 } |
| 787 } | 788 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 876 } | 877 } |
| 877 | 878 |
| 878 | 879 |
| 879 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 880 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 880 const intptr_t kNumInputs = 2; | 881 const intptr_t kNumInputs = 2; |
| 881 const intptr_t kNumTemps = 0; | 882 const intptr_t kNumTemps = 0; |
| 882 if (operands_class_id() == kMintCid) { | 883 if (operands_class_id() == kMintCid) { |
| 883 const intptr_t kNumTemps = 2; | 884 const intptr_t kNumTemps = 2; |
| 884 LocationSummary* locs = | 885 LocationSummary* locs = |
| 885 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 886 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 886 locs->set_in(0, Location::RequiresXmmRegister()); | 887 locs->set_in(0, Location::RequiresFpuRegister()); |
| 887 locs->set_in(1, Location::RequiresXmmRegister()); | 888 locs->set_in(1, Location::RequiresFpuRegister()); |
| 888 locs->set_temp(0, Location::RequiresRegister()); | 889 locs->set_temp(0, Location::RequiresRegister()); |
| 889 locs->set_temp(1, Location::RequiresRegister()); | 890 locs->set_temp(1, Location::RequiresRegister()); |
| 890 locs->set_out(Location::RequiresRegister()); | 891 locs->set_out(Location::RequiresRegister()); |
| 891 return locs; | 892 return locs; |
| 892 } | 893 } |
| 893 if (operands_class_id() == kDoubleCid) { | 894 if (operands_class_id() == kDoubleCid) { |
| 894 LocationSummary* summary = | 895 LocationSummary* summary = |
| 895 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 896 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 896 summary->set_in(0, Location::RequiresXmmRegister()); | 897 summary->set_in(0, Location::RequiresFpuRegister()); |
| 897 summary->set_in(1, Location::RequiresXmmRegister()); | 898 summary->set_in(1, Location::RequiresFpuRegister()); |
| 898 summary->set_out(Location::RequiresRegister()); | 899 summary->set_out(Location::RequiresRegister()); |
| 899 return summary; | 900 return summary; |
| 900 } else if (operands_class_id() == kSmiCid) { | 901 } else if (operands_class_id() == kSmiCid) { |
| 901 LocationSummary* summary = | 902 LocationSummary* summary = |
| 902 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 903 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 903 summary->set_in(0, Location::RegisterOrConstant(left())); | 904 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 904 // Only one input can be a constant operand. The case of two constant | 905 // Only one input can be a constant operand. The case of two constant |
| 905 // operands should be handled by constant propagation. | 906 // operands should be handled by constant propagation. |
| 906 summary->set_in(1, summary->in(0).IsConstant() | 907 summary->set_in(1, summary->in(0).IsConstant() |
| 907 ? Location::RequiresRegister() | 908 ? Location::RequiresRegister() |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1138 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { | 1139 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { |
| 1139 const intptr_t kNumInputs = 2; | 1140 const intptr_t kNumInputs = 2; |
| 1140 const intptr_t kNumTemps = 0; | 1141 const intptr_t kNumTemps = 0; |
| 1141 LocationSummary* locs = | 1142 LocationSummary* locs = |
| 1142 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1143 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1143 locs->set_in(0, Location::RequiresRegister()); | 1144 locs->set_in(0, Location::RequiresRegister()); |
| 1144 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1145 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
| 1145 ? Location::RegisterOrSmiConstant(index()) | 1146 ? Location::RegisterOrSmiConstant(index()) |
| 1146 : Location::RequiresRegister()); | 1147 : Location::RequiresRegister()); |
| 1147 if (representation() == kUnboxedDouble) { | 1148 if (representation() == kUnboxedDouble) { |
| 1148 locs->set_out(Location::RequiresXmmRegister()); | 1149 locs->set_out(Location::RequiresFpuRegister()); |
| 1149 } else { | 1150 } else { |
| 1150 locs->set_out(Location::RequiresRegister()); | 1151 locs->set_out(Location::RequiresRegister()); |
| 1151 } | 1152 } |
| 1152 return locs; | 1153 return locs; |
| 1153 } | 1154 } |
| 1154 | 1155 |
| 1155 | 1156 |
| 1156 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1157 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1157 Register array = locs()->in(0).reg(); | 1158 Register array = locs()->in(0).reg(); |
| 1158 Location index = locs()->in(1); | 1159 Location index = locs()->in(1); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1177 return; | 1178 return; |
| 1178 } | 1179 } |
| 1179 | 1180 |
| 1180 FieldAddress element_address = index.IsRegister() ? | 1181 FieldAddress element_address = index.IsRegister() ? |
| 1181 FlowGraphCompiler::ElementAddressForRegIndex( | 1182 FlowGraphCompiler::ElementAddressForRegIndex( |
| 1182 class_id(), array, index.reg()) : | 1183 class_id(), array, index.reg()) : |
| 1183 FlowGraphCompiler::ElementAddressForIntIndex( | 1184 FlowGraphCompiler::ElementAddressForIntIndex( |
| 1184 class_id(), array, Smi::Cast(index.constant()).Value()); | 1185 class_id(), array, Smi::Cast(index.constant()).Value()); |
| 1185 | 1186 |
| 1186 if (representation() == kUnboxedDouble) { | 1187 if (representation() == kUnboxedDouble) { |
| 1187 XmmRegister result = locs()->out().xmm_reg(); | 1188 XmmRegister result = locs()->out().fpu_reg(); |
| 1188 if (class_id() == kFloat32ArrayCid) { | 1189 if (class_id() == kFloat32ArrayCid) { |
| 1189 // Load single precision float. | 1190 // Load single precision float. |
| 1190 __ movss(result, element_address); | 1191 __ movss(result, element_address); |
| 1191 // Promote to double. | 1192 // Promote to double. |
| 1192 __ cvtss2sd(result, locs()->out().xmm_reg()); | 1193 __ cvtss2sd(result, locs()->out().fpu_reg()); |
| 1193 } else { | 1194 } else { |
| 1194 ASSERT(class_id() == kFloat64ArrayCid); | 1195 ASSERT(class_id() == kFloat64ArrayCid); |
| 1195 __ movsd(result, element_address); | 1196 __ movsd(result, element_address); |
| 1196 } | 1197 } |
| 1197 return; | 1198 return; |
| 1198 } | 1199 } |
| 1199 | 1200 |
| 1200 Register result = locs()->out().reg(); | 1201 Register result = locs()->out().reg(); |
| 1201 if ((class_id() == kUint8ArrayCid) || | 1202 if ((class_id() == kUint8ArrayCid) || |
| 1202 (class_id() == kUint8ClampedArrayCid)) { | 1203 (class_id() == kUint8ClampedArrayCid)) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1231 ? Location::WritableRegister() | 1232 ? Location::WritableRegister() |
| 1232 : Location::RegisterOrConstant(value())); | 1233 : Location::RegisterOrConstant(value())); |
| 1233 break; | 1234 break; |
| 1234 case kUint8ArrayCid: | 1235 case kUint8ArrayCid: |
| 1235 // TODO(fschneider): Add location constraint for byte registers (EAX, | 1236 // TODO(fschneider): Add location constraint for byte registers (EAX, |
| 1236 // EBX, ECX, EDX) instead of using a fixed register. | 1237 // EBX, ECX, EDX) instead of using a fixed register. |
| 1237 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); | 1238 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); |
| 1238 break; | 1239 break; |
| 1239 case kFloat32ArrayCid: | 1240 case kFloat32ArrayCid: |
| 1240 // Need temp register for float-to-double conversion. | 1241 // Need temp register for float-to-double conversion. |
| 1241 locs->AddTemp(Location::RequiresXmmRegister()); | 1242 locs->AddTemp(Location::RequiresFpuRegister()); |
| 1242 // Fall through. | 1243 // Fall through. |
| 1243 case kFloat64ArrayCid: | 1244 case kFloat64ArrayCid: |
| 1244 // TODO(srdjan): Support Float64 constants. | 1245 // TODO(srdjan): Support Float64 constants. |
| 1245 locs->set_in(2, Location::RequiresXmmRegister()); | 1246 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1246 break; | 1247 break; |
| 1247 default: | 1248 default: |
| 1248 UNREACHABLE(); | 1249 UNREACHABLE(); |
| 1249 return NULL; | 1250 return NULL; |
| 1250 } | 1251 } |
| 1251 return locs; | 1252 return locs; |
| 1252 } | 1253 } |
| 1253 | 1254 |
| 1254 | 1255 |
| 1255 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1256 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1287 ASSERT(locs()->in(2).reg() == EAX); | 1288 ASSERT(locs()->in(2).reg() == EAX); |
| 1288 __ SmiUntag(EAX); | 1289 __ SmiUntag(EAX); |
| 1289 __ movb(element_address, AL); | 1290 __ movb(element_address, AL); |
| 1290 } | 1291 } |
| 1291 if (index.IsRegister()) { | 1292 if (index.IsRegister()) { |
| 1292 __ SmiTag(index.reg()); // Re-tag. | 1293 __ SmiTag(index.reg()); // Re-tag. |
| 1293 } | 1294 } |
| 1294 break; | 1295 break; |
| 1295 case kFloat32ArrayCid: | 1296 case kFloat32ArrayCid: |
| 1296 // Convert to single precision. | 1297 // Convert to single precision. |
| 1297 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg()); | 1298 __ cvtsd2ss(locs()->temp(0).fpu_reg(), locs()->in(2).fpu_reg()); |
| 1298 // Store. | 1299 // Store. |
| 1299 __ movss(element_address, locs()->temp(0).xmm_reg()); | 1300 __ movss(element_address, locs()->temp(0).fpu_reg()); |
| 1300 break; | 1301 break; |
| 1301 case kFloat64ArrayCid: | 1302 case kFloat64ArrayCid: |
| 1302 __ movsd(element_address, locs()->in(2).xmm_reg()); | 1303 __ movsd(element_address, locs()->in(2).fpu_reg()); |
| 1303 break; | 1304 break; |
| 1304 default: | 1305 default: |
| 1305 UNREACHABLE(); | 1306 UNREACHABLE(); |
| 1306 } | 1307 } |
| 1307 } | 1308 } |
| 1308 | 1309 |
| 1309 | 1310 |
| 1310 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { | 1311 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { |
| 1311 const intptr_t kNumInputs = 2; | 1312 const intptr_t kNumInputs = 2; |
| 1312 const intptr_t num_temps = 0; | 1313 const intptr_t num_temps = 0; |
| (...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2081 } | 2082 } |
| 2082 | 2083 |
| 2083 | 2084 |
| 2084 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const { | 2085 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const { |
| 2085 const intptr_t kNumInputs = 1; | 2086 const intptr_t kNumInputs = 1; |
| 2086 const intptr_t kNumTemps = 0; | 2087 const intptr_t kNumTemps = 0; |
| 2087 LocationSummary* summary = | 2088 LocationSummary* summary = |
| 2088 new LocationSummary(kNumInputs, | 2089 new LocationSummary(kNumInputs, |
| 2089 kNumTemps, | 2090 kNumTemps, |
| 2090 LocationSummary::kCallOnSlowPath); | 2091 LocationSummary::kCallOnSlowPath); |
| 2091 summary->set_in(0, Location::RequiresXmmRegister()); | 2092 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2092 summary->set_out(Location::RequiresRegister()); | 2093 summary->set_out(Location::RequiresRegister()); |
| 2093 return summary; | 2094 return summary; |
| 2094 } | 2095 } |
| 2095 | 2096 |
| 2096 | 2097 |
| 2097 class BoxDoubleSlowPath : public SlowPathCode { | 2098 class BoxDoubleSlowPath : public SlowPathCode { |
| 2098 public: | 2099 public: |
| 2099 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction) | 2100 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction) |
| 2100 : instruction_(instruction) { } | 2101 : instruction_(instruction) { } |
| 2101 | 2102 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2124 private: | 2125 private: |
| 2125 BoxDoubleInstr* instruction_; | 2126 BoxDoubleInstr* instruction_; |
| 2126 }; | 2127 }; |
| 2127 | 2128 |
| 2128 | 2129 |
| 2129 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2130 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2130 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 2131 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
| 2131 compiler->AddSlowPathCode(slow_path); | 2132 compiler->AddSlowPathCode(slow_path); |
| 2132 | 2133 |
| 2133 Register out_reg = locs()->out().reg(); | 2134 Register out_reg = locs()->out().reg(); |
| 2134 XmmRegister value = locs()->in(0).xmm_reg(); | 2135 XmmRegister value = locs()->in(0).fpu_reg(); |
| 2135 | 2136 |
| 2136 AssemblerMacros::TryAllocate(compiler->assembler(), | 2137 AssemblerMacros::TryAllocate(compiler->assembler(), |
| 2137 compiler->double_class(), | 2138 compiler->double_class(), |
| 2138 slow_path->entry_label(), | 2139 slow_path->entry_label(), |
| 2139 Assembler::kFarJump, | 2140 Assembler::kFarJump, |
| 2140 out_reg); | 2141 out_reg); |
| 2141 __ Bind(slow_path->exit_label()); | 2142 __ Bind(slow_path->exit_label()); |
| 2142 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); | 2143 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
| 2143 } | 2144 } |
| 2144 | 2145 |
| 2145 | 2146 |
| 2146 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { | 2147 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { |
| 2147 const intptr_t kNumInputs = 1; | 2148 const intptr_t kNumInputs = 1; |
| 2148 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | 2149 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; |
| 2149 LocationSummary* summary = | 2150 LocationSummary* summary = |
| 2150 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2151 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2151 summary->set_in(0, Location::RequiresRegister()); | 2152 summary->set_in(0, Location::RequiresRegister()); |
| 2152 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); | 2153 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); |
| 2153 summary->set_out(Location::RequiresXmmRegister()); | 2154 summary->set_out(Location::RequiresFpuRegister()); |
| 2154 return summary; | 2155 return summary; |
| 2155 } | 2156 } |
| 2156 | 2157 |
| 2157 | 2158 |
| 2158 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2159 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2159 const intptr_t value_cid = value()->ResultCid(); | 2160 const intptr_t value_cid = value()->ResultCid(); |
| 2160 const Register value = locs()->in(0).reg(); | 2161 const Register value = locs()->in(0).reg(); |
| 2161 const XmmRegister result = locs()->out().xmm_reg(); | 2162 const XmmRegister result = locs()->out().fpu_reg(); |
| 2162 | 2163 |
| 2163 if (value_cid == kDoubleCid) { | 2164 if (value_cid == kDoubleCid) { |
| 2164 __ movsd(result, FieldAddress(value, Double::value_offset())); | 2165 __ movsd(result, FieldAddress(value, Double::value_offset())); |
| 2165 } else if (value_cid == kSmiCid) { | 2166 } else if (value_cid == kSmiCid) { |
| 2166 __ SmiUntag(value); // Untag input before conversion. | 2167 __ SmiUntag(value); // Untag input before conversion. |
| 2167 __ cvtsi2sd(result, value); | 2168 __ cvtsi2sd(result, value); |
| 2168 __ SmiTag(value); // Restore input register. | 2169 __ SmiTag(value); // Restore input register. |
| 2169 } else { | 2170 } else { |
| 2170 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); | 2171 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
| 2171 compiler->LoadDoubleOrSmiToXmm(result, | 2172 compiler->LoadDoubleOrSmiToFpu(result, |
| 2172 value, | 2173 value, |
| 2173 locs()->temp(0).reg(), | 2174 locs()->temp(0).reg(), |
| 2174 deopt); | 2175 deopt); |
| 2175 } | 2176 } |
| 2176 } | 2177 } |
| 2177 | 2178 |
| 2178 | 2179 |
| 2179 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { | 2180 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { |
| 2180 const intptr_t kNumInputs = 2; | 2181 const intptr_t kNumInputs = 2; |
| 2181 const intptr_t kNumTemps = 0; | 2182 const intptr_t kNumTemps = 0; |
| 2182 LocationSummary* summary = | 2183 LocationSummary* summary = |
| 2183 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2184 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2184 summary->set_in(0, Location::RequiresXmmRegister()); | 2185 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2185 summary->set_in(1, Location::RequiresXmmRegister()); | 2186 summary->set_in(1, Location::RequiresFpuRegister()); |
| 2186 summary->set_out(Location::SameAsFirstInput()); | 2187 summary->set_out(Location::SameAsFirstInput()); |
| 2187 return summary; | 2188 return summary; |
| 2188 } | 2189 } |
| 2189 | 2190 |
| 2190 | 2191 |
| 2191 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2192 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2192 XmmRegister left = locs()->in(0).xmm_reg(); | 2193 XmmRegister left = locs()->in(0).fpu_reg(); |
| 2193 XmmRegister right = locs()->in(1).xmm_reg(); | 2194 XmmRegister right = locs()->in(1).fpu_reg(); |
| 2194 | 2195 |
| 2195 ASSERT(locs()->out().xmm_reg() == left); | 2196 ASSERT(locs()->out().fpu_reg() == left); |
| 2196 | 2197 |
| 2197 switch (op_kind()) { | 2198 switch (op_kind()) { |
| 2198 case Token::kADD: __ addsd(left, right); break; | 2199 case Token::kADD: __ addsd(left, right); break; |
| 2199 case Token::kSUB: __ subsd(left, right); break; | 2200 case Token::kSUB: __ subsd(left, right); break; |
| 2200 case Token::kMUL: __ mulsd(left, right); break; | 2201 case Token::kMUL: __ mulsd(left, right); break; |
| 2201 case Token::kDIV: __ divsd(left, right); break; | 2202 case Token::kDIV: __ divsd(left, right); break; |
| 2202 default: UNREACHABLE(); | 2203 default: UNREACHABLE(); |
| 2203 } | 2204 } |
| 2204 } | 2205 } |
| 2205 | 2206 |
| 2206 | 2207 |
| 2207 LocationSummary* MathSqrtInstr::MakeLocationSummary() const { | 2208 LocationSummary* MathSqrtInstr::MakeLocationSummary() const { |
| 2208 const intptr_t kNumInputs = 1; | 2209 const intptr_t kNumInputs = 1; |
| 2209 const intptr_t kNumTemps = 0; | 2210 const intptr_t kNumTemps = 0; |
| 2210 LocationSummary* summary = | 2211 LocationSummary* summary = |
| 2211 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2212 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2212 summary->set_in(0, Location::RequiresXmmRegister()); | 2213 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2213 summary->set_out(Location::RequiresXmmRegister()); | 2214 summary->set_out(Location::RequiresFpuRegister()); |
| 2214 return summary; | 2215 return summary; |
| 2215 } | 2216 } |
| 2216 | 2217 |
| 2217 | 2218 |
| 2218 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2219 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2219 __ sqrtsd(locs()->out().xmm_reg(), locs()->in(0).xmm_reg()); | 2220 __ sqrtsd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); |
| 2220 } | 2221 } |
| 2221 | 2222 |
| 2222 | 2223 |
| 2223 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { | 2224 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { |
| 2224 const intptr_t kNumInputs = 1; | 2225 const intptr_t kNumInputs = 1; |
| 2225 const intptr_t kNumTemps = 0; | 2226 const intptr_t kNumTemps = 0; |
| 2226 LocationSummary* summary = | 2227 LocationSummary* summary = |
| 2227 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2228 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2228 summary->set_in(0, Location::RequiresRegister()); | 2229 summary->set_in(0, Location::RequiresRegister()); |
| 2229 summary->set_out(Location::SameAsFirstInput()); | 2230 summary->set_out(Location::SameAsFirstInput()); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2329 locs()); | 2330 locs()); |
| 2330 __ Bind(&done); | 2331 __ Bind(&done); |
| 2331 } | 2332 } |
| 2332 | 2333 |
| 2333 | 2334 |
| 2334 LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const { | 2335 LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const { |
| 2335 const intptr_t kNumInputs = 1; | 2336 const intptr_t kNumInputs = 1; |
| 2336 const intptr_t kNumTemps = 0; | 2337 const intptr_t kNumTemps = 0; |
| 2337 LocationSummary* result = new LocationSummary( | 2338 LocationSummary* result = new LocationSummary( |
| 2338 kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2339 kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2339 result->set_in(0, Location::RequiresXmmRegister()); | 2340 result->set_in(0, Location::RequiresFpuRegister()); |
| 2340 result->set_out(Location::RequiresRegister()); | 2341 result->set_out(Location::RequiresRegister()); |
| 2341 return result; | 2342 return result; |
| 2342 } | 2343 } |
| 2343 | 2344 |
| 2344 | 2345 |
| 2345 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2346 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2346 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); | 2347 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); |
| 2347 Register result = locs()->out().reg(); | 2348 Register result = locs()->out().reg(); |
| 2348 XmmRegister value = locs()->in(0).xmm_reg(); | 2349 XmmRegister value = locs()->in(0).fpu_reg(); |
| 2349 __ cvttsd2si(result, value); | 2350 __ cvttsd2si(result, value); |
| 2350 // Overflow is signalled with minint. | 2351 // Overflow is signalled with minint. |
| 2351 Label do_call, done; | 2352 Label do_call, done; |
| 2352 // Check for overflow and that it fits into Smi. | 2353 // Check for overflow and that it fits into Smi. |
| 2353 __ cmpl(result, Immediate(0xC0000000)); | 2354 __ cmpl(result, Immediate(0xC0000000)); |
| 2354 __ j(NEGATIVE, deopt); | 2355 __ j(NEGATIVE, deopt); |
| 2355 __ SmiTag(result); | 2356 __ SmiTag(result); |
| 2356 } | 2357 } |
| 2357 | 2358 |
| 2358 | 2359 |
| 2359 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { | 2360 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { |
| 2360 const intptr_t kNumInputs = 1; | 2361 const intptr_t kNumInputs = 1; |
| 2361 const intptr_t kNumTemps = | 2362 const intptr_t kNumTemps = |
| 2362 (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0; | 2363 (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0; |
| 2363 LocationSummary* result = | 2364 LocationSummary* result = |
| 2364 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2365 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2365 result->set_in(0, Location::RequiresXmmRegister()); | 2366 result->set_in(0, Location::RequiresFpuRegister()); |
| 2366 result->set_out(Location::RequiresXmmRegister()); | 2367 result->set_out(Location::RequiresFpuRegister()); |
| 2367 if (recognized_kind() == MethodRecognizer::kDoubleRound) { | 2368 if (recognized_kind() == MethodRecognizer::kDoubleRound) { |
| 2368 result->set_temp(0, Location::RequiresXmmRegister()); | 2369 result->set_temp(0, Location::RequiresFpuRegister()); |
| 2369 } | 2370 } |
| 2370 return result; | 2371 return result; |
| 2371 } | 2372 } |
| 2372 | 2373 |
| 2373 | 2374 |
| 2374 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2375 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2375 XmmRegister value = locs()->in(0).xmm_reg(); | 2376 XmmRegister value = locs()->in(0).fpu_reg(); |
| 2376 XmmRegister result = locs()->out().xmm_reg(); | 2377 XmmRegister result = locs()->out().fpu_reg(); |
| 2377 if (recognized_kind() == MethodRecognizer::kDoubleTruncate) { | 2378 if (recognized_kind() == MethodRecognizer::kDoubleTruncate) { |
| 2378 __ roundsd(result, value, Assembler::kRoundToZero); | 2379 __ roundsd(result, value, Assembler::kRoundToZero); |
| 2379 } else { | 2380 } else { |
| 2380 XmmRegister temp = locs()->temp(0).xmm_reg(); | 2381 XmmRegister temp = locs()->temp(0).fpu_reg(); |
| 2381 __ DoubleRound(result, value, temp); | 2382 __ DoubleRound(result, value, temp); |
| 2382 } | 2383 } |
| 2383 } | 2384 } |
| 2384 | 2385 |
| 2385 | 2386 |
| 2386 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { | 2387 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { |
| 2387 return MakeCallSummary(); | 2388 return MakeCallSummary(); |
| 2388 } | 2389 } |
| 2389 | 2390 |
| 2390 | 2391 |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2563 } | 2564 } |
| 2564 | 2565 |
| 2565 | 2566 |
| 2566 LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const { | 2567 LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const { |
| 2567 const intptr_t kNumInputs = 1; | 2568 const intptr_t kNumInputs = 1; |
| 2568 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | 2569 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; |
| 2569 LocationSummary* summary = | 2570 LocationSummary* summary = |
| 2570 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2571 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2571 summary->set_in(0, Location::RequiresRegister()); | 2572 summary->set_in(0, Location::RequiresRegister()); |
| 2572 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); | 2573 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); |
| 2573 summary->set_out(Location::RequiresXmmRegister()); | 2574 summary->set_out(Location::RequiresFpuRegister()); |
| 2574 return summary; | 2575 return summary; |
| 2575 } | 2576 } |
| 2576 | 2577 |
| 2577 | 2578 |
| 2578 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2579 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2579 const intptr_t value_cid = value()->ResultCid(); | 2580 const intptr_t value_cid = value()->ResultCid(); |
| 2580 const Register value = locs()->in(0).reg(); | 2581 const Register value = locs()->in(0).reg(); |
| 2581 const XmmRegister result = locs()->out().xmm_reg(); | 2582 const XmmRegister result = locs()->out().fpu_reg(); |
| 2582 | 2583 |
| 2583 if (value_cid == kMintCid) { | 2584 if (value_cid == kMintCid) { |
| 2584 __ movsd(result, FieldAddress(value, Mint::value_offset())); | 2585 __ movsd(result, FieldAddress(value, Mint::value_offset())); |
| 2585 } else if (value_cid == kSmiCid) { | 2586 } else if (value_cid == kSmiCid) { |
| 2586 __ SmiUntag(value); // Untag input before conversion. | 2587 __ SmiUntag(value); // Untag input before conversion. |
| 2587 __ movd(result, value); | 2588 __ movd(result, value); |
| 2588 __ pmovsxdq(result, result); | 2589 __ pmovsxdq(result, result); |
| 2589 __ SmiTag(value); // Restore input register. | 2590 __ SmiTag(value); // Restore input register. |
| 2590 } else { | 2591 } else { |
| 2591 Register temp = locs()->temp(0).reg(); | 2592 Register temp = locs()->temp(0).reg(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2607 } | 2608 } |
| 2608 | 2609 |
| 2609 | 2610 |
| 2610 LocationSummary* BoxIntegerInstr::MakeLocationSummary() const { | 2611 LocationSummary* BoxIntegerInstr::MakeLocationSummary() const { |
| 2611 const intptr_t kNumInputs = 1; | 2612 const intptr_t kNumInputs = 1; |
| 2612 const intptr_t kNumTemps = 2; | 2613 const intptr_t kNumTemps = 2; |
| 2613 LocationSummary* summary = | 2614 LocationSummary* summary = |
| 2614 new LocationSummary(kNumInputs, | 2615 new LocationSummary(kNumInputs, |
| 2615 kNumTemps, | 2616 kNumTemps, |
| 2616 LocationSummary::kCallOnSlowPath); | 2617 LocationSummary::kCallOnSlowPath); |
| 2617 summary->set_in(0, Location::RequiresXmmRegister()); | 2618 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2618 summary->set_temp(0, Location::RegisterLocation(EAX)); | 2619 summary->set_temp(0, Location::RegisterLocation(EAX)); |
| 2619 summary->set_temp(1, Location::RegisterLocation(EDX)); | 2620 summary->set_temp(1, Location::RegisterLocation(EDX)); |
| 2620 // TODO(fschneider): Save one temp by using result register as a temp. | 2621 // TODO(fschneider): Save one temp by using result register as a temp. |
| 2621 summary->set_out(Location::RequiresRegister()); | 2622 summary->set_out(Location::RequiresRegister()); |
| 2622 return summary; | 2623 return summary; |
| 2623 } | 2624 } |
| 2624 | 2625 |
| 2625 | 2626 |
| 2626 class BoxIntegerSlowPath : public SlowPathCode { | 2627 class BoxIntegerSlowPath : public SlowPathCode { |
| 2627 public: | 2628 public: |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2654 private: | 2655 private: |
| 2655 BoxIntegerInstr* instruction_; | 2656 BoxIntegerInstr* instruction_; |
| 2656 }; | 2657 }; |
| 2657 | 2658 |
| 2658 | 2659 |
| 2659 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2660 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2660 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | 2661 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
| 2661 compiler->AddSlowPathCode(slow_path); | 2662 compiler->AddSlowPathCode(slow_path); |
| 2662 | 2663 |
| 2663 Register out_reg = locs()->out().reg(); | 2664 Register out_reg = locs()->out().reg(); |
| 2664 XmmRegister value = locs()->in(0).xmm_reg(); | 2665 XmmRegister value = locs()->in(0).fpu_reg(); |
| 2665 | 2666 |
| 2666 // Unboxed operations produce smis or mint-sized values. | 2667 // Unboxed operations produce smis or mint-sized values. |
| 2667 // Check if value fits into a smi. | 2668 // Check if value fits into a smi. |
| 2668 Label not_smi, done; | 2669 Label not_smi, done; |
| 2669 __ pextrd(EDX, value, Immediate(1)); // Upper half. | 2670 __ pextrd(EDX, value, Immediate(1)); // Upper half. |
| 2670 __ pextrd(EAX, value, Immediate(0)); // Lower half. | 2671 __ pextrd(EAX, value, Immediate(0)); // Lower half. |
| 2671 // 1. Compute (x + -kMinSmi) which has to be in the range | 2672 // 1. Compute (x + -kMinSmi) which has to be in the range |
| 2672 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. | 2673 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. |
| 2673 __ addl(EAX, Immediate(0x40000000)); | 2674 __ addl(EAX, Immediate(0x40000000)); |
| 2674 __ adcl(EDX, Immediate(0)); | 2675 __ adcl(EDX, Immediate(0)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2698 | 2699 |
| 2699 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { | 2700 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { |
| 2700 const intptr_t kNumInputs = 2; | 2701 const intptr_t kNumInputs = 2; |
| 2701 switch (op_kind()) { | 2702 switch (op_kind()) { |
| 2702 case Token::kBIT_AND: | 2703 case Token::kBIT_AND: |
| 2703 case Token::kBIT_OR: | 2704 case Token::kBIT_OR: |
| 2704 case Token::kBIT_XOR: { | 2705 case Token::kBIT_XOR: { |
| 2705 const intptr_t kNumTemps = 0; | 2706 const intptr_t kNumTemps = 0; |
| 2706 LocationSummary* summary = | 2707 LocationSummary* summary = |
| 2707 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2708 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2708 summary->set_in(0, Location::RequiresXmmRegister()); | 2709 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2709 summary->set_in(1, Location::RequiresXmmRegister()); | 2710 summary->set_in(1, Location::RequiresFpuRegister()); |
| 2710 summary->set_out(Location::SameAsFirstInput()); | 2711 summary->set_out(Location::SameAsFirstInput()); |
| 2711 return summary; | 2712 return summary; |
| 2712 } | 2713 } |
| 2713 case Token::kADD: | 2714 case Token::kADD: |
| 2714 case Token::kSUB: { | 2715 case Token::kSUB: { |
| 2715 const intptr_t kNumTemps = 2; | 2716 const intptr_t kNumTemps = 2; |
| 2716 LocationSummary* summary = | 2717 LocationSummary* summary = |
| 2717 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2718 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2718 summary->set_in(0, Location::RequiresXmmRegister()); | 2719 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2719 summary->set_in(1, Location::RequiresXmmRegister()); | 2720 summary->set_in(1, Location::RequiresFpuRegister()); |
| 2720 summary->set_temp(0, Location::RequiresRegister()); | 2721 summary->set_temp(0, Location::RequiresRegister()); |
| 2721 summary->set_temp(1, Location::RequiresRegister()); | 2722 summary->set_temp(1, Location::RequiresRegister()); |
| 2722 summary->set_out(Location::SameAsFirstInput()); | 2723 summary->set_out(Location::SameAsFirstInput()); |
| 2723 return summary; | 2724 return summary; |
| 2724 } | 2725 } |
| 2725 default: | 2726 default: |
| 2726 UNREACHABLE(); | 2727 UNREACHABLE(); |
| 2727 return NULL; | 2728 return NULL; |
| 2728 } | 2729 } |
| 2729 } | 2730 } |
| 2730 | 2731 |
| 2731 | 2732 |
| 2732 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2733 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2733 XmmRegister left = locs()->in(0).xmm_reg(); | 2734 XmmRegister left = locs()->in(0).fpu_reg(); |
| 2734 XmmRegister right = locs()->in(1).xmm_reg(); | 2735 XmmRegister right = locs()->in(1).fpu_reg(); |
| 2735 | 2736 |
| 2736 ASSERT(locs()->out().xmm_reg() == left); | 2737 ASSERT(locs()->out().fpu_reg() == left); |
| 2737 | 2738 |
| 2738 switch (op_kind()) { | 2739 switch (op_kind()) { |
| 2739 case Token::kBIT_AND: __ andpd(left, right); break; | 2740 case Token::kBIT_AND: __ andpd(left, right); break; |
| 2740 case Token::kBIT_OR: __ orpd(left, right); break; | 2741 case Token::kBIT_OR: __ orpd(left, right); break; |
| 2741 case Token::kBIT_XOR: __ xorpd(left, right); break; | 2742 case Token::kBIT_XOR: __ xorpd(left, right); break; |
| 2742 case Token::kADD: | 2743 case Token::kADD: |
| 2743 case Token::kSUB: { | 2744 case Token::kSUB: { |
| 2744 Register lo = locs()->temp(0).reg(); | 2745 Register lo = locs()->temp(0).reg(); |
| 2745 Register hi = locs()->temp(1).reg(); | 2746 Register hi = locs()->temp(1).reg(); |
| 2746 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2747 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2770 default: UNREACHABLE(); | 2771 default: UNREACHABLE(); |
| 2771 } | 2772 } |
| 2772 } | 2773 } |
| 2773 | 2774 |
| 2774 | 2775 |
| 2775 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { | 2776 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { |
| 2776 const intptr_t kNumInputs = 2; | 2777 const intptr_t kNumInputs = 2; |
| 2777 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; | 2778 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; |
| 2778 LocationSummary* summary = | 2779 LocationSummary* summary = |
| 2779 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2780 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2780 summary->set_in(0, Location::RequiresXmmRegister()); | 2781 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2781 summary->set_in(1, Location::RegisterLocation(ECX)); | 2782 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 2782 summary->set_temp(0, Location::RequiresRegister()); | 2783 summary->set_temp(0, Location::RequiresRegister()); |
| 2783 if (op_kind() == Token::kSHL) { | 2784 if (op_kind() == Token::kSHL) { |
| 2784 summary->set_temp(1, Location::RequiresRegister()); | 2785 summary->set_temp(1, Location::RequiresRegister()); |
| 2785 } | 2786 } |
| 2786 summary->set_out(Location::SameAsFirstInput()); | 2787 summary->set_out(Location::SameAsFirstInput()); |
| 2787 return summary; | 2788 return summary; |
| 2788 } | 2789 } |
| 2789 | 2790 |
| 2790 | 2791 |
| 2791 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2792 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2792 XmmRegister left = locs()->in(0).xmm_reg(); | 2793 XmmRegister left = locs()->in(0).fpu_reg(); |
| 2793 ASSERT(locs()->in(1).reg() == ECX); | 2794 ASSERT(locs()->in(1).reg() == ECX); |
| 2794 ASSERT(locs()->out().xmm_reg() == left); | 2795 ASSERT(locs()->out().fpu_reg() == left); |
| 2795 | 2796 |
| 2796 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2797 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2797 kDeoptShiftMintOp); | 2798 kDeoptShiftMintOp); |
| 2798 Label done; | 2799 Label done; |
| 2799 __ testl(ECX, ECX); | 2800 __ testl(ECX, ECX); |
| 2800 __ j(ZERO, &done); // Shift by 0 is a nop. | 2801 __ j(ZERO, &done); // Shift by 0 is a nop. |
| 2801 __ subl(ESP, Immediate(2 * kWordSize)); | 2802 __ subl(ESP, Immediate(2 * kWordSize)); |
| 2802 __ movq(Address(ESP, 0), left); | 2803 __ movq(Address(ESP, 0), left); |
| 2803 // Deoptimize if shift count is > 31. | 2804 // Deoptimize if shift count is > 31. |
| 2804 // sarl operation masks the count to 5 bits and | 2805 // sarl operation masks the count to 5 bits and |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2840 __ addl(ESP, Immediate(2 * kWordSize)); | 2841 __ addl(ESP, Immediate(2 * kWordSize)); |
| 2841 __ Bind(&done); | 2842 __ Bind(&done); |
| 2842 } | 2843 } |
| 2843 | 2844 |
| 2844 | 2845 |
| 2845 LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const { | 2846 LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const { |
| 2846 const intptr_t kNumInputs = 1; | 2847 const intptr_t kNumInputs = 1; |
| 2847 const intptr_t kNumTemps = 0; | 2848 const intptr_t kNumTemps = 0; |
| 2848 LocationSummary* summary = | 2849 LocationSummary* summary = |
| 2849 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2850 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2850 summary->set_in(0, Location::RequiresXmmRegister()); | 2851 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2851 summary->set_out(Location::SameAsFirstInput()); | 2852 summary->set_out(Location::SameAsFirstInput()); |
| 2852 return summary; | 2853 return summary; |
| 2853 } | 2854 } |
| 2854 | 2855 |
| 2855 | 2856 |
| 2856 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2857 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2857 ASSERT(op_kind() == Token::kBIT_NOT); | 2858 ASSERT(op_kind() == Token::kBIT_NOT); |
| 2858 XmmRegister value = locs()->in(0).xmm_reg(); | 2859 XmmRegister value = locs()->in(0).fpu_reg(); |
| 2859 ASSERT(value == locs()->out().xmm_reg()); | 2860 ASSERT(value == locs()->out().fpu_reg()); |
| 2860 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 2861 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. |
| 2861 __ pxor(value, XMM0); | 2862 __ pxor(value, XMM0); |
| 2862 } | 2863 } |
| 2863 | 2864 |
| 2864 | 2865 |
| 2866 LocationSummary* ThrowInstr::MakeLocationSummary() const { |
| 2867 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 2868 } |
| 2869 |
| 2870 |
| 2871 |
| 2872 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2873 compiler->GenerateCallRuntime(token_pos(), |
| 2874 kThrowRuntimeEntry, |
| 2875 locs()); |
| 2876 __ int3(); |
| 2877 } |
| 2878 |
| 2879 |
| 2880 LocationSummary* ReThrowInstr::MakeLocationSummary() const { |
| 2881 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 2882 } |
| 2883 |
| 2884 |
| 2885 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2886 compiler->GenerateCallRuntime(token_pos(), |
| 2887 kReThrowRuntimeEntry, |
| 2888 locs()); |
| 2889 __ int3(); |
| 2890 } |
| 2891 |
| 2892 |
| 2893 LocationSummary* GotoInstr::MakeLocationSummary() const { |
| 2894 return new LocationSummary(0, 0, LocationSummary::kNoCall); |
| 2895 } |
| 2896 |
| 2897 |
| 2898 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2899 // Add deoptimization descriptor for deoptimizing instructions |
| 2900 // that may be inserted before this instruction. |
| 2901 if (!compiler->is_optimizing()) { |
| 2902 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
| 2903 GetDeoptId(), |
| 2904 0); // No token position. |
| 2905 } |
| 2906 |
| 2907 if (HasParallelMove()) { |
| 2908 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 2909 } |
| 2910 |
| 2911 // We can fall through if the successor is the next block in the list. |
| 2912 // Otherwise, we need a jump. |
| 2913 if (!compiler->IsNextBlock(successor())) { |
| 2914 __ jmp(compiler->GetBlockLabel(successor())); |
| 2915 } |
| 2916 } |
| 2917 |
| 2918 |
| 2919 static Condition NegateCondition(Condition condition) { |
| 2920 switch (condition) { |
| 2921 case EQUAL: return NOT_EQUAL; |
| 2922 case NOT_EQUAL: return EQUAL; |
| 2923 case LESS: return GREATER_EQUAL; |
| 2924 case LESS_EQUAL: return GREATER; |
| 2925 case GREATER: return LESS_EQUAL; |
| 2926 case GREATER_EQUAL: return LESS; |
| 2927 case BELOW: return ABOVE_EQUAL; |
| 2928 case BELOW_EQUAL: return ABOVE; |
| 2929 case ABOVE: return BELOW_EQUAL; |
| 2930 case ABOVE_EQUAL: return BELOW; |
| 2931 default: |
| 2932 OS::Print("Error %d\n", condition); |
| 2933 UNIMPLEMENTED(); |
| 2934 return EQUAL; |
| 2935 } |
| 2936 } |
| 2937 |
| 2938 |
| 2939 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, |
| 2940 bool value) { |
| 2941 if (value && compiler->IsNextBlock(false_successor())) { |
| 2942 __ jmp(compiler->GetBlockLabel(true_successor())); |
| 2943 } else if (!value && compiler->IsNextBlock(true_successor())) { |
| 2944 __ jmp(compiler->GetBlockLabel(false_successor())); |
| 2945 } |
| 2946 } |
| 2947 |
| 2948 |
| 2949 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 2950 Condition true_condition) { |
| 2951 if (compiler->IsNextBlock(false_successor())) { |
| 2952 // If the next block is the false successor we will fall through to it. |
| 2953 __ j(true_condition, compiler->GetBlockLabel(true_successor())); |
| 2954 } else { |
| 2955 // If the next block is the true successor we negate comparison and fall |
| 2956 // through to it. |
| 2957 ASSERT(compiler->IsNextBlock(true_successor())); |
| 2958 Condition false_condition = NegateCondition(true_condition); |
| 2959 __ j(false_condition, compiler->GetBlockLabel(false_successor())); |
| 2960 } |
| 2961 } |
| 2962 |
| 2963 |
| 2964 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { |
| 2965 return LocationSummary::Make(0, |
| 2966 Location::RequiresRegister(), |
| 2967 LocationSummary::kNoCall); |
| 2968 } |
| 2969 |
| 2970 |
| 2971 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2972 __ MoveRegister(locs()->out().reg(), CTX); |
| 2973 } |
| 2974 |
| 2975 |
| 2976 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { |
| 2977 const intptr_t kNumInputs = 2; |
| 2978 const intptr_t kNumTemps = 0; |
| 2979 LocationSummary* locs = |
| 2980 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2981 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 2982 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 2983 locs->set_out(Location::RequiresRegister()); |
| 2984 return locs; |
| 2985 } |
| 2986 |
| 2987 |
| 2988 // Special code for numbers (compare values instead of references.) |
| 2989 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2990 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 2991 Location left = locs()->in(0); |
| 2992 Location right = locs()->in(1); |
| 2993 if (left.IsConstant() && right.IsConstant()) { |
| 2994 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 2995 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 2996 left.constant().raw() == right.constant().raw() : |
| 2997 left.constant().raw() != right.constant().raw(); |
| 2998 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False()); |
| 2999 return; |
| 3000 } |
| 3001 if (left.IsConstant()) { |
| 3002 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 3003 left.constant(), |
| 3004 needs_number_check()); |
| 3005 } else if (right.IsConstant()) { |
| 3006 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 3007 right.constant(), |
| 3008 needs_number_check()); |
| 3009 } else { |
| 3010 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 3011 right.reg(), |
| 3012 needs_number_check()); |
| 3013 } |
| 3014 |
| 3015 Register result = locs()->out().reg(); |
| 3016 Label load_true, done; |
| 3017 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 3018 __ j(true_condition, &load_true, Assembler::kNearJump); |
| 3019 __ LoadObject(result, Bool::False()); |
| 3020 __ jmp(&done, Assembler::kNearJump); |
| 3021 __ Bind(&load_true); |
| 3022 __ LoadObject(result, Bool::True()); |
| 3023 __ Bind(&done); |
| 3024 } |
| 3025 |
| 3026 |
| 3027 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3028 BranchInstr* branch) { |
| 3029 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 3030 Location left = locs()->in(0); |
| 3031 Location right = locs()->in(1); |
| 3032 if (left.IsConstant() && right.IsConstant()) { |
| 3033 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 3034 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 3035 left.constant().raw() == right.constant().raw() : |
| 3036 left.constant().raw() != right.constant().raw(); |
| 3037 branch->EmitBranchOnValue(compiler, result); |
| 3038 return; |
| 3039 } |
| 3040 if (left.IsConstant()) { |
| 3041 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 3042 left.constant(), |
| 3043 needs_number_check()); |
| 3044 } else if (right.IsConstant()) { |
| 3045 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 3046 right.constant(), |
| 3047 needs_number_check()); |
| 3048 } else { |
| 3049 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 3050 right.reg(), |
| 3051 needs_number_check()); |
| 3052 } |
| 3053 |
| 3054 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 3055 branch->EmitBranchOnCondition(compiler, true_condition); |
| 3056 } |
| 3057 |
| 3058 |
| 3059 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3060 // The arguments to the stub include the closure, as does the arguments |
| 3061 // descriptor. |
| 3062 Register temp_reg = locs()->temp(0).reg(); |
| 3063 int argument_count = ArgumentCount(); |
| 3064 const Array& arguments_descriptor = |
| 3065 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
| 3066 argument_names())); |
| 3067 __ LoadObject(temp_reg, arguments_descriptor); |
| 3068 compiler->GenerateDartCall(deopt_id(), |
| 3069 token_pos(), |
| 3070 &StubCode::CallClosureFunctionLabel(), |
| 3071 PcDescriptors::kOther, |
| 3072 locs()); |
| 3073 __ Drop(argument_count); |
| 3074 } |
| 3075 |
| 3076 |
| 3077 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
| 3078 return LocationSummary::Make(1, |
| 3079 Location::RequiresRegister(), |
| 3080 LocationSummary::kNoCall); |
| 3081 } |
| 3082 |
| 3083 |
| 3084 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3085 Register value = locs()->in(0).reg(); |
| 3086 Register result = locs()->out().reg(); |
| 3087 |
| 3088 Label done; |
| 3089 __ LoadObject(result, Bool::True()); |
| 3090 __ CompareRegisters(result, value); |
| 3091 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 3092 __ LoadObject(result, Bool::False()); |
| 3093 __ Bind(&done); |
| 3094 } |
| 3095 |
| 3096 |
| 3097 LocationSummary* ChainContextInstr::MakeLocationSummary() const { |
| 3098 return LocationSummary::Make(1, |
| 3099 Location::NoLocation(), |
| 3100 LocationSummary::kNoCall); |
| 3101 } |
| 3102 |
| 3103 |
| 3104 void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3105 Register context_value = locs()->in(0).reg(); |
| 3106 |
| 3107 // Chain the new context in context_value to its parent in CTX. |
| 3108 __ StoreIntoObject(context_value, |
| 3109 FieldAddress(context_value, Context::parent_offset()), |
| 3110 CTX); |
| 3111 // Set new context as current context. |
| 3112 __ MoveRegister(CTX, context_value); |
| 3113 } |
| 3114 |
| 3115 |
| 3116 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const { |
| 3117 const intptr_t kNumInputs = 2; |
| 3118 const intptr_t kNumTemps = 0; |
| 3119 LocationSummary* locs = |
| 3120 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3121 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 3122 : Location::RequiresRegister()); |
| 3123 locs->set_in(1, Location::RequiresRegister()); |
| 3124 return locs; |
| 3125 } |
| 3126 |
| 3127 |
| 3128 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3129 Register value_reg = locs()->in(0).reg(); |
| 3130 Register dest_reg = locs()->in(1).reg(); |
| 3131 |
| 3132 if (value()->NeedsStoreBuffer()) { |
| 3133 __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()), |
| 3134 value_reg); |
| 3135 } else { |
| 3136 __ StoreIntoObjectNoBarrier( |
| 3137 dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg); |
| 3138 } |
| 3139 } |
| 3140 |
| 3141 |
| 3142 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { |
| 3143 return MakeCallSummary(); |
| 3144 } |
| 3145 |
| 3146 |
| 3147 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3148 const Class& cls = Class::ZoneHandle(constructor().Owner()); |
| 3149 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 3150 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 3151 compiler->GenerateCall(token_pos(), |
| 3152 &label, |
| 3153 PcDescriptors::kOther, |
| 3154 locs()); |
| 3155 __ Drop(ArgumentCount()); // Discard arguments. |
| 3156 } |
| 3157 |
| 3158 |
| 3159 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { |
| 3160 return MakeCallSummary(); |
| 3161 } |
| 3162 |
| 3163 |
| 3164 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3165 const Function& closure_function = function(); |
| 3166 ASSERT(!closure_function.IsImplicitStaticClosureFunction()); |
| 3167 const Code& stub = Code::Handle( |
| 3168 StubCode::GetAllocationStubForClosure(closure_function)); |
| 3169 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); |
| 3170 compiler->GenerateCall(token_pos(), |
| 3171 &label, |
| 3172 PcDescriptors::kOther, |
| 3173 locs()); |
| 3174 __ Drop(2); // Discard type arguments and receiver. |
| 3175 } |
| 3176 |
| 2865 } // namespace dart | 3177 } // namespace dart |
| 2866 | 3178 |
| 2867 #undef __ | 3179 #undef __ |
| 2868 | 3180 |
| 2869 #endif // defined TARGET_ARCH_X64 | 3181 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |