| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 DECLARE_FLAG(int, optimization_counter_threshold); | 23 DECLARE_FLAG(int, optimization_counter_threshold); |
| 24 DECLARE_FLAG(bool, propagate_ic_data); | 24 DECLARE_FLAG(bool, propagate_ic_data); |
| 25 DECLARE_FLAG(bool, use_osr); | 25 DECLARE_FLAG(bool, use_osr); |
| 26 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); | 26 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| 27 DECLARE_FLAG(bool, use_slow_path); | 27 DECLARE_FLAG(bool, use_slow_path); |
| 28 | 28 |
| 29 // Generic summary for call instructions that have all arguments pushed | 29 // Generic summary for call instructions that have all arguments pushed |
| 30 // on the stack and return the result in a fixed register EAX. | 30 // on the stack and return the result in a fixed register EAX. |
| 31 LocationSummary* Instruction::MakeCallSummary() { | 31 LocationSummary* Instruction::MakeCallSummary() { |
| 32 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); | 32 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); |
| 33 result->set_out(Location::RegisterLocation(EAX)); | 33 result->set_out(0, Location::RegisterLocation(EAX)); |
| 34 return result; | 34 return result; |
| 35 } | 35 } |
| 36 | 36 |
| 37 | 37 |
| 38 LocationSummary* PushArgumentInstr::MakeLocationSummary(bool opt) const { | 38 LocationSummary* PushArgumentInstr::MakeLocationSummary(bool opt) const { |
| 39 const intptr_t kNumInputs = 1; | 39 const intptr_t kNumInputs = 1; |
| 40 const intptr_t kNumTemps= 0; | 40 const intptr_t kNumTemps= 0; |
| 41 LocationSummary* locs = | 41 LocationSummary* locs = |
| 42 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 42 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 43 locs->set_in(0, Location::AnyOrConstant(value())); | 43 locs->set_in(0, Location::AnyOrConstant(value())); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const { | 116 LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const { |
| 117 const intptr_t kNumInputs = 1; | 117 const intptr_t kNumInputs = 1; |
| 118 return LocationSummary::Make(kNumInputs, | 118 return LocationSummary::Make(kNumInputs, |
| 119 Location::SameAsFirstInput(), | 119 Location::SameAsFirstInput(), |
| 120 LocationSummary::kNoCall); | 120 LocationSummary::kNoCall); |
| 121 } | 121 } |
| 122 | 122 |
| 123 | 123 |
| 124 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 124 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 125 Register value = locs()->in(0).reg(); | 125 Register value = locs()->in(0).reg(); |
| 126 Register result = locs()->out().reg(); | 126 Register result = locs()->out(0).reg(); |
| 127 ASSERT(result == value); // Assert that register assignment is correct. | 127 ASSERT(result == value); // Assert that register assignment is correct. |
| 128 __ movl(Address(EBP, local().index() * kWordSize), value); | 128 __ movl(Address(EBP, local().index() * kWordSize), value); |
| 129 } | 129 } |
| 130 | 130 |
| 131 | 131 |
| 132 LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const { | 132 LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const { |
| 133 const intptr_t kNumInputs = 0; | 133 const intptr_t kNumInputs = 0; |
| 134 return LocationSummary::Make(kNumInputs, | 134 return LocationSummary::Make(kNumInputs, |
| 135 Location::RequiresRegister(), | 135 Location::RequiresRegister(), |
| 136 LocationSummary::kNoCall); | 136 LocationSummary::kNoCall); |
| 137 } | 137 } |
| 138 | 138 |
| 139 | 139 |
| 140 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 140 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 141 // The register allocator drops constant definitions that have no uses. | 141 // The register allocator drops constant definitions that have no uses. |
| 142 if (!locs()->out().IsInvalid()) { | 142 if (!locs()->out(0).IsInvalid()) { |
| 143 Register result = locs()->out().reg(); | 143 Register result = locs()->out(0).reg(); |
| 144 __ LoadObjectSafely(result, value()); | 144 __ LoadObjectSafely(result, value()); |
| 145 } | 145 } |
| 146 } | 146 } |
| 147 | 147 |
| 148 | 148 |
| 149 LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const { | 149 LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const { |
| 150 const intptr_t kNumInputs = 3; | 150 const intptr_t kNumInputs = 3; |
| 151 const intptr_t kNumTemps = 0; | 151 const intptr_t kNumTemps = 0; |
| 152 LocationSummary* summary = | 152 LocationSummary* summary = |
| 153 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 153 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 154 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. | 154 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. |
| 155 summary->set_in(1, Location::RegisterLocation(ECX)); // Instantiator. | 155 summary->set_in(1, Location::RegisterLocation(ECX)); // Instantiator. |
| 156 summary->set_in(2, Location::RegisterLocation(EDX)); // Type arguments. | 156 summary->set_in(2, Location::RegisterLocation(EDX)); // Type arguments. |
| 157 summary->set_out(Location::RegisterLocation(EAX)); | 157 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 158 return summary; | 158 return summary; |
| 159 } | 159 } |
| 160 | 160 |
| 161 | 161 |
| 162 LocationSummary* AssertBooleanInstr::MakeLocationSummary(bool opt) const { | 162 LocationSummary* AssertBooleanInstr::MakeLocationSummary(bool opt) const { |
| 163 const intptr_t kNumInputs = 1; | 163 const intptr_t kNumInputs = 1; |
| 164 const intptr_t kNumTemps = 0; | 164 const intptr_t kNumTemps = 0; |
| 165 LocationSummary* locs = | 165 LocationSummary* locs = |
| 166 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 166 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 167 locs->set_in(0, Location::RegisterLocation(EAX)); | 167 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 168 locs->set_out(Location::RegisterLocation(EAX)); | 168 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 169 return locs; | 169 return locs; |
| 170 } | 170 } |
| 171 | 171 |
| 172 | 172 |
| 173 static void EmitAssertBoolean(Register reg, | 173 static void EmitAssertBoolean(Register reg, |
| 174 intptr_t token_pos, | 174 intptr_t token_pos, |
| 175 intptr_t deopt_id, | 175 intptr_t deopt_id, |
| 176 LocationSummary* locs, | 176 LocationSummary* locs, |
| 177 FlowGraphCompiler* compiler) { | 177 FlowGraphCompiler* compiler) { |
| 178 // Check that the type of the value is allowed in conditional context. | 178 // Check that the type of the value is allowed in conditional context. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 191 1, | 191 1, |
| 192 locs); | 192 locs); |
| 193 // We should never return here. | 193 // We should never return here. |
| 194 __ int3(); | 194 __ int3(); |
| 195 __ Bind(&done); | 195 __ Bind(&done); |
| 196 } | 196 } |
| 197 | 197 |
| 198 | 198 |
| 199 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 199 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 200 Register obj = locs()->in(0).reg(); | 200 Register obj = locs()->in(0).reg(); |
| 201 Register result = locs()->out().reg(); | 201 Register result = locs()->out(0).reg(); |
| 202 | 202 |
| 203 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 203 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 204 ASSERT(obj == result); | 204 ASSERT(obj == result); |
| 205 } | 205 } |
| 206 | 206 |
| 207 | 207 |
| 208 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 208 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 209 switch (kind) { | 209 switch (kind) { |
| 210 case Token::kEQ: return EQUAL; | 210 case Token::kEQ: return EQUAL; |
| 211 case Token::kNE: return NOT_EQUAL; | 211 case Token::kNE: return NOT_EQUAL; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 222 | 222 |
| 223 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { | 223 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { |
| 224 const intptr_t kNumInputs = 2; | 224 const intptr_t kNumInputs = 2; |
| 225 if (operation_cid() == kMintCid) { | 225 if (operation_cid() == kMintCid) { |
| 226 const intptr_t kNumTemps = 1; | 226 const intptr_t kNumTemps = 1; |
| 227 LocationSummary* locs = | 227 LocationSummary* locs = |
| 228 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 228 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 229 locs->set_in(0, Location::RequiresFpuRegister()); | 229 locs->set_in(0, Location::RequiresFpuRegister()); |
| 230 locs->set_in(1, Location::RequiresFpuRegister()); | 230 locs->set_in(1, Location::RequiresFpuRegister()); |
| 231 locs->set_temp(0, Location::RequiresRegister()); | 231 locs->set_temp(0, Location::RequiresRegister()); |
| 232 locs->set_out(Location::RequiresRegister()); | 232 locs->set_out(0, Location::RequiresRegister()); |
| 233 return locs; | 233 return locs; |
| 234 } | 234 } |
| 235 if (operation_cid() == kDoubleCid) { | 235 if (operation_cid() == kDoubleCid) { |
| 236 const intptr_t kNumTemps = 0; | 236 const intptr_t kNumTemps = 0; |
| 237 LocationSummary* locs = | 237 LocationSummary* locs = |
| 238 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 238 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 239 locs->set_in(0, Location::RequiresFpuRegister()); | 239 locs->set_in(0, Location::RequiresFpuRegister()); |
| 240 locs->set_in(1, Location::RequiresFpuRegister()); | 240 locs->set_in(1, Location::RequiresFpuRegister()); |
| 241 locs->set_out(Location::RequiresRegister()); | 241 locs->set_out(0, Location::RequiresRegister()); |
| 242 return locs; | 242 return locs; |
| 243 } | 243 } |
| 244 if (operation_cid() == kSmiCid) { | 244 if (operation_cid() == kSmiCid) { |
| 245 const intptr_t kNumTemps = 0; | 245 const intptr_t kNumTemps = 0; |
| 246 LocationSummary* locs = | 246 LocationSummary* locs = |
| 247 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 247 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 248 locs->set_in(0, Location::RegisterOrConstant(left())); | 248 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 249 // Only one input can be a constant operand. The case of two constant | 249 // Only one input can be a constant operand. The case of two constant |
| 250 // operands should be handled by constant propagation. | 250 // operands should be handled by constant propagation. |
| 251 // Only right can be a stack slot. | 251 // Only right can be a stack slot. |
| 252 locs->set_in(1, locs->in(0).IsConstant() | 252 locs->set_in(1, locs->in(0).IsConstant() |
| 253 ? Location::RequiresRegister() | 253 ? Location::RequiresRegister() |
| 254 : Location::RegisterOrConstant(right())); | 254 : Location::RegisterOrConstant(right())); |
| 255 locs->set_out(Location::RequiresRegister()); | 255 locs->set_out(0, Location::RequiresRegister()); |
| 256 return locs; | 256 return locs; |
| 257 } | 257 } |
| 258 UNREACHABLE(); | 258 UNREACHABLE(); |
| 259 return NULL; | 259 return NULL; |
| 260 } | 260 } |
| 261 | 261 |
| 262 | 262 |
| 263 static void LoadValueCid(FlowGraphCompiler* compiler, | 263 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 264 Register value_cid_reg, | 264 Register value_cid_reg, |
| 265 Register value_reg, | 265 Register value_reg, |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 | 512 |
| 513 | 513 |
| 514 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 514 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 515 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 515 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 516 | 516 |
| 517 Label is_true, is_false; | 517 Label is_true, is_false; |
| 518 BranchLabels labels = { &is_true, &is_false, &is_false }; | 518 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 519 Condition true_condition = EmitComparisonCode(compiler, labels); | 519 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 520 EmitBranchOnCondition(compiler, true_condition, labels); | 520 EmitBranchOnCondition(compiler, true_condition, labels); |
| 521 | 521 |
| 522 Register result = locs()->out().reg(); | 522 Register result = locs()->out(0).reg(); |
| 523 Label done; | 523 Label done; |
| 524 __ Bind(&is_false); | 524 __ Bind(&is_false); |
| 525 __ LoadObject(result, Bool::False()); | 525 __ LoadObject(result, Bool::False()); |
| 526 __ jmp(&done, Assembler::kNearJump); | 526 __ jmp(&done, Assembler::kNearJump); |
| 527 __ Bind(&is_true); | 527 __ Bind(&is_true); |
| 528 __ LoadObject(result, Bool::True()); | 528 __ LoadObject(result, Bool::True()); |
| 529 __ Bind(&done); | 529 __ Bind(&done); |
| 530 } | 530 } |
| 531 | 531 |
| 532 | 532 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 const intptr_t kNumInputs = 2; | 588 const intptr_t kNumInputs = 2; |
| 589 const intptr_t kNumTemps = 0; | 589 const intptr_t kNumTemps = 0; |
| 590 if (operation_cid() == kMintCid) { | 590 if (operation_cid() == kMintCid) { |
| 591 const intptr_t kNumTemps = 2; | 591 const intptr_t kNumTemps = 2; |
| 592 LocationSummary* locs = | 592 LocationSummary* locs = |
| 593 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 593 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 594 locs->set_in(0, Location::RequiresFpuRegister()); | 594 locs->set_in(0, Location::RequiresFpuRegister()); |
| 595 locs->set_in(1, Location::RequiresFpuRegister()); | 595 locs->set_in(1, Location::RequiresFpuRegister()); |
| 596 locs->set_temp(0, Location::RequiresRegister()); | 596 locs->set_temp(0, Location::RequiresRegister()); |
| 597 locs->set_temp(1, Location::RequiresRegister()); | 597 locs->set_temp(1, Location::RequiresRegister()); |
| 598 locs->set_out(Location::RequiresRegister()); | 598 locs->set_out(0, Location::RequiresRegister()); |
| 599 return locs; | 599 return locs; |
| 600 } | 600 } |
| 601 if (operation_cid() == kDoubleCid) { | 601 if (operation_cid() == kDoubleCid) { |
| 602 LocationSummary* summary = | 602 LocationSummary* summary = |
| 603 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 603 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 604 summary->set_in(0, Location::RequiresFpuRegister()); | 604 summary->set_in(0, Location::RequiresFpuRegister()); |
| 605 summary->set_in(1, Location::RequiresFpuRegister()); | 605 summary->set_in(1, Location::RequiresFpuRegister()); |
| 606 summary->set_out(Location::RequiresRegister()); | 606 summary->set_out(0, Location::RequiresRegister()); |
| 607 return summary; | 607 return summary; |
| 608 } | 608 } |
| 609 ASSERT(operation_cid() == kSmiCid); | 609 ASSERT(operation_cid() == kSmiCid); |
| 610 LocationSummary* summary = | 610 LocationSummary* summary = |
| 611 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 611 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 612 summary->set_in(0, Location::RegisterOrConstant(left())); | 612 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 613 // Only one input can be a constant operand. The case of two constant | 613 // Only one input can be a constant operand. The case of two constant |
| 614 // operands should be handled by constant propagation. | 614 // operands should be handled by constant propagation. |
| 615 summary->set_in(1, summary->in(0).IsConstant() | 615 summary->set_in(1, summary->in(0).IsConstant() |
| 616 ? Location::RequiresRegister() | 616 ? Location::RequiresRegister() |
| 617 : Location::RegisterOrConstant(right())); | 617 : Location::RegisterOrConstant(right())); |
| 618 summary->set_out(Location::RequiresRegister()); | 618 summary->set_out(0, Location::RequiresRegister()); |
| 619 return summary; | 619 return summary; |
| 620 } | 620 } |
| 621 | 621 |
| 622 | 622 |
| 623 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 623 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 624 BranchLabels labels) { | 624 BranchLabels labels) { |
| 625 if (operation_cid() == kSmiCid) { | 625 if (operation_cid() == kSmiCid) { |
| 626 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 626 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 627 } else if (operation_cid() == kMintCid) { | 627 } else if (operation_cid() == kMintCid) { |
| 628 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); | 628 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); |
| 629 } else { | 629 } else { |
| 630 ASSERT(operation_cid() == kDoubleCid); | 630 ASSERT(operation_cid() == kDoubleCid); |
| 631 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 631 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 632 } | 632 } |
| 633 } | 633 } |
| 634 | 634 |
| 635 | 635 |
| 636 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 636 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 637 Label is_true, is_false; | 637 Label is_true, is_false; |
| 638 BranchLabels labels = { &is_true, &is_false, &is_false }; | 638 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 639 Condition true_condition = EmitComparisonCode(compiler, labels); | 639 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 640 EmitBranchOnCondition(compiler, true_condition, labels); | 640 EmitBranchOnCondition(compiler, true_condition, labels); |
| 641 | 641 |
| 642 Register result = locs()->out().reg(); | 642 Register result = locs()->out(0).reg(); |
| 643 Label done; | 643 Label done; |
| 644 __ Bind(&is_false); | 644 __ Bind(&is_false); |
| 645 __ LoadObject(result, Bool::False()); | 645 __ LoadObject(result, Bool::False()); |
| 646 __ jmp(&done, Assembler::kNearJump); | 646 __ jmp(&done, Assembler::kNearJump); |
| 647 __ Bind(&is_true); | 647 __ Bind(&is_true); |
| 648 __ LoadObject(result, Bool::True()); | 648 __ LoadObject(result, Bool::True()); |
| 649 __ Bind(&done); | 649 __ Bind(&done); |
| 650 } | 650 } |
| 651 | 651 |
| 652 | 652 |
| 653 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 653 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 654 BranchInstr* branch) { | 654 BranchInstr* branch) { |
| 655 BranchLabels labels = compiler->CreateBranchLabels(branch); | 655 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 656 Condition true_condition = EmitComparisonCode(compiler, labels); | 656 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 657 EmitBranchOnCondition(compiler, true_condition, labels); | 657 EmitBranchOnCondition(compiler, true_condition, labels); |
| 658 } | 658 } |
| 659 | 659 |
| 660 | 660 |
| 661 LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const { | 661 LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const { |
| 662 const intptr_t kNumInputs = 0; | 662 const intptr_t kNumInputs = 0; |
| 663 const intptr_t kNumTemps = 3; | 663 const intptr_t kNumTemps = 3; |
| 664 LocationSummary* locs = | 664 LocationSummary* locs = |
| 665 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 665 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 666 locs->set_temp(0, Location::RegisterLocation(EAX)); | 666 locs->set_temp(0, Location::RegisterLocation(EAX)); |
| 667 locs->set_temp(1, Location::RegisterLocation(ECX)); | 667 locs->set_temp(1, Location::RegisterLocation(ECX)); |
| 668 locs->set_temp(2, Location::RegisterLocation(EDX)); | 668 locs->set_temp(2, Location::RegisterLocation(EDX)); |
| 669 locs->set_out(Location::RegisterLocation(EAX)); | 669 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 670 return locs; | 670 return locs; |
| 671 } | 671 } |
| 672 | 672 |
| 673 | 673 |
| 674 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 674 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 675 ASSERT(locs()->temp(0).reg() == EAX); | 675 ASSERT(locs()->temp(0).reg() == EAX); |
| 676 ASSERT(locs()->temp(1).reg() == ECX); | 676 ASSERT(locs()->temp(1).reg() == ECX); |
| 677 ASSERT(locs()->temp(2).reg() == EDX); | 677 ASSERT(locs()->temp(2).reg() == EDX); |
| 678 Register result = locs()->out().reg(); | 678 Register result = locs()->out(0).reg(); |
| 679 | 679 |
| 680 // Push the result place holder initialized to NULL. | 680 // Push the result place holder initialized to NULL. |
| 681 __ PushObject(Object::ZoneHandle()); | 681 __ PushObject(Object::ZoneHandle()); |
| 682 // Pass a pointer to the first argument in EAX. | 682 // Pass a pointer to the first argument in EAX. |
| 683 if (!function().HasOptionalParameters()) { | 683 if (!function().HasOptionalParameters()) { |
| 684 __ leal(EAX, Address(EBP, (kParamEndSlotFromFp + | 684 __ leal(EAX, Address(EBP, (kParamEndSlotFromFp + |
| 685 function().NumParameters()) * kWordSize)); | 685 function().NumParameters()) * kWordSize)); |
| 686 } else { | 686 } else { |
| 687 __ leal(EAX, Address(EBP, kFirstLocalSlotFromFp * kWordSize)); | 687 __ leal(EAX, Address(EBP, kFirstLocalSlotFromFp * kWordSize)); |
| 688 } | 688 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 716 const intptr_t kNumInputs = 1; | 716 const intptr_t kNumInputs = 1; |
| 717 // TODO(fschneider): Allow immediate operands for the char code. | 717 // TODO(fschneider): Allow immediate operands for the char code. |
| 718 return LocationSummary::Make(kNumInputs, | 718 return LocationSummary::Make(kNumInputs, |
| 719 Location::RequiresRegister(), | 719 Location::RequiresRegister(), |
| 720 LocationSummary::kNoCall); | 720 LocationSummary::kNoCall); |
| 721 } | 721 } |
| 722 | 722 |
| 723 | 723 |
| 724 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 724 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 725 Register char_code = locs()->in(0).reg(); | 725 Register char_code = locs()->in(0).reg(); |
| 726 Register result = locs()->out().reg(); | 726 Register result = locs()->out(0).reg(); |
| 727 __ movl(result, | 727 __ movl(result, |
| 728 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); | 728 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); |
| 729 __ movl(result, Address(result, | 729 __ movl(result, Address(result, |
| 730 char_code, | 730 char_code, |
| 731 TIMES_HALF_WORD_SIZE, // Char code is a smi. | 731 TIMES_HALF_WORD_SIZE, // Char code is a smi. |
| 732 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 732 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
| 733 } | 733 } |
| 734 | 734 |
| 735 | 735 |
| 736 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(bool opt) const { | 736 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(bool opt) const { |
| 737 const intptr_t kNumInputs = 1; | 737 const intptr_t kNumInputs = 1; |
| 738 return LocationSummary::Make(kNumInputs, | 738 return LocationSummary::Make(kNumInputs, |
| 739 Location::RequiresRegister(), | 739 Location::RequiresRegister(), |
| 740 LocationSummary::kNoCall); | 740 LocationSummary::kNoCall); |
| 741 } | 741 } |
| 742 | 742 |
| 743 | 743 |
| 744 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 744 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 745 ASSERT(cid_ == kOneByteStringCid); | 745 ASSERT(cid_ == kOneByteStringCid); |
| 746 Register str = locs()->in(0).reg(); | 746 Register str = locs()->in(0).reg(); |
| 747 Register result = locs()->out().reg(); | 747 Register result = locs()->out(0).reg(); |
| 748 Label is_one, done; | 748 Label is_one, done; |
| 749 __ movl(result, FieldAddress(str, String::length_offset())); | 749 __ movl(result, FieldAddress(str, String::length_offset())); |
| 750 __ cmpl(result, Immediate(Smi::RawValue(1))); | 750 __ cmpl(result, Immediate(Smi::RawValue(1))); |
| 751 __ j(EQUAL, &is_one, Assembler::kNearJump); | 751 __ j(EQUAL, &is_one, Assembler::kNearJump); |
| 752 __ movl(result, Immediate(Smi::RawValue(-1))); | 752 __ movl(result, Immediate(Smi::RawValue(-1))); |
| 753 __ jmp(&done); | 753 __ jmp(&done); |
| 754 __ Bind(&is_one); | 754 __ Bind(&is_one); |
| 755 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); | 755 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); |
| 756 __ SmiTag(result); | 756 __ SmiTag(result); |
| 757 __ Bind(&done); | 757 __ Bind(&done); |
| 758 } | 758 } |
| 759 | 759 |
| 760 | 760 |
| 761 LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const { | 761 LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const { |
| 762 const intptr_t kNumInputs = 1; | 762 const intptr_t kNumInputs = 1; |
| 763 const intptr_t kNumTemps = 0; | 763 const intptr_t kNumTemps = 0; |
| 764 LocationSummary* summary = | 764 LocationSummary* summary = |
| 765 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 765 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 766 summary->set_in(0, Location::RegisterLocation(EAX)); | 766 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 767 summary->set_out(Location::RegisterLocation(EAX)); | 767 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 768 return summary; | 768 return summary; |
| 769 } | 769 } |
| 770 | 770 |
| 771 | 771 |
| 772 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 772 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 773 Register array = locs()->in(0).reg(); | 773 Register array = locs()->in(0).reg(); |
| 774 __ pushl(array); | 774 __ pushl(array); |
| 775 const int kNumberOfArguments = 1; | 775 const int kNumberOfArguments = 1; |
| 776 const Array& kNoArgumentNames = Object::null_array(); | 776 const Array& kNoArgumentNames = Object::null_array(); |
| 777 compiler->GenerateStaticCall(deopt_id(), | 777 compiler->GenerateStaticCall(deopt_id(), |
| 778 token_pos(), | 778 token_pos(), |
| 779 CallFunction(), | 779 CallFunction(), |
| 780 kNumberOfArguments, | 780 kNumberOfArguments, |
| 781 kNoArgumentNames, | 781 kNoArgumentNames, |
| 782 locs()); | 782 locs()); |
| 783 ASSERT(locs()->out().reg() == EAX); | 783 ASSERT(locs()->out(0).reg() == EAX); |
| 784 } | 784 } |
| 785 | 785 |
| 786 | 786 |
| 787 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const { | 787 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const { |
| 788 const intptr_t kNumInputs = 1; | 788 const intptr_t kNumInputs = 1; |
| 789 return LocationSummary::Make(kNumInputs, | 789 return LocationSummary::Make(kNumInputs, |
| 790 Location::RequiresRegister(), | 790 Location::RequiresRegister(), |
| 791 LocationSummary::kNoCall); | 791 LocationSummary::kNoCall); |
| 792 } | 792 } |
| 793 | 793 |
| 794 | 794 |
| 795 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 795 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 796 Register object = locs()->in(0).reg(); | 796 Register object = locs()->in(0).reg(); |
| 797 Register result = locs()->out().reg(); | 797 Register result = locs()->out(0).reg(); |
| 798 __ movl(result, FieldAddress(object, offset())); | 798 __ movl(result, FieldAddress(object, offset())); |
| 799 } | 799 } |
| 800 | 800 |
| 801 | 801 |
| 802 LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const { | 802 LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const { |
| 803 const intptr_t kNumInputs = 1; | 803 const intptr_t kNumInputs = 1; |
| 804 return LocationSummary::Make(kNumInputs, | 804 return LocationSummary::Make(kNumInputs, |
| 805 Location::RequiresRegister(), | 805 Location::RequiresRegister(), |
| 806 LocationSummary::kNoCall); | 806 LocationSummary::kNoCall); |
| 807 } | 807 } |
| 808 | 808 |
| 809 | 809 |
| 810 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 810 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 811 Register object = locs()->in(0).reg(); | 811 Register object = locs()->in(0).reg(); |
| 812 Register result = locs()->out().reg(); | 812 Register result = locs()->out(0).reg(); |
| 813 Label load, done; | 813 Label load, done; |
| 814 __ testl(object, Immediate(kSmiTagMask)); | 814 __ testl(object, Immediate(kSmiTagMask)); |
| 815 __ j(NOT_ZERO, &load, Assembler::kNearJump); | 815 __ j(NOT_ZERO, &load, Assembler::kNearJump); |
| 816 __ movl(result, Immediate(Smi::RawValue(kSmiCid))); | 816 __ movl(result, Immediate(Smi::RawValue(kSmiCid))); |
| 817 __ jmp(&done); | 817 __ jmp(&done); |
| 818 __ Bind(&load); | 818 __ Bind(&load); |
| 819 __ LoadClassId(result, object); | 819 __ LoadClassId(result, object); |
| 820 __ SmiTag(result); | 820 __ SmiTag(result); |
| 821 __ Bind(&done); | 821 __ Bind(&done); |
| 822 } | 822 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 912 // The index is either untagged (element size == 1) or a smi (for all | 912 // The index is either untagged (element size == 1) or a smi (for all |
| 913 // element sizes > 1). | 913 // element sizes > 1). |
| 914 locs->set_in(1, (index_scale() == 1) | 914 locs->set_in(1, (index_scale() == 1) |
| 915 ? Location::WritableRegister() | 915 ? Location::WritableRegister() |
| 916 : Location::RequiresRegister()); | 916 : Location::RequiresRegister()); |
| 917 } | 917 } |
| 918 if ((representation() == kUnboxedDouble) || | 918 if ((representation() == kUnboxedDouble) || |
| 919 (representation() == kUnboxedFloat32x4) || | 919 (representation() == kUnboxedFloat32x4) || |
| 920 (representation() == kUnboxedInt32x4) || | 920 (representation() == kUnboxedInt32x4) || |
| 921 (representation() == kUnboxedFloat64x2)) { | 921 (representation() == kUnboxedFloat64x2)) { |
| 922 locs->set_out(Location::RequiresFpuRegister()); | 922 locs->set_out(0, Location::RequiresFpuRegister()); |
| 923 } else { | 923 } else { |
| 924 locs->set_out(Location::RequiresRegister()); | 924 locs->set_out(0, Location::RequiresRegister()); |
| 925 } | 925 } |
| 926 return locs; | 926 return locs; |
| 927 } | 927 } |
| 928 | 928 |
| 929 | 929 |
| 930 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 930 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 931 Register array = locs()->in(0).reg(); | 931 Register array = locs()->in(0).reg(); |
| 932 Location index = locs()->in(1); | 932 Location index = locs()->in(1); |
| 933 | 933 |
| 934 Address element_address(kNoRegister, 0); | 934 Address element_address(kNoRegister, 0); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 946 : FlowGraphCompiler::ElementAddressForIntIndex( | 946 : FlowGraphCompiler::ElementAddressForIntIndex( |
| 947 class_id(), index_scale(), array, | 947 class_id(), index_scale(), array, |
| 948 Smi::Cast(index.constant()).Value()); | 948 Smi::Cast(index.constant()).Value()); |
| 949 } | 949 } |
| 950 | 950 |
| 951 if ((representation() == kUnboxedDouble) || | 951 if ((representation() == kUnboxedDouble) || |
| 952 (representation() == kUnboxedMint) || | 952 (representation() == kUnboxedMint) || |
| 953 (representation() == kUnboxedFloat32x4) || | 953 (representation() == kUnboxedFloat32x4) || |
| 954 (representation() == kUnboxedInt32x4) || | 954 (representation() == kUnboxedInt32x4) || |
| 955 (representation() == kUnboxedFloat64x2)) { | 955 (representation() == kUnboxedFloat64x2)) { |
| 956 XmmRegister result = locs()->out().fpu_reg(); | 956 XmmRegister result = locs()->out(0).fpu_reg(); |
| 957 if ((index_scale() == 1) && index.IsRegister()) { | 957 if ((index_scale() == 1) && index.IsRegister()) { |
| 958 __ SmiUntag(index.reg()); | 958 __ SmiUntag(index.reg()); |
| 959 } | 959 } |
| 960 switch (class_id()) { | 960 switch (class_id()) { |
| 961 case kTypedDataInt32ArrayCid: | 961 case kTypedDataInt32ArrayCid: |
| 962 __ movss(result, element_address); | 962 __ movss(result, element_address); |
| 963 __ pmovsxdq(result, result); | 963 __ pmovsxdq(result, result); |
| 964 break; | 964 break; |
| 965 case kTypedDataUint32ArrayCid: | 965 case kTypedDataUint32ArrayCid: |
| 966 __ xorpd(result, result); | 966 __ xorpd(result, result); |
| 967 __ movss(result, element_address); | 967 __ movss(result, element_address); |
| 968 break; | 968 break; |
| 969 case kTypedDataFloat32ArrayCid: | 969 case kTypedDataFloat32ArrayCid: |
| 970 __ movss(result, element_address); | 970 __ movss(result, element_address); |
| 971 break; | 971 break; |
| 972 case kTypedDataFloat64ArrayCid: | 972 case kTypedDataFloat64ArrayCid: |
| 973 __ movsd(result, element_address); | 973 __ movsd(result, element_address); |
| 974 break; | 974 break; |
| 975 case kTypedDataInt32x4ArrayCid: | 975 case kTypedDataInt32x4ArrayCid: |
| 976 case kTypedDataFloat32x4ArrayCid: | 976 case kTypedDataFloat32x4ArrayCid: |
| 977 case kTypedDataFloat64x2ArrayCid: | 977 case kTypedDataFloat64x2ArrayCid: |
| 978 __ movups(result, element_address); | 978 __ movups(result, element_address); |
| 979 break; | 979 break; |
| 980 } | 980 } |
| 981 return; | 981 return; |
| 982 } | 982 } |
| 983 | 983 |
| 984 Register result = locs()->out().reg(); | 984 Register result = locs()->out(0).reg(); |
| 985 if ((index_scale() == 1) && index.IsRegister()) { | 985 if ((index_scale() == 1) && index.IsRegister()) { |
| 986 __ SmiUntag(index.reg()); | 986 __ SmiUntag(index.reg()); |
| 987 } | 987 } |
| 988 switch (class_id()) { | 988 switch (class_id()) { |
| 989 case kTypedDataInt8ArrayCid: | 989 case kTypedDataInt8ArrayCid: |
| 990 ASSERT(index_scale() == 1); | 990 ASSERT(index_scale() == 1); |
| 991 __ movsxb(result, element_address); | 991 __ movsxb(result, element_address); |
| 992 __ SmiTag(result); | 992 __ SmiTag(result); |
| 993 break; | 993 break; |
| 994 case kTypedDataUint8ArrayCid: | 994 case kTypedDataUint8ArrayCid: |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1601 : instruction_(instruction), cls_(cls) { } | 1601 : instruction_(instruction), cls_(cls) { } |
| 1602 | 1602 |
| 1603 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1603 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1604 __ Comment("StoreInstanceFieldSlowPath"); | 1604 __ Comment("StoreInstanceFieldSlowPath"); |
| 1605 __ Bind(entry_label()); | 1605 __ Bind(entry_label()); |
| 1606 const Code& stub = | 1606 const Code& stub = |
| 1607 Code::Handle(StubCode::GetAllocationStubForClass(cls_)); | 1607 Code::Handle(StubCode::GetAllocationStubForClass(cls_)); |
| 1608 const ExternalLabel label(cls_.ToCString(), stub.EntryPoint()); | 1608 const ExternalLabel label(cls_.ToCString(), stub.EntryPoint()); |
| 1609 | 1609 |
| 1610 LocationSummary* locs = instruction_->locs(); | 1610 LocationSummary* locs = instruction_->locs(); |
| 1611 locs->live_registers()->Remove(locs->out()); | 1611 locs->live_registers()->Remove(locs->out(0)); |
| 1612 compiler->SaveLiveRegisters(locs); | 1612 compiler->SaveLiveRegisters(locs); |
| 1613 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 1613 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 1614 &label, | 1614 &label, |
| 1615 PcDescriptors::kOther, | 1615 PcDescriptors::kOther, |
| 1616 locs); | 1616 locs); |
| 1617 __ MoveRegister(locs->temp(0).reg(), EAX); | 1617 __ MoveRegister(locs->temp(0).reg(), EAX); |
| 1618 compiler->RestoreLiveRegisters(locs); | 1618 compiler->RestoreLiveRegisters(locs); |
| 1619 __ jmp(exit_label()); | 1619 __ jmp(exit_label()); |
| 1620 } | 1620 } |
| 1621 | 1621 |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1881 | 1881 |
| 1882 | 1882 |
| 1883 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const { | 1883 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const { |
| 1884 const intptr_t kNumInputs = 1; | 1884 const intptr_t kNumInputs = 1; |
| 1885 const intptr_t kNumTemps = 0; | 1885 const intptr_t kNumTemps = 0; |
| 1886 LocationSummary* summary = | 1886 LocationSummary* summary = |
| 1887 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1887 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1888 summary->set_in(0, Location::RequiresRegister()); | 1888 summary->set_in(0, Location::RequiresRegister()); |
| 1889 // By specifying same register as input, our simple register allocator can | 1889 // By specifying same register as input, our simple register allocator can |
| 1890 // generate better code. | 1890 // generate better code. |
| 1891 summary->set_out(Location::SameAsFirstInput()); | 1891 summary->set_out(0, Location::SameAsFirstInput()); |
| 1892 return summary; | 1892 return summary; |
| 1893 } | 1893 } |
| 1894 | 1894 |
| 1895 | 1895 |
| 1896 // When the parser is building an implicit static getter for optimization, | 1896 // When the parser is building an implicit static getter for optimization, |
| 1897 // it can generate a function body where deoptimization ids do not line up | 1897 // it can generate a function body where deoptimization ids do not line up |
| 1898 // with the unoptimized code. | 1898 // with the unoptimized code. |
| 1899 // | 1899 // |
| 1900 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 1900 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
| 1901 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1901 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1902 Register field = locs()->in(0).reg(); | 1902 Register field = locs()->in(0).reg(); |
| 1903 Register result = locs()->out().reg(); | 1903 Register result = locs()->out(0).reg(); |
| 1904 __ movl(result, FieldAddress(field, Field::value_offset())); | 1904 __ movl(result, FieldAddress(field, Field::value_offset())); |
| 1905 } | 1905 } |
| 1906 | 1906 |
| 1907 | 1907 |
| 1908 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const { | 1908 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const { |
| 1909 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall); | 1909 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall); |
| 1910 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 1910 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 1911 : Location::RequiresRegister()); | 1911 : Location::RequiresRegister()); |
| 1912 locs->set_temp(0, Location::RequiresRegister()); | 1912 locs->set_temp(0, Location::RequiresRegister()); |
| 1913 return locs; | 1913 return locs; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1930 | 1930 |
| 1931 | 1931 |
| 1932 LocationSummary* InstanceOfInstr::MakeLocationSummary(bool opt) const { | 1932 LocationSummary* InstanceOfInstr::MakeLocationSummary(bool opt) const { |
| 1933 const intptr_t kNumInputs = 3; | 1933 const intptr_t kNumInputs = 3; |
| 1934 const intptr_t kNumTemps = 0; | 1934 const intptr_t kNumTemps = 0; |
| 1935 LocationSummary* summary = | 1935 LocationSummary* summary = |
| 1936 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1936 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1937 summary->set_in(0, Location::RegisterLocation(EAX)); | 1937 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 1938 summary->set_in(1, Location::RegisterLocation(ECX)); | 1938 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 1939 summary->set_in(2, Location::RegisterLocation(EDX)); | 1939 summary->set_in(2, Location::RegisterLocation(EDX)); |
| 1940 summary->set_out(Location::RegisterLocation(EAX)); | 1940 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 1941 return summary; | 1941 return summary; |
| 1942 } | 1942 } |
| 1943 | 1943 |
| 1944 | 1944 |
| 1945 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1945 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1946 ASSERT(locs()->in(0).reg() == EAX); // Value. | 1946 ASSERT(locs()->in(0).reg() == EAX); // Value. |
| 1947 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 1947 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. |
| 1948 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | 1948 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. |
| 1949 | 1949 |
| 1950 compiler->GenerateInstanceOf(token_pos(), | 1950 compiler->GenerateInstanceOf(token_pos(), |
| 1951 deopt_id(), | 1951 deopt_id(), |
| 1952 type(), | 1952 type(), |
| 1953 negate_result(), | 1953 negate_result(), |
| 1954 locs()); | 1954 locs()); |
| 1955 ASSERT(locs()->out().reg() == EAX); | 1955 ASSERT(locs()->out(0).reg() == EAX); |
| 1956 } | 1956 } |
| 1957 | 1957 |
| 1958 | 1958 |
| 1959 LocationSummary* CreateArrayInstr::MakeLocationSummary(bool opt) const { | 1959 LocationSummary* CreateArrayInstr::MakeLocationSummary(bool opt) const { |
| 1960 const intptr_t kNumInputs = 2; | 1960 const intptr_t kNumInputs = 2; |
| 1961 const intptr_t kNumTemps = 0; | 1961 const intptr_t kNumTemps = 0; |
| 1962 LocationSummary* locs = | 1962 LocationSummary* locs = |
| 1963 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1963 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1964 locs->set_in(0, Location::RegisterLocation(ECX)); | 1964 locs->set_in(0, Location::RegisterLocation(ECX)); |
| 1965 locs->set_in(1, Location::RegisterLocation(EDX)); | 1965 locs->set_in(1, Location::RegisterLocation(EDX)); |
| 1966 locs->set_out(Location::RegisterLocation(EAX)); | 1966 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 1967 return locs; | 1967 return locs; |
| 1968 } | 1968 } |
| 1969 | 1969 |
| 1970 | 1970 |
| 1971 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1971 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1972 // Allocate the array. EDX = length, ECX = element type. | 1972 // Allocate the array. EDX = length, ECX = element type. |
| 1973 ASSERT(locs()->in(0).reg() == ECX); | 1973 ASSERT(locs()->in(0).reg() == ECX); |
| 1974 ASSERT(locs()->in(1).reg() == EDX); | 1974 ASSERT(locs()->in(1).reg() == EDX); |
| 1975 compiler->GenerateCall(token_pos(), | 1975 compiler->GenerateCall(token_pos(), |
| 1976 &StubCode::AllocateArrayLabel(), | 1976 &StubCode::AllocateArrayLabel(), |
| 1977 PcDescriptors::kOther, | 1977 PcDescriptors::kOther, |
| 1978 locs()); | 1978 locs()); |
| 1979 ASSERT(locs()->out().reg() == EAX); | 1979 ASSERT(locs()->out(0).reg() == EAX); |
| 1980 } | 1980 } |
| 1981 | 1981 |
| 1982 | 1982 |
| 1983 class BoxDoubleSlowPath : public SlowPathCode { | 1983 class BoxDoubleSlowPath : public SlowPathCode { |
| 1984 public: | 1984 public: |
| 1985 explicit BoxDoubleSlowPath(Instruction* instruction) | 1985 explicit BoxDoubleSlowPath(Instruction* instruction) |
| 1986 : instruction_(instruction) { } | 1986 : instruction_(instruction) { } |
| 1987 | 1987 |
| 1988 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1988 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1989 __ Comment("BoxDoubleSlowPath"); | 1989 __ Comment("BoxDoubleSlowPath"); |
| 1990 __ Bind(entry_label()); | 1990 __ Bind(entry_label()); |
| 1991 const Class& double_class = compiler->double_class(); | 1991 const Class& double_class = compiler->double_class(); |
| 1992 const Code& stub = | 1992 const Code& stub = |
| 1993 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1993 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1994 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1994 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1995 | 1995 |
| 1996 LocationSummary* locs = instruction_->locs(); | 1996 LocationSummary* locs = instruction_->locs(); |
| 1997 locs->live_registers()->Remove(locs->out()); | 1997 locs->live_registers()->Remove(locs->out(0)); |
| 1998 | 1998 |
| 1999 compiler->SaveLiveRegisters(locs); | 1999 compiler->SaveLiveRegisters(locs); |
| 2000 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 2000 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 2001 &label, | 2001 &label, |
| 2002 PcDescriptors::kOther, | 2002 PcDescriptors::kOther, |
| 2003 locs); | 2003 locs); |
| 2004 __ MoveRegister(locs->out().reg(), EAX); | 2004 __ MoveRegister(locs->out(0).reg(), EAX); |
| 2005 compiler->RestoreLiveRegisters(locs); | 2005 compiler->RestoreLiveRegisters(locs); |
| 2006 | 2006 |
| 2007 __ jmp(exit_label()); | 2007 __ jmp(exit_label()); |
| 2008 } | 2008 } |
| 2009 | 2009 |
| 2010 private: | 2010 private: |
| 2011 Instruction* instruction_; | 2011 Instruction* instruction_; |
| 2012 }; | 2012 }; |
| 2013 | 2013 |
| 2014 | 2014 |
| 2015 class BoxFloat32x4SlowPath : public SlowPathCode { | 2015 class BoxFloat32x4SlowPath : public SlowPathCode { |
| 2016 public: | 2016 public: |
| 2017 explicit BoxFloat32x4SlowPath(Instruction* instruction) | 2017 explicit BoxFloat32x4SlowPath(Instruction* instruction) |
| 2018 : instruction_(instruction) { } | 2018 : instruction_(instruction) { } |
| 2019 | 2019 |
| 2020 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2020 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2021 __ Comment("BoxFloat32x4SlowPath"); | 2021 __ Comment("BoxFloat32x4SlowPath"); |
| 2022 __ Bind(entry_label()); | 2022 __ Bind(entry_label()); |
| 2023 const Class& float32x4_class = compiler->float32x4_class(); | 2023 const Class& float32x4_class = compiler->float32x4_class(); |
| 2024 const Code& stub = | 2024 const Code& stub = |
| 2025 Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class)); | 2025 Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class)); |
| 2026 const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint()); | 2026 const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint()); |
| 2027 | 2027 |
| 2028 LocationSummary* locs = instruction_->locs(); | 2028 LocationSummary* locs = instruction_->locs(); |
| 2029 locs->live_registers()->Remove(locs->out()); | 2029 locs->live_registers()->Remove(locs->out(0)); |
| 2030 | 2030 |
| 2031 compiler->SaveLiveRegisters(locs); | 2031 compiler->SaveLiveRegisters(locs); |
| 2032 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 2032 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 2033 &label, | 2033 &label, |
| 2034 PcDescriptors::kOther, | 2034 PcDescriptors::kOther, |
| 2035 locs); | 2035 locs); |
| 2036 __ MoveRegister(locs->out().reg(), EAX); | 2036 __ MoveRegister(locs->out(0).reg(), EAX); |
| 2037 compiler->RestoreLiveRegisters(locs); | 2037 compiler->RestoreLiveRegisters(locs); |
| 2038 | 2038 |
| 2039 __ jmp(exit_label()); | 2039 __ jmp(exit_label()); |
| 2040 } | 2040 } |
| 2041 | 2041 |
| 2042 private: | 2042 private: |
| 2043 Instruction* instruction_; | 2043 Instruction* instruction_; |
| 2044 }; | 2044 }; |
| 2045 | 2045 |
| 2046 | 2046 |
| 2047 class BoxFloat64x2SlowPath : public SlowPathCode { | 2047 class BoxFloat64x2SlowPath : public SlowPathCode { |
| 2048 public: | 2048 public: |
| 2049 explicit BoxFloat64x2SlowPath(Instruction* instruction) | 2049 explicit BoxFloat64x2SlowPath(Instruction* instruction) |
| 2050 : instruction_(instruction) { } | 2050 : instruction_(instruction) { } |
| 2051 | 2051 |
| 2052 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2052 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2053 __ Comment("BoxFloat64x2SlowPath"); | 2053 __ Comment("BoxFloat64x2SlowPath"); |
| 2054 __ Bind(entry_label()); | 2054 __ Bind(entry_label()); |
| 2055 const Class& float64x2_class = compiler->float64x2_class(); | 2055 const Class& float64x2_class = compiler->float64x2_class(); |
| 2056 const Code& stub = | 2056 const Code& stub = |
| 2057 Code::Handle(StubCode::GetAllocationStubForClass(float64x2_class)); | 2057 Code::Handle(StubCode::GetAllocationStubForClass(float64x2_class)); |
| 2058 const ExternalLabel label(float64x2_class.ToCString(), stub.EntryPoint()); | 2058 const ExternalLabel label(float64x2_class.ToCString(), stub.EntryPoint()); |
| 2059 | 2059 |
| 2060 LocationSummary* locs = instruction_->locs(); | 2060 LocationSummary* locs = instruction_->locs(); |
| 2061 locs->live_registers()->Remove(locs->out()); | 2061 locs->live_registers()->Remove(locs->out(0)); |
| 2062 | 2062 |
| 2063 compiler->SaveLiveRegisters(locs); | 2063 compiler->SaveLiveRegisters(locs); |
| 2064 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 2064 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 2065 &label, | 2065 &label, |
| 2066 PcDescriptors::kOther, | 2066 PcDescriptors::kOther, |
| 2067 locs); | 2067 locs); |
| 2068 __ MoveRegister(locs->out().reg(), EAX); | 2068 __ MoveRegister(locs->out(0).reg(), EAX); |
| 2069 compiler->RestoreLiveRegisters(locs); | 2069 compiler->RestoreLiveRegisters(locs); |
| 2070 | 2070 |
| 2071 __ jmp(exit_label()); | 2071 __ jmp(exit_label()); |
| 2072 } | 2072 } |
| 2073 | 2073 |
| 2074 private: | 2074 private: |
| 2075 Instruction* instruction_; | 2075 Instruction* instruction_; |
| 2076 }; | 2076 }; |
| 2077 | 2077 |
| 2078 | 2078 |
| 2079 LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const { | 2079 LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const { |
| 2080 const intptr_t kNumInputs = 1; | 2080 const intptr_t kNumInputs = 1; |
| 2081 const intptr_t kNumTemps = 0; | 2081 const intptr_t kNumTemps = 0; |
| 2082 LocationSummary* locs = | 2082 LocationSummary* locs = |
| 2083 new LocationSummary( | 2083 new LocationSummary( |
| 2084 kNumInputs, kNumTemps, | 2084 kNumInputs, kNumTemps, |
| 2085 (opt && !IsPotentialUnboxedLoad()) | 2085 (opt && !IsPotentialUnboxedLoad()) |
| 2086 ? LocationSummary::kNoCall | 2086 ? LocationSummary::kNoCall |
| 2087 : LocationSummary::kCallOnSlowPath); | 2087 : LocationSummary::kCallOnSlowPath); |
| 2088 | 2088 |
| 2089 locs->set_in(0, Location::RequiresRegister()); | 2089 locs->set_in(0, Location::RequiresRegister()); |
| 2090 | 2090 |
| 2091 if (IsUnboxedLoad() && opt) { | 2091 if (IsUnboxedLoad() && opt) { |
| 2092 locs->AddTemp(Location::RequiresRegister()); | 2092 locs->AddTemp(Location::RequiresRegister()); |
| 2093 } else if (IsPotentialUnboxedLoad()) { | 2093 } else if (IsPotentialUnboxedLoad()) { |
| 2094 locs->AddTemp(opt ? Location::RequiresFpuRegister() | 2094 locs->AddTemp(opt ? Location::RequiresFpuRegister() |
| 2095 : Location::FpuRegisterLocation(XMM1)); | 2095 : Location::FpuRegisterLocation(XMM1)); |
| 2096 locs->AddTemp(Location::RequiresRegister()); | 2096 locs->AddTemp(Location::RequiresRegister()); |
| 2097 } | 2097 } |
| 2098 locs->set_out(Location::RequiresRegister()); | 2098 locs->set_out(0, Location::RequiresRegister()); |
| 2099 return locs; | 2099 return locs; |
| 2100 } | 2100 } |
| 2101 | 2101 |
| 2102 | 2102 |
| 2103 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2103 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2104 Register instance_reg = locs()->in(0).reg(); | 2104 Register instance_reg = locs()->in(0).reg(); |
| 2105 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2105 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
| 2106 XmmRegister result = locs()->out().fpu_reg(); | 2106 XmmRegister result = locs()->out(0).fpu_reg(); |
| 2107 Register temp = locs()->temp(0).reg(); | 2107 Register temp = locs()->temp(0).reg(); |
| 2108 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2108 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2109 const intptr_t cid = field()->UnboxedFieldCid(); | 2109 const intptr_t cid = field()->UnboxedFieldCid(); |
| 2110 switch (cid) { | 2110 switch (cid) { |
| 2111 case kDoubleCid: | 2111 case kDoubleCid: |
| 2112 __ Comment("UnboxedDoubleLoadFieldInstr"); | 2112 __ Comment("UnboxedDoubleLoadFieldInstr"); |
| 2113 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 2113 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 2114 break; | 2114 break; |
| 2115 case kFloat32x4Cid: | 2115 case kFloat32x4Cid: |
| 2116 __ Comment("UnboxedFloat32x4LoadFieldInstr"); | 2116 __ Comment("UnboxedFloat32x4LoadFieldInstr"); |
| 2117 __ movups(result, FieldAddress(temp, Float32x4::value_offset())); | 2117 __ movups(result, FieldAddress(temp, Float32x4::value_offset())); |
| 2118 break; | 2118 break; |
| 2119 case kFloat64x2Cid: | 2119 case kFloat64x2Cid: |
| 2120 __ Comment("UnboxedFloat64x2LoadFieldInstr"); | 2120 __ Comment("UnboxedFloat64x2LoadFieldInstr"); |
| 2121 __ movups(result, FieldAddress(temp, Float64x2::value_offset())); | 2121 __ movups(result, FieldAddress(temp, Float64x2::value_offset())); |
| 2122 break; | 2122 break; |
| 2123 default: | 2123 default: |
| 2124 UNREACHABLE(); | 2124 UNREACHABLE(); |
| 2125 } | 2125 } |
| 2126 return; | 2126 return; |
| 2127 } | 2127 } |
| 2128 | 2128 |
| 2129 Label done; | 2129 Label done; |
| 2130 Register result = locs()->out().reg(); | 2130 Register result = locs()->out(0).reg(); |
| 2131 if (IsPotentialUnboxedLoad()) { | 2131 if (IsPotentialUnboxedLoad()) { |
| 2132 Register temp = locs()->temp(1).reg(); | 2132 Register temp = locs()->temp(1).reg(); |
| 2133 XmmRegister value = locs()->temp(0).fpu_reg(); | 2133 XmmRegister value = locs()->temp(0).fpu_reg(); |
| 2134 | 2134 |
| 2135 | 2135 |
| 2136 Label load_pointer; | 2136 Label load_pointer; |
| 2137 Label load_double; | 2137 Label load_double; |
| 2138 Label load_float32x4; | 2138 Label load_float32x4; |
| 2139 Label load_float64x2; | 2139 Label load_float64x2; |
| 2140 | 2140 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2221 __ Bind(&done); | 2221 __ Bind(&done); |
| 2222 } | 2222 } |
| 2223 | 2223 |
| 2224 | 2224 |
| 2225 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { | 2225 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { |
| 2226 const intptr_t kNumInputs = 1; | 2226 const intptr_t kNumInputs = 1; |
| 2227 const intptr_t kNumTemps = 0; | 2227 const intptr_t kNumTemps = 0; |
| 2228 LocationSummary* locs = | 2228 LocationSummary* locs = |
| 2229 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 2229 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2230 locs->set_in(0, Location::RegisterLocation(EAX)); | 2230 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 2231 locs->set_out(Location::RegisterLocation(EAX)); | 2231 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2232 return locs; | 2232 return locs; |
| 2233 } | 2233 } |
| 2234 | 2234 |
| 2235 | 2235 |
| 2236 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2236 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2237 Register instantiator_reg = locs()->in(0).reg(); | 2237 Register instantiator_reg = locs()->in(0).reg(); |
| 2238 Register result_reg = locs()->out().reg(); | 2238 Register result_reg = locs()->out(0).reg(); |
| 2239 | 2239 |
| 2240 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2240 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2241 // A runtime call to instantiate the type is required. | 2241 // A runtime call to instantiate the type is required. |
| 2242 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 2242 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 2243 __ PushObject(type()); | 2243 __ PushObject(type()); |
| 2244 __ pushl(instantiator_reg); // Push instantiator type arguments. | 2244 __ pushl(instantiator_reg); // Push instantiator type arguments. |
| 2245 compiler->GenerateRuntimeCall(token_pos(), | 2245 compiler->GenerateRuntimeCall(token_pos(), |
| 2246 deopt_id(), | 2246 deopt_id(), |
| 2247 kInstantiateTypeRuntimeEntry, | 2247 kInstantiateTypeRuntimeEntry, |
| 2248 2, | 2248 2, |
| 2249 locs()); | 2249 locs()); |
| 2250 __ Drop(2); // Drop instantiator and uninstantiated type. | 2250 __ Drop(2); // Drop instantiator and uninstantiated type. |
| 2251 __ popl(result_reg); // Pop instantiated type. | 2251 __ popl(result_reg); // Pop instantiated type. |
| 2252 ASSERT(instantiator_reg == result_reg); | 2252 ASSERT(instantiator_reg == result_reg); |
| 2253 } | 2253 } |
| 2254 | 2254 |
| 2255 | 2255 |
| 2256 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2256 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
| 2257 bool opt) const { | 2257 bool opt) const { |
| 2258 const intptr_t kNumInputs = 1; | 2258 const intptr_t kNumInputs = 1; |
| 2259 const intptr_t kNumTemps = 0; | 2259 const intptr_t kNumTemps = 0; |
| 2260 LocationSummary* locs = | 2260 LocationSummary* locs = |
| 2261 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 2261 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2262 locs->set_in(0, Location::RegisterLocation(EAX)); | 2262 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 2263 locs->set_out(Location::RegisterLocation(EAX)); | 2263 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2264 return locs; | 2264 return locs; |
| 2265 } | 2265 } |
| 2266 | 2266 |
| 2267 | 2267 |
| 2268 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2268 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 2269 FlowGraphCompiler* compiler) { | 2269 FlowGraphCompiler* compiler) { |
| 2270 Register instantiator_reg = locs()->in(0).reg(); | 2270 Register instantiator_reg = locs()->in(0).reg(); |
| 2271 Register result_reg = locs()->out().reg(); | 2271 Register result_reg = locs()->out(0).reg(); |
| 2272 ASSERT(instantiator_reg == EAX); | 2272 ASSERT(instantiator_reg == EAX); |
| 2273 ASSERT(instantiator_reg == result_reg); | 2273 ASSERT(instantiator_reg == result_reg); |
| 2274 | 2274 |
| 2275 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2275 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2276 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2276 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
| 2277 !type_arguments().CanShareInstantiatorTypeArguments( | 2277 !type_arguments().CanShareInstantiatorTypeArguments( |
| 2278 instantiator_class())); | 2278 instantiator_class())); |
| 2279 // If the instantiator is null and if the type argument vector | 2279 // If the instantiator is null and if the type argument vector |
| 2280 // instantiated from null becomes a vector of dynamic, then use null as | 2280 // instantiated from null becomes a vector of dynamic, then use null as |
| 2281 // the type arguments. | 2281 // the type arguments. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2326 | 2326 |
| 2327 | 2327 |
| 2328 LocationSummary* AllocateContextInstr::MakeLocationSummary(bool opt) const { | 2328 LocationSummary* AllocateContextInstr::MakeLocationSummary(bool opt) const { |
| 2329 if (opt) { | 2329 if (opt) { |
| 2330 const intptr_t kNumInputs = 0; | 2330 const intptr_t kNumInputs = 0; |
| 2331 const intptr_t kNumTemps = 2; | 2331 const intptr_t kNumTemps = 2; |
| 2332 LocationSummary* locs = new LocationSummary( | 2332 LocationSummary* locs = new LocationSummary( |
| 2333 kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2333 kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2334 locs->set_temp(0, Location::RegisterLocation(ECX)); | 2334 locs->set_temp(0, Location::RegisterLocation(ECX)); |
| 2335 locs->set_temp(1, Location::RegisterLocation(EBX)); | 2335 locs->set_temp(1, Location::RegisterLocation(EBX)); |
| 2336 locs->set_out(Location::RegisterLocation(EAX)); | 2336 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2337 return locs; | 2337 return locs; |
| 2338 } | 2338 } |
| 2339 const intptr_t kNumInputs = 0; | 2339 const intptr_t kNumInputs = 0; |
| 2340 const intptr_t kNumTemps = 1; | 2340 const intptr_t kNumTemps = 1; |
| 2341 LocationSummary* locs = | 2341 LocationSummary* locs = |
| 2342 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 2342 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2343 locs->set_temp(0, Location::RegisterLocation(EDX)); | 2343 locs->set_temp(0, Location::RegisterLocation(EDX)); |
| 2344 locs->set_out(Location::RegisterLocation(EAX)); | 2344 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2345 return locs; | 2345 return locs; |
| 2346 } | 2346 } |
| 2347 | 2347 |
| 2348 | 2348 |
| 2349 class AllocateContextSlowPath : public SlowPathCode { | 2349 class AllocateContextSlowPath : public SlowPathCode { |
| 2350 public: | 2350 public: |
| 2351 explicit AllocateContextSlowPath(AllocateContextInstr* instruction) | 2351 explicit AllocateContextSlowPath(AllocateContextInstr* instruction) |
| 2352 : instruction_(instruction) { } | 2352 : instruction_(instruction) { } |
| 2353 | 2353 |
| 2354 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2354 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2355 __ Comment("AllocateContextSlowPath"); | 2355 __ Comment("AllocateContextSlowPath"); |
| 2356 __ Bind(entry_label()); | 2356 __ Bind(entry_label()); |
| 2357 | 2357 |
| 2358 LocationSummary* locs = instruction_->locs(); | 2358 LocationSummary* locs = instruction_->locs(); |
| 2359 locs->live_registers()->Remove(locs->out()); | 2359 locs->live_registers()->Remove(locs->out(0)); |
| 2360 | 2360 |
| 2361 compiler->SaveLiveRegisters(locs); | 2361 compiler->SaveLiveRegisters(locs); |
| 2362 | 2362 |
| 2363 __ movl(EDX, Immediate(instruction_->num_context_variables())); | 2363 __ movl(EDX, Immediate(instruction_->num_context_variables())); |
| 2364 const ExternalLabel label("alloc_context", | 2364 const ExternalLabel label("alloc_context", |
| 2365 StubCode::AllocateContextEntryPoint()); | 2365 StubCode::AllocateContextEntryPoint()); |
| 2366 compiler->GenerateCall(instruction_->token_pos(), | 2366 compiler->GenerateCall(instruction_->token_pos(), |
| 2367 &label, | 2367 &label, |
| 2368 PcDescriptors::kOther, | 2368 PcDescriptors::kOther, |
| 2369 locs); | 2369 locs); |
| 2370 ASSERT(instruction_->locs()->out().reg() == EAX); | 2370 ASSERT(instruction_->locs()->out(0).reg() == EAX); |
| 2371 compiler->RestoreLiveRegisters(instruction_->locs()); | 2371 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2372 __ jmp(exit_label()); | 2372 __ jmp(exit_label()); |
| 2373 } | 2373 } |
| 2374 | 2374 |
| 2375 private: | 2375 private: |
| 2376 AllocateContextInstr* instruction_; | 2376 AllocateContextInstr* instruction_; |
| 2377 }; | 2377 }; |
| 2378 | 2378 |
| 2379 | 2379 |
| 2380 | 2380 |
| 2381 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2381 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2382 if (compiler->is_optimizing()) { | 2382 if (compiler->is_optimizing()) { |
| 2383 Register temp0 = locs()->temp(0).reg(); | 2383 Register temp0 = locs()->temp(0).reg(); |
| 2384 Register temp1 = locs()->temp(1).reg(); | 2384 Register temp1 = locs()->temp(1).reg(); |
| 2385 Register result = locs()->out().reg(); | 2385 Register result = locs()->out(0).reg(); |
| 2386 // Try allocate the object. | 2386 // Try allocate the object. |
| 2387 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2387 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| 2388 compiler->AddSlowPathCode(slow_path); | 2388 compiler->AddSlowPathCode(slow_path); |
| 2389 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2389 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| 2390 __ movl(temp1, Immediate(instance_size)); | 2390 __ movl(temp1, Immediate(instance_size)); |
| 2391 Isolate* isolate = Isolate::Current(); | 2391 Isolate* isolate = Isolate::Current(); |
| 2392 Heap* heap = isolate->heap(); | 2392 Heap* heap = isolate->heap(); |
| 2393 __ movl(result, Address::Absolute(heap->TopAddress())); | 2393 __ movl(result, Address::Absolute(heap->TopAddress())); |
| 2394 __ addl(temp1, result); | 2394 __ addl(temp1, result); |
| 2395 // Check if the allocation fits into the remaining space. | 2395 // Check if the allocation fits into the remaining space. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2442 __ decl(temp0); | 2442 __ decl(temp0); |
| 2443 __ movl(Address(temp1, temp0, TIMES_4, 0), raw_null); | 2443 __ movl(Address(temp1, temp0, TIMES_4, 0), raw_null); |
| 2444 __ j(NOT_ZERO, &loop, Assembler::kNearJump); | 2444 __ j(NOT_ZERO, &loop, Assembler::kNearJump); |
| 2445 } | 2445 } |
| 2446 // EAX: new object. | 2446 // EAX: new object. |
| 2447 __ Bind(slow_path->exit_label()); | 2447 __ Bind(slow_path->exit_label()); |
| 2448 return; | 2448 return; |
| 2449 } | 2449 } |
| 2450 | 2450 |
| 2451 ASSERT(locs()->temp(0).reg() == EDX); | 2451 ASSERT(locs()->temp(0).reg() == EDX); |
| 2452 ASSERT(locs()->out().reg() == EAX); | 2452 ASSERT(locs()->out(0).reg() == EAX); |
| 2453 | 2453 |
| 2454 __ movl(EDX, Immediate(num_context_variables())); | 2454 __ movl(EDX, Immediate(num_context_variables())); |
| 2455 const ExternalLabel label("alloc_context", | 2455 const ExternalLabel label("alloc_context", |
| 2456 StubCode::AllocateContextEntryPoint()); | 2456 StubCode::AllocateContextEntryPoint()); |
| 2457 compiler->GenerateCall(token_pos(), | 2457 compiler->GenerateCall(token_pos(), |
| 2458 &label, | 2458 &label, |
| 2459 PcDescriptors::kOther, | 2459 PcDescriptors::kOther, |
| 2460 locs()); | 2460 locs()); |
| 2461 } | 2461 } |
| 2462 | 2462 |
| 2463 | 2463 |
| 2464 LocationSummary* CloneContextInstr::MakeLocationSummary(bool opt) const { | 2464 LocationSummary* CloneContextInstr::MakeLocationSummary(bool opt) const { |
| 2465 const intptr_t kNumInputs = 1; | 2465 const intptr_t kNumInputs = 1; |
| 2466 const intptr_t kNumTemps = 0; | 2466 const intptr_t kNumTemps = 0; |
| 2467 LocationSummary* locs = | 2467 LocationSummary* locs = |
| 2468 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 2468 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2469 locs->set_in(0, Location::RegisterLocation(EAX)); | 2469 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 2470 locs->set_out(Location::RegisterLocation(EAX)); | 2470 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2471 return locs; | 2471 return locs; |
| 2472 } | 2472 } |
| 2473 | 2473 |
| 2474 | 2474 |
| 2475 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2475 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2476 Register context_value = locs()->in(0).reg(); | 2476 Register context_value = locs()->in(0).reg(); |
| 2477 Register result = locs()->out().reg(); | 2477 Register result = locs()->out(0).reg(); |
| 2478 | 2478 |
| 2479 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 2479 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 2480 __ pushl(context_value); | 2480 __ pushl(context_value); |
| 2481 compiler->GenerateRuntimeCall(token_pos(), | 2481 compiler->GenerateRuntimeCall(token_pos(), |
| 2482 deopt_id(), | 2482 deopt_id(), |
| 2483 kCloneContextRuntimeEntry, | 2483 kCloneContextRuntimeEntry, |
| 2484 1, | 2484 1, |
| 2485 locs()); | 2485 locs()); |
| 2486 __ popl(result); // Remove argument. | 2486 __ popl(result); // Remove argument. |
| 2487 __ popl(result); // Get result (cloned context). | 2487 __ popl(result); // Get result (cloned context). |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2588 } | 2588 } |
| 2589 __ Bind(slow_path->exit_label()); | 2589 __ Bind(slow_path->exit_label()); |
| 2590 } | 2590 } |
| 2591 | 2591 |
| 2592 | 2592 |
| 2593 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2593 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 2594 BinarySmiOpInstr* shift_left) { | 2594 BinarySmiOpInstr* shift_left) { |
| 2595 const bool is_truncating = shift_left->is_truncating(); | 2595 const bool is_truncating = shift_left->is_truncating(); |
| 2596 const LocationSummary& locs = *shift_left->locs(); | 2596 const LocationSummary& locs = *shift_left->locs(); |
| 2597 Register left = locs.in(0).reg(); | 2597 Register left = locs.in(0).reg(); |
| 2598 Register result = locs.out().reg(); | 2598 Register result = locs.out(0).reg(); |
| 2599 ASSERT(left == result); | 2599 ASSERT(left == result); |
| 2600 Label* deopt = shift_left->CanDeoptimize() ? | 2600 Label* deopt = shift_left->CanDeoptimize() ? |
| 2601 compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL; | 2601 compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL; |
| 2602 if (locs.in(1).IsConstant()) { | 2602 if (locs.in(1).IsConstant()) { |
| 2603 const Object& constant = locs.in(1).constant(); | 2603 const Object& constant = locs.in(1).constant(); |
| 2604 ASSERT(constant.IsSmi()); | 2604 ASSERT(constant.IsSmi()); |
| 2605 // shll operation masks the count to 5 bits. | 2605 // shll operation masks the count to 5 bits. |
| 2606 const intptr_t kCountLimit = 0x1F; | 2606 const intptr_t kCountLimit = 0x1F; |
| 2607 const intptr_t value = Smi::Cast(constant).Value(); | 2607 const intptr_t value = Smi::Cast(constant).Value(); |
| 2608 if (value == 0) { | 2608 if (value == 0) { |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2716 if (op_kind() == Token::kTRUNCDIV) { | 2716 if (op_kind() == Token::kTRUNCDIV) { |
| 2717 const intptr_t kNumTemps = 1; | 2717 const intptr_t kNumTemps = 1; |
| 2718 LocationSummary* summary = | 2718 LocationSummary* summary = |
| 2719 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2719 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2720 if (RightIsPowerOfTwoConstant()) { | 2720 if (RightIsPowerOfTwoConstant()) { |
| 2721 summary->set_in(0, Location::RequiresRegister()); | 2721 summary->set_in(0, Location::RequiresRegister()); |
| 2722 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 2722 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 2723 // The programmer only controls one bit, so the constant is safe. | 2723 // The programmer only controls one bit, so the constant is safe. |
| 2724 summary->set_in(1, Location::Constant(right_constant->value())); | 2724 summary->set_in(1, Location::Constant(right_constant->value())); |
| 2725 summary->set_temp(0, Location::RequiresRegister()); | 2725 summary->set_temp(0, Location::RequiresRegister()); |
| 2726 summary->set_out(Location::SameAsFirstInput()); | 2726 summary->set_out(0, Location::SameAsFirstInput()); |
| 2727 } else { | 2727 } else { |
| 2728 // Both inputs must be writable because they will be untagged. | 2728 // Both inputs must be writable because they will be untagged. |
| 2729 summary->set_in(0, Location::RegisterLocation(EAX)); | 2729 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 2730 summary->set_in(1, Location::WritableRegister()); | 2730 summary->set_in(1, Location::WritableRegister()); |
| 2731 summary->set_out(Location::SameAsFirstInput()); | 2731 summary->set_out(0, Location::SameAsFirstInput()); |
| 2732 // Will be used for sign extension and division. | 2732 // Will be used for sign extension and division. |
| 2733 summary->set_temp(0, Location::RegisterLocation(EDX)); | 2733 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 2734 } | 2734 } |
| 2735 return summary; | 2735 return summary; |
| 2736 } else if (op_kind() == Token::kMOD) { | 2736 } else if (op_kind() == Token::kMOD) { |
| 2737 const intptr_t kNumTemps = 1; | 2737 const intptr_t kNumTemps = 1; |
| 2738 LocationSummary* summary = | 2738 LocationSummary* summary = |
| 2739 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2739 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2740 // Both inputs must be writable because they will be untagged. | 2740 // Both inputs must be writable because they will be untagged. |
| 2741 summary->set_in(0, Location::RegisterLocation(EDX)); | 2741 summary->set_in(0, Location::RegisterLocation(EDX)); |
| 2742 summary->set_in(1, Location::WritableRegister()); | 2742 summary->set_in(1, Location::WritableRegister()); |
| 2743 summary->set_out(Location::SameAsFirstInput()); | 2743 summary->set_out(0, Location::SameAsFirstInput()); |
| 2744 // Will be used for sign extension and division. | 2744 // Will be used for sign extension and division. |
| 2745 summary->set_temp(0, Location::RegisterLocation(EAX)); | 2745 summary->set_temp(0, Location::RegisterLocation(EAX)); |
| 2746 return summary; | 2746 return summary; |
| 2747 } else if (op_kind() == Token::kSHR) { | 2747 } else if (op_kind() == Token::kSHR) { |
| 2748 const intptr_t kNumTemps = 0; | 2748 const intptr_t kNumTemps = 0; |
| 2749 LocationSummary* summary = | 2749 LocationSummary* summary = |
| 2750 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2750 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2751 summary->set_in(0, Location::RequiresRegister()); | 2751 summary->set_in(0, Location::RequiresRegister()); |
| 2752 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 2752 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 2753 summary->set_out(Location::SameAsFirstInput()); | 2753 summary->set_out(0, Location::SameAsFirstInput()); |
| 2754 return summary; | 2754 return summary; |
| 2755 } else if (op_kind() == Token::kSHL) { | 2755 } else if (op_kind() == Token::kSHL) { |
| 2756 const intptr_t kNumTemps = 0; | 2756 const intptr_t kNumTemps = 0; |
| 2757 LocationSummary* summary = | 2757 LocationSummary* summary = |
| 2758 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2758 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2759 summary->set_in(0, Location::RequiresRegister()); | 2759 summary->set_in(0, Location::RequiresRegister()); |
| 2760 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 2760 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 2761 if (!is_truncating()) { | 2761 if (!is_truncating()) { |
| 2762 summary->AddTemp(Location::RequiresRegister()); | 2762 summary->AddTemp(Location::RequiresRegister()); |
| 2763 } | 2763 } |
| 2764 summary->set_out(Location::SameAsFirstInput()); | 2764 summary->set_out(0, Location::SameAsFirstInput()); |
| 2765 return summary; | 2765 return summary; |
| 2766 } else { | 2766 } else { |
| 2767 const intptr_t kNumTemps = 0; | 2767 const intptr_t kNumTemps = 0; |
| 2768 LocationSummary* summary = | 2768 LocationSummary* summary = |
| 2769 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2769 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2770 summary->set_in(0, Location::RequiresRegister()); | 2770 summary->set_in(0, Location::RequiresRegister()); |
| 2771 ConstantInstr* constant = right()->definition()->AsConstant(); | 2771 ConstantInstr* constant = right()->definition()->AsConstant(); |
| 2772 if (constant != NULL) { | 2772 if (constant != NULL) { |
| 2773 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 2773 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 2774 } else { | 2774 } else { |
| 2775 summary->set_in(1, Location::PrefersRegister()); | 2775 summary->set_in(1, Location::PrefersRegister()); |
| 2776 } | 2776 } |
| 2777 summary->set_out(Location::SameAsFirstInput()); | 2777 summary->set_out(0, Location::SameAsFirstInput()); |
| 2778 return summary; | 2778 return summary; |
| 2779 } | 2779 } |
| 2780 } | 2780 } |
| 2781 | 2781 |
| 2782 | 2782 |
| 2783 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2783 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2784 if (op_kind() == Token::kSHL) { | 2784 if (op_kind() == Token::kSHL) { |
| 2785 EmitSmiShiftLeft(compiler, this); | 2785 EmitSmiShiftLeft(compiler, this); |
| 2786 return; | 2786 return; |
| 2787 } | 2787 } |
| 2788 | 2788 |
| 2789 ASSERT(!is_truncating()); | 2789 ASSERT(!is_truncating()); |
| 2790 Register left = locs()->in(0).reg(); | 2790 Register left = locs()->in(0).reg(); |
| 2791 Register result = locs()->out().reg(); | 2791 Register result = locs()->out(0).reg(); |
| 2792 ASSERT(left == result); | 2792 ASSERT(left == result); |
| 2793 Label* deopt = NULL; | 2793 Label* deopt = NULL; |
| 2794 if (CanDeoptimize()) { | 2794 if (CanDeoptimize()) { |
| 2795 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 2795 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| 2796 } | 2796 } |
| 2797 | 2797 |
| 2798 if (locs()->in(1).IsConstant()) { | 2798 if (locs()->in(1).IsConstant()) { |
| 2799 const Object& constant = locs()->in(1).constant(); | 2799 const Object& constant = locs()->in(1).constant(); |
| 2800 ASSERT(constant.IsSmi()); | 2800 ASSERT(constant.IsSmi()); |
| 2801 const int32_t imm = | 2801 const int32_t imm = |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3121 | 3121 |
| 3122 | 3122 |
| 3123 LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const { | 3123 LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const { |
| 3124 const intptr_t kNumInputs = 1; | 3124 const intptr_t kNumInputs = 1; |
| 3125 const intptr_t kNumTemps = 0; | 3125 const intptr_t kNumTemps = 0; |
| 3126 LocationSummary* summary = | 3126 LocationSummary* summary = |
| 3127 new LocationSummary(kNumInputs, | 3127 new LocationSummary(kNumInputs, |
| 3128 kNumTemps, | 3128 kNumTemps, |
| 3129 LocationSummary::kCallOnSlowPath); | 3129 LocationSummary::kCallOnSlowPath); |
| 3130 summary->set_in(0, Location::RequiresFpuRegister()); | 3130 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3131 summary->set_out(Location::RequiresRegister()); | 3131 summary->set_out(0, Location::RequiresRegister()); |
| 3132 return summary; | 3132 return summary; |
| 3133 } | 3133 } |
| 3134 | 3134 |
| 3135 | 3135 |
| 3136 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3136 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3137 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 3137 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
| 3138 compiler->AddSlowPathCode(slow_path); | 3138 compiler->AddSlowPathCode(slow_path); |
| 3139 | 3139 |
| 3140 Register out_reg = locs()->out().reg(); | 3140 Register out_reg = locs()->out(0).reg(); |
| 3141 XmmRegister value = locs()->in(0).fpu_reg(); | 3141 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3142 | 3142 |
| 3143 __ TryAllocate(compiler->double_class(), | 3143 __ TryAllocate(compiler->double_class(), |
| 3144 slow_path->entry_label(), | 3144 slow_path->entry_label(), |
| 3145 Assembler::kFarJump, | 3145 Assembler::kFarJump, |
| 3146 out_reg, | 3146 out_reg, |
| 3147 kNoRegister); | 3147 kNoRegister); |
| 3148 __ Bind(slow_path->exit_label()); | 3148 __ Bind(slow_path->exit_label()); |
| 3149 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); | 3149 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
| 3150 } | 3150 } |
| 3151 | 3151 |
| 3152 | 3152 |
| 3153 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const { | 3153 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const { |
| 3154 const intptr_t kNumInputs = 1; | 3154 const intptr_t kNumInputs = 1; |
| 3155 const intptr_t value_cid = value()->Type()->ToCid(); | 3155 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3156 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid)); | 3156 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid)); |
| 3157 const bool needs_writable_input = (value_cid == kSmiCid); | 3157 const bool needs_writable_input = (value_cid == kSmiCid); |
| 3158 const intptr_t kNumTemps = needs_temp ? 1 : 0; | 3158 const intptr_t kNumTemps = needs_temp ? 1 : 0; |
| 3159 LocationSummary* summary = | 3159 LocationSummary* summary = |
| 3160 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3160 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3161 summary->set_in(0, needs_writable_input | 3161 summary->set_in(0, needs_writable_input |
| 3162 ? Location::WritableRegister() | 3162 ? Location::WritableRegister() |
| 3163 : Location::RequiresRegister()); | 3163 : Location::RequiresRegister()); |
| 3164 if (needs_temp) summary->set_temp(0, Location::RequiresRegister()); | 3164 if (needs_temp) summary->set_temp(0, Location::RequiresRegister()); |
| 3165 summary->set_out(Location::RequiresFpuRegister()); | 3165 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3166 return summary; | 3166 return summary; |
| 3167 } | 3167 } |
| 3168 | 3168 |
| 3169 | 3169 |
| 3170 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3170 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3171 const intptr_t value_cid = value()->Type()->ToCid(); | 3171 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3172 const Register value = locs()->in(0).reg(); | 3172 const Register value = locs()->in(0).reg(); |
| 3173 const XmmRegister result = locs()->out().fpu_reg(); | 3173 const XmmRegister result = locs()->out(0).fpu_reg(); |
| 3174 | 3174 |
| 3175 if (value_cid == kDoubleCid) { | 3175 if (value_cid == kDoubleCid) { |
| 3176 __ movsd(result, FieldAddress(value, Double::value_offset())); | 3176 __ movsd(result, FieldAddress(value, Double::value_offset())); |
| 3177 } else if (value_cid == kSmiCid) { | 3177 } else if (value_cid == kSmiCid) { |
| 3178 __ SmiUntag(value); // Untag input before conversion. | 3178 __ SmiUntag(value); // Untag input before conversion. |
| 3179 __ cvtsi2sd(result, value); | 3179 __ cvtsi2sd(result, value); |
| 3180 } else { | 3180 } else { |
| 3181 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); | 3181 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
| 3182 Register temp = locs()->temp(0).reg(); | 3182 Register temp = locs()->temp(0).reg(); |
| 3183 Label is_smi, done; | 3183 Label is_smi, done; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3197 | 3197 |
| 3198 | 3198 |
| 3199 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(bool opt) const { | 3199 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(bool opt) const { |
| 3200 const intptr_t kNumInputs = 1; | 3200 const intptr_t kNumInputs = 1; |
| 3201 const intptr_t kNumTemps = 0; | 3201 const intptr_t kNumTemps = 0; |
| 3202 LocationSummary* summary = | 3202 LocationSummary* summary = |
| 3203 new LocationSummary(kNumInputs, | 3203 new LocationSummary(kNumInputs, |
| 3204 kNumTemps, | 3204 kNumTemps, |
| 3205 LocationSummary::kCallOnSlowPath); | 3205 LocationSummary::kCallOnSlowPath); |
| 3206 summary->set_in(0, Location::RequiresFpuRegister()); | 3206 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3207 summary->set_out(Location::RequiresRegister()); | 3207 summary->set_out(0, Location::RequiresRegister()); |
| 3208 return summary; | 3208 return summary; |
| 3209 } | 3209 } |
| 3210 | 3210 |
| 3211 | 3211 |
| 3212 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3212 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3213 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this); | 3213 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this); |
| 3214 compiler->AddSlowPathCode(slow_path); | 3214 compiler->AddSlowPathCode(slow_path); |
| 3215 | 3215 |
| 3216 Register out_reg = locs()->out().reg(); | 3216 Register out_reg = locs()->out(0).reg(); |
| 3217 XmmRegister value = locs()->in(0).fpu_reg(); | 3217 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3218 | 3218 |
| 3219 __ TryAllocate(compiler->float32x4_class(), | 3219 __ TryAllocate(compiler->float32x4_class(), |
| 3220 slow_path->entry_label(), | 3220 slow_path->entry_label(), |
| 3221 Assembler::kFarJump, | 3221 Assembler::kFarJump, |
| 3222 out_reg, | 3222 out_reg, |
| 3223 kNoRegister); | 3223 kNoRegister); |
| 3224 __ Bind(slow_path->exit_label()); | 3224 __ Bind(slow_path->exit_label()); |
| 3225 __ movups(FieldAddress(out_reg, Float32x4::value_offset()), value); | 3225 __ movups(FieldAddress(out_reg, Float32x4::value_offset()), value); |
| 3226 } | 3226 } |
| 3227 | 3227 |
| 3228 | 3228 |
| 3229 LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary(bool opt) const { | 3229 LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary(bool opt) const { |
| 3230 const intptr_t value_cid = value()->Type()->ToCid(); | 3230 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3231 const intptr_t kNumInputs = 1; | 3231 const intptr_t kNumInputs = 1; |
| 3232 const intptr_t kNumTemps = value_cid == kFloat32x4Cid ? 0 : 1; | 3232 const intptr_t kNumTemps = value_cid == kFloat32x4Cid ? 0 : 1; |
| 3233 LocationSummary* summary = | 3233 LocationSummary* summary = |
| 3234 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3234 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3235 summary->set_in(0, Location::RequiresRegister()); | 3235 summary->set_in(0, Location::RequiresRegister()); |
| 3236 if (kNumTemps > 0) { | 3236 if (kNumTemps > 0) { |
| 3237 ASSERT(kNumTemps == 1); | 3237 ASSERT(kNumTemps == 1); |
| 3238 summary->set_temp(0, Location::RequiresRegister()); | 3238 summary->set_temp(0, Location::RequiresRegister()); |
| 3239 } | 3239 } |
| 3240 summary->set_out(Location::RequiresFpuRegister()); | 3240 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3241 return summary; | 3241 return summary; |
| 3242 } | 3242 } |
| 3243 | 3243 |
| 3244 | 3244 |
| 3245 void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3245 void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3246 const intptr_t value_cid = value()->Type()->ToCid(); | 3246 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3247 const Register value = locs()->in(0).reg(); | 3247 const Register value = locs()->in(0).reg(); |
| 3248 const XmmRegister result = locs()->out().fpu_reg(); | 3248 const XmmRegister result = locs()->out(0).fpu_reg(); |
| 3249 | 3249 |
| 3250 if (value_cid != kFloat32x4Cid) { | 3250 if (value_cid != kFloat32x4Cid) { |
| 3251 const Register temp = locs()->temp(0).reg(); | 3251 const Register temp = locs()->temp(0).reg(); |
| 3252 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass); | 3252 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass); |
| 3253 __ testl(value, Immediate(kSmiTagMask)); | 3253 __ testl(value, Immediate(kSmiTagMask)); |
| 3254 __ j(ZERO, deopt); | 3254 __ j(ZERO, deopt); |
| 3255 __ CompareClassId(value, kFloat32x4Cid, temp); | 3255 __ CompareClassId(value, kFloat32x4Cid, temp); |
| 3256 __ j(NOT_EQUAL, deopt); | 3256 __ j(NOT_EQUAL, deopt); |
| 3257 } | 3257 } |
| 3258 __ movups(result, FieldAddress(value, Float32x4::value_offset())); | 3258 __ movups(result, FieldAddress(value, Float32x4::value_offset())); |
| 3259 } | 3259 } |
| 3260 | 3260 |
| 3261 | 3261 |
| 3262 LocationSummary* BoxFloat64x2Instr::MakeLocationSummary(bool opt) const { | 3262 LocationSummary* BoxFloat64x2Instr::MakeLocationSummary(bool opt) const { |
| 3263 const intptr_t kNumInputs = 1; | 3263 const intptr_t kNumInputs = 1; |
| 3264 const intptr_t kNumTemps = 0; | 3264 const intptr_t kNumTemps = 0; |
| 3265 LocationSummary* summary = | 3265 LocationSummary* summary = |
| 3266 new LocationSummary(kNumInputs, | 3266 new LocationSummary(kNumInputs, |
| 3267 kNumTemps, | 3267 kNumTemps, |
| 3268 LocationSummary::kCallOnSlowPath); | 3268 LocationSummary::kCallOnSlowPath); |
| 3269 summary->set_in(0, Location::RequiresFpuRegister()); | 3269 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3270 summary->set_out(Location::RequiresRegister()); | 3270 summary->set_out(0, Location::RequiresRegister()); |
| 3271 return summary; | 3271 return summary; |
| 3272 } | 3272 } |
| 3273 | 3273 |
| 3274 | 3274 |
| 3275 void BoxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3275 void BoxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3276 BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this); | 3276 BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this); |
| 3277 compiler->AddSlowPathCode(slow_path); | 3277 compiler->AddSlowPathCode(slow_path); |
| 3278 | 3278 |
| 3279 Register out_reg = locs()->out().reg(); | 3279 Register out_reg = locs()->out(0).reg(); |
| 3280 XmmRegister value = locs()->in(0).fpu_reg(); | 3280 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3281 | 3281 |
| 3282 __ TryAllocate(compiler->float64x2_class(), | 3282 __ TryAllocate(compiler->float64x2_class(), |
| 3283 slow_path->entry_label(), | 3283 slow_path->entry_label(), |
| 3284 Assembler::kFarJump, | 3284 Assembler::kFarJump, |
| 3285 out_reg, | 3285 out_reg, |
| 3286 kNoRegister); | 3286 kNoRegister); |
| 3287 __ Bind(slow_path->exit_label()); | 3287 __ Bind(slow_path->exit_label()); |
| 3288 __ movups(FieldAddress(out_reg, Float64x2::value_offset()), value); | 3288 __ movups(FieldAddress(out_reg, Float64x2::value_offset()), value); |
| 3289 } | 3289 } |
| 3290 | 3290 |
| 3291 | 3291 |
| 3292 LocationSummary* UnboxFloat64x2Instr::MakeLocationSummary(bool opt) const { | 3292 LocationSummary* UnboxFloat64x2Instr::MakeLocationSummary(bool opt) const { |
| 3293 const intptr_t value_cid = value()->Type()->ToCid(); | 3293 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3294 const intptr_t kNumInputs = 1; | 3294 const intptr_t kNumInputs = 1; |
| 3295 const intptr_t kNumTemps = value_cid == kFloat64x2Cid ? 0 : 1; | 3295 const intptr_t kNumTemps = value_cid == kFloat64x2Cid ? 0 : 1; |
| 3296 LocationSummary* summary = | 3296 LocationSummary* summary = |
| 3297 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3297 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3298 summary->set_in(0, Location::RequiresRegister()); | 3298 summary->set_in(0, Location::RequiresRegister()); |
| 3299 if (kNumTemps > 0) { | 3299 if (kNumTemps > 0) { |
| 3300 ASSERT(kNumTemps == 1); | 3300 ASSERT(kNumTemps == 1); |
| 3301 summary->set_temp(0, Location::RequiresRegister()); | 3301 summary->set_temp(0, Location::RequiresRegister()); |
| 3302 } | 3302 } |
| 3303 summary->set_out(Location::RequiresFpuRegister()); | 3303 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3304 return summary; | 3304 return summary; |
| 3305 } | 3305 } |
| 3306 | 3306 |
| 3307 | 3307 |
| 3308 void UnboxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3308 void UnboxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3309 const intptr_t value_cid = value()->Type()->ToCid(); | 3309 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3310 const Register value = locs()->in(0).reg(); | 3310 const Register value = locs()->in(0).reg(); |
| 3311 const XmmRegister result = locs()->out().fpu_reg(); | 3311 const XmmRegister result = locs()->out(0).fpu_reg(); |
| 3312 | 3312 |
| 3313 if (value_cid != kFloat64x2Cid) { | 3313 if (value_cid != kFloat64x2Cid) { |
| 3314 const Register temp = locs()->temp(0).reg(); | 3314 const Register temp = locs()->temp(0).reg(); |
| 3315 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass); | 3315 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass); |
| 3316 __ testl(value, Immediate(kSmiTagMask)); | 3316 __ testl(value, Immediate(kSmiTagMask)); |
| 3317 __ j(ZERO, deopt); | 3317 __ j(ZERO, deopt); |
| 3318 __ CompareClassId(value, kFloat64x2Cid, temp); | 3318 __ CompareClassId(value, kFloat64x2Cid, temp); |
| 3319 __ j(NOT_EQUAL, deopt); | 3319 __ j(NOT_EQUAL, deopt); |
| 3320 } | 3320 } |
| 3321 __ movups(result, FieldAddress(value, Float64x2::value_offset())); | 3321 __ movups(result, FieldAddress(value, Float64x2::value_offset())); |
| 3322 } | 3322 } |
| 3323 | 3323 |
| 3324 | 3324 |
| 3325 LocationSummary* BoxInt32x4Instr::MakeLocationSummary(bool opt) const { | 3325 LocationSummary* BoxInt32x4Instr::MakeLocationSummary(bool opt) const { |
| 3326 const intptr_t kNumInputs = 1; | 3326 const intptr_t kNumInputs = 1; |
| 3327 const intptr_t kNumTemps = 0; | 3327 const intptr_t kNumTemps = 0; |
| 3328 LocationSummary* summary = | 3328 LocationSummary* summary = |
| 3329 new LocationSummary(kNumInputs, | 3329 new LocationSummary(kNumInputs, |
| 3330 kNumTemps, | 3330 kNumTemps, |
| 3331 LocationSummary::kCallOnSlowPath); | 3331 LocationSummary::kCallOnSlowPath); |
| 3332 summary->set_in(0, Location::RequiresFpuRegister()); | 3332 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3333 summary->set_out(Location::RequiresRegister()); | 3333 summary->set_out(0, Location::RequiresRegister()); |
| 3334 return summary; | 3334 return summary; |
| 3335 } | 3335 } |
| 3336 | 3336 |
| 3337 | 3337 |
| 3338 class BoxInt32x4SlowPath : public SlowPathCode { | 3338 class BoxInt32x4SlowPath : public SlowPathCode { |
| 3339 public: | 3339 public: |
| 3340 explicit BoxInt32x4SlowPath(BoxInt32x4Instr* instruction) | 3340 explicit BoxInt32x4SlowPath(BoxInt32x4Instr* instruction) |
| 3341 : instruction_(instruction) { } | 3341 : instruction_(instruction) { } |
| 3342 | 3342 |
| 3343 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 3343 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3344 __ Comment("BoxInt32x4SlowPath"); | 3344 __ Comment("BoxInt32x4SlowPath"); |
| 3345 __ Bind(entry_label()); | 3345 __ Bind(entry_label()); |
| 3346 const Class& int32x4_class = compiler->int32x4_class(); | 3346 const Class& int32x4_class = compiler->int32x4_class(); |
| 3347 const Code& stub = | 3347 const Code& stub = |
| 3348 Code::Handle(StubCode::GetAllocationStubForClass(int32x4_class)); | 3348 Code::Handle(StubCode::GetAllocationStubForClass(int32x4_class)); |
| 3349 const ExternalLabel label(int32x4_class.ToCString(), stub.EntryPoint()); | 3349 const ExternalLabel label(int32x4_class.ToCString(), stub.EntryPoint()); |
| 3350 | 3350 |
| 3351 LocationSummary* locs = instruction_->locs(); | 3351 LocationSummary* locs = instruction_->locs(); |
| 3352 locs->live_registers()->Remove(locs->out()); | 3352 locs->live_registers()->Remove(locs->out(0)); |
| 3353 | 3353 |
| 3354 compiler->SaveLiveRegisters(locs); | 3354 compiler->SaveLiveRegisters(locs); |
| 3355 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 3355 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 3356 &label, | 3356 &label, |
| 3357 PcDescriptors::kOther, | 3357 PcDescriptors::kOther, |
| 3358 locs); | 3358 locs); |
| 3359 __ MoveRegister(locs->out().reg(), EAX); | 3359 __ MoveRegister(locs->out(0).reg(), EAX); |
| 3360 compiler->RestoreLiveRegisters(locs); | 3360 compiler->RestoreLiveRegisters(locs); |
| 3361 | 3361 |
| 3362 __ jmp(exit_label()); | 3362 __ jmp(exit_label()); |
| 3363 } | 3363 } |
| 3364 | 3364 |
| 3365 private: | 3365 private: |
| 3366 BoxInt32x4Instr* instruction_; | 3366 BoxInt32x4Instr* instruction_; |
| 3367 }; | 3367 }; |
| 3368 | 3368 |
| 3369 | 3369 |
| 3370 void BoxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3370 void BoxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3371 BoxInt32x4SlowPath* slow_path = new BoxInt32x4SlowPath(this); | 3371 BoxInt32x4SlowPath* slow_path = new BoxInt32x4SlowPath(this); |
| 3372 compiler->AddSlowPathCode(slow_path); | 3372 compiler->AddSlowPathCode(slow_path); |
| 3373 | 3373 |
| 3374 Register out_reg = locs()->out().reg(); | 3374 Register out_reg = locs()->out(0).reg(); |
| 3375 XmmRegister value = locs()->in(0).fpu_reg(); | 3375 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3376 | 3376 |
| 3377 __ TryAllocate(compiler->int32x4_class(), | 3377 __ TryAllocate(compiler->int32x4_class(), |
| 3378 slow_path->entry_label(), | 3378 slow_path->entry_label(), |
| 3379 Assembler::kFarJump, | 3379 Assembler::kFarJump, |
| 3380 out_reg, | 3380 out_reg, |
| 3381 kNoRegister); | 3381 kNoRegister); |
| 3382 __ Bind(slow_path->exit_label()); | 3382 __ Bind(slow_path->exit_label()); |
| 3383 __ movups(FieldAddress(out_reg, Int32x4::value_offset()), value); | 3383 __ movups(FieldAddress(out_reg, Int32x4::value_offset()), value); |
| 3384 } | 3384 } |
| 3385 | 3385 |
| 3386 | 3386 |
| 3387 LocationSummary* UnboxInt32x4Instr::MakeLocationSummary(bool opt) const { | 3387 LocationSummary* UnboxInt32x4Instr::MakeLocationSummary(bool opt) const { |
| 3388 const intptr_t value_cid = value()->Type()->ToCid(); | 3388 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3389 const intptr_t kNumInputs = 1; | 3389 const intptr_t kNumInputs = 1; |
| 3390 const intptr_t kNumTemps = value_cid == kInt32x4Cid ? 0 : 1; | 3390 const intptr_t kNumTemps = value_cid == kInt32x4Cid ? 0 : 1; |
| 3391 LocationSummary* summary = | 3391 LocationSummary* summary = |
| 3392 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3392 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3393 summary->set_in(0, Location::RequiresRegister()); | 3393 summary->set_in(0, Location::RequiresRegister()); |
| 3394 if (kNumTemps > 0) { | 3394 if (kNumTemps > 0) { |
| 3395 ASSERT(kNumTemps == 1); | 3395 ASSERT(kNumTemps == 1); |
| 3396 summary->set_temp(0, Location::RequiresRegister()); | 3396 summary->set_temp(0, Location::RequiresRegister()); |
| 3397 } | 3397 } |
| 3398 summary->set_out(Location::RequiresFpuRegister()); | 3398 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3399 return summary; | 3399 return summary; |
| 3400 } | 3400 } |
| 3401 | 3401 |
| 3402 | 3402 |
| 3403 void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3403 void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3404 const intptr_t value_cid = value()->Type()->ToCid(); | 3404 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3405 const Register value = locs()->in(0).reg(); | 3405 const Register value = locs()->in(0).reg(); |
| 3406 const XmmRegister result = locs()->out().fpu_reg(); | 3406 const XmmRegister result = locs()->out(0).fpu_reg(); |
| 3407 | 3407 |
| 3408 if (value_cid != kInt32x4Cid) { | 3408 if (value_cid != kInt32x4Cid) { |
| 3409 const Register temp = locs()->temp(0).reg(); | 3409 const Register temp = locs()->temp(0).reg(); |
| 3410 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass); | 3410 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass); |
| 3411 __ testl(value, Immediate(kSmiTagMask)); | 3411 __ testl(value, Immediate(kSmiTagMask)); |
| 3412 __ j(ZERO, deopt); | 3412 __ j(ZERO, deopt); |
| 3413 __ CompareClassId(value, kInt32x4Cid, temp); | 3413 __ CompareClassId(value, kInt32x4Cid, temp); |
| 3414 __ j(NOT_EQUAL, deopt); | 3414 __ j(NOT_EQUAL, deopt); |
| 3415 } | 3415 } |
| 3416 __ movups(result, FieldAddress(value, Int32x4::value_offset())); | 3416 __ movups(result, FieldAddress(value, Int32x4::value_offset())); |
| 3417 } | 3417 } |
| 3418 | 3418 |
| 3419 | 3419 |
| 3420 | 3420 |
| 3421 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(bool opt) const { | 3421 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(bool opt) const { |
| 3422 const intptr_t kNumInputs = 2; | 3422 const intptr_t kNumInputs = 2; |
| 3423 const intptr_t kNumTemps = 0; | 3423 const intptr_t kNumTemps = 0; |
| 3424 LocationSummary* summary = | 3424 LocationSummary* summary = |
| 3425 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3425 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3426 summary->set_in(0, Location::RequiresFpuRegister()); | 3426 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3427 summary->set_in(1, Location::RequiresFpuRegister()); | 3427 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3428 summary->set_out(Location::SameAsFirstInput()); | 3428 summary->set_out(0, Location::SameAsFirstInput()); |
| 3429 return summary; | 3429 return summary; |
| 3430 } | 3430 } |
| 3431 | 3431 |
| 3432 | 3432 |
| 3433 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3433 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3434 XmmRegister left = locs()->in(0).fpu_reg(); | 3434 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3435 XmmRegister right = locs()->in(1).fpu_reg(); | 3435 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3436 | 3436 |
| 3437 ASSERT(locs()->out().fpu_reg() == left); | 3437 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3438 | 3438 |
| 3439 switch (op_kind()) { | 3439 switch (op_kind()) { |
| 3440 case Token::kADD: __ addsd(left, right); break; | 3440 case Token::kADD: __ addsd(left, right); break; |
| 3441 case Token::kSUB: __ subsd(left, right); break; | 3441 case Token::kSUB: __ subsd(left, right); break; |
| 3442 case Token::kMUL: __ mulsd(left, right); break; | 3442 case Token::kMUL: __ mulsd(left, right); break; |
| 3443 case Token::kDIV: __ divsd(left, right); break; | 3443 case Token::kDIV: __ divsd(left, right); break; |
| 3444 default: UNREACHABLE(); | 3444 default: UNREACHABLE(); |
| 3445 } | 3445 } |
| 3446 } | 3446 } |
| 3447 | 3447 |
| 3448 | 3448 |
| 3449 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(bool opt) const { | 3449 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(bool opt) const { |
| 3450 const intptr_t kNumInputs = 2; | 3450 const intptr_t kNumInputs = 2; |
| 3451 const intptr_t kNumTemps = 0; | 3451 const intptr_t kNumTemps = 0; |
| 3452 LocationSummary* summary = | 3452 LocationSummary* summary = |
| 3453 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3453 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3454 summary->set_in(0, Location::RequiresFpuRegister()); | 3454 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3455 summary->set_in(1, Location::RequiresFpuRegister()); | 3455 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3456 summary->set_out(Location::SameAsFirstInput()); | 3456 summary->set_out(0, Location::SameAsFirstInput()); |
| 3457 return summary; | 3457 return summary; |
| 3458 } | 3458 } |
| 3459 | 3459 |
| 3460 | 3460 |
| 3461 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3461 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3462 XmmRegister left = locs()->in(0).fpu_reg(); | 3462 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3463 XmmRegister right = locs()->in(1).fpu_reg(); | 3463 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3464 | 3464 |
| 3465 ASSERT(locs()->out().fpu_reg() == left); | 3465 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3466 | 3466 |
| 3467 switch (op_kind()) { | 3467 switch (op_kind()) { |
| 3468 case Token::kADD: __ addps(left, right); break; | 3468 case Token::kADD: __ addps(left, right); break; |
| 3469 case Token::kSUB: __ subps(left, right); break; | 3469 case Token::kSUB: __ subps(left, right); break; |
| 3470 case Token::kMUL: __ mulps(left, right); break; | 3470 case Token::kMUL: __ mulps(left, right); break; |
| 3471 case Token::kDIV: __ divps(left, right); break; | 3471 case Token::kDIV: __ divps(left, right); break; |
| 3472 default: UNREACHABLE(); | 3472 default: UNREACHABLE(); |
| 3473 } | 3473 } |
| 3474 } | 3474 } |
| 3475 | 3475 |
| 3476 | 3476 |
| 3477 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(bool opt) const { | 3477 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(bool opt) const { |
| 3478 const intptr_t kNumInputs = 2; | 3478 const intptr_t kNumInputs = 2; |
| 3479 const intptr_t kNumTemps = 0; | 3479 const intptr_t kNumTemps = 0; |
| 3480 LocationSummary* summary = | 3480 LocationSummary* summary = |
| 3481 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3481 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3482 summary->set_in(0, Location::RequiresFpuRegister()); | 3482 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3483 summary->set_in(1, Location::RequiresFpuRegister()); | 3483 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3484 summary->set_out(Location::SameAsFirstInput()); | 3484 summary->set_out(0, Location::SameAsFirstInput()); |
| 3485 return summary; | 3485 return summary; |
| 3486 } | 3486 } |
| 3487 | 3487 |
| 3488 | 3488 |
| 3489 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3489 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3490 XmmRegister left = locs()->in(0).fpu_reg(); | 3490 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3491 XmmRegister right = locs()->in(1).fpu_reg(); | 3491 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3492 | 3492 |
| 3493 ASSERT(locs()->out().fpu_reg() == left); | 3493 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3494 | 3494 |
| 3495 switch (op_kind()) { | 3495 switch (op_kind()) { |
| 3496 case Token::kADD: __ addpd(left, right); break; | 3496 case Token::kADD: __ addpd(left, right); break; |
| 3497 case Token::kSUB: __ subpd(left, right); break; | 3497 case Token::kSUB: __ subpd(left, right); break; |
| 3498 case Token::kMUL: __ mulpd(left, right); break; | 3498 case Token::kMUL: __ mulpd(left, right); break; |
| 3499 case Token::kDIV: __ divpd(left, right); break; | 3499 case Token::kDIV: __ divpd(left, right); break; |
| 3500 default: UNREACHABLE(); | 3500 default: UNREACHABLE(); |
| 3501 } | 3501 } |
| 3502 } | 3502 } |
| 3503 | 3503 |
| 3504 | 3504 |
| 3505 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(bool opt) const { | 3505 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(bool opt) const { |
| 3506 const intptr_t kNumInputs = 1; | 3506 const intptr_t kNumInputs = 1; |
| 3507 const intptr_t kNumTemps = 0; | 3507 const intptr_t kNumTemps = 0; |
| 3508 LocationSummary* summary = | 3508 LocationSummary* summary = |
| 3509 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3509 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3510 summary->set_in(0, Location::RequiresFpuRegister()); | 3510 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3511 summary->set_out(Location::SameAsFirstInput()); | 3511 summary->set_out(0, Location::SameAsFirstInput()); |
| 3512 return summary; | 3512 return summary; |
| 3513 } | 3513 } |
| 3514 | 3514 |
| 3515 | 3515 |
| 3516 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3516 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3517 XmmRegister value = locs()->in(0).fpu_reg(); | 3517 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3518 | 3518 |
| 3519 ASSERT(locs()->out().fpu_reg() == value); | 3519 ASSERT(locs()->out(0).fpu_reg() == value); |
| 3520 | 3520 |
| 3521 switch (op_kind()) { | 3521 switch (op_kind()) { |
| 3522 case MethodRecognizer::kFloat32x4ShuffleX: | 3522 case MethodRecognizer::kFloat32x4ShuffleX: |
| 3523 // Shuffle not necessary. | 3523 // Shuffle not necessary. |
| 3524 __ cvtss2sd(value, value); | 3524 __ cvtss2sd(value, value); |
| 3525 break; | 3525 break; |
| 3526 case MethodRecognizer::kFloat32x4ShuffleY: | 3526 case MethodRecognizer::kFloat32x4ShuffleY: |
| 3527 __ shufps(value, value, Immediate(0x55)); | 3527 __ shufps(value, value, Immediate(0x55)); |
| 3528 __ cvtss2sd(value, value); | 3528 __ cvtss2sd(value, value); |
| 3529 break; | 3529 break; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3544 } | 3544 } |
| 3545 | 3545 |
| 3546 | 3546 |
| 3547 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(bool opt) const { | 3547 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(bool opt) const { |
| 3548 const intptr_t kNumInputs = 2; | 3548 const intptr_t kNumInputs = 2; |
| 3549 const intptr_t kNumTemps = 0; | 3549 const intptr_t kNumTemps = 0; |
| 3550 LocationSummary* summary = | 3550 LocationSummary* summary = |
| 3551 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3551 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3552 summary->set_in(0, Location::RequiresFpuRegister()); | 3552 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3553 summary->set_in(1, Location::RequiresFpuRegister()); | 3553 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3554 summary->set_out(Location::SameAsFirstInput()); | 3554 summary->set_out(0, Location::SameAsFirstInput()); |
| 3555 return summary; | 3555 return summary; |
| 3556 } | 3556 } |
| 3557 | 3557 |
| 3558 | 3558 |
| 3559 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3559 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3560 XmmRegister left = locs()->in(0).fpu_reg(); | 3560 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3561 XmmRegister right = locs()->in(1).fpu_reg(); | 3561 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3562 | 3562 |
| 3563 ASSERT(locs()->out().fpu_reg() == left); | 3563 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3564 switch (op_kind()) { | 3564 switch (op_kind()) { |
| 3565 case MethodRecognizer::kFloat32x4ShuffleMix: | 3565 case MethodRecognizer::kFloat32x4ShuffleMix: |
| 3566 case MethodRecognizer::kInt32x4ShuffleMix: | 3566 case MethodRecognizer::kInt32x4ShuffleMix: |
| 3567 __ shufps(left, right, Immediate(mask_)); | 3567 __ shufps(left, right, Immediate(mask_)); |
| 3568 break; | 3568 break; |
| 3569 default: UNREACHABLE(); | 3569 default: UNREACHABLE(); |
| 3570 } | 3570 } |
| 3571 } | 3571 } |
| 3572 | 3572 |
| 3573 | 3573 |
| 3574 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(bool opt) const { | 3574 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(bool opt) const { |
| 3575 const intptr_t kNumInputs = 1; | 3575 const intptr_t kNumInputs = 1; |
| 3576 const intptr_t kNumTemps = 0; | 3576 const intptr_t kNumTemps = 0; |
| 3577 LocationSummary* summary = | 3577 LocationSummary* summary = |
| 3578 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3578 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3579 summary->set_in(0, Location::RequiresFpuRegister()); | 3579 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3580 summary->set_out(Location::RequiresRegister()); | 3580 summary->set_out(0, Location::RequiresRegister()); |
| 3581 return summary; | 3581 return summary; |
| 3582 } | 3582 } |
| 3583 | 3583 |
| 3584 | 3584 |
| 3585 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3585 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3586 XmmRegister value = locs()->in(0).fpu_reg(); | 3586 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3587 Register out = locs()->out().reg(); | 3587 Register out = locs()->out(0).reg(); |
| 3588 | 3588 |
| 3589 __ movmskps(out, value); | 3589 __ movmskps(out, value); |
| 3590 __ SmiTag(out); | 3590 __ SmiTag(out); |
| 3591 } | 3591 } |
| 3592 | 3592 |
| 3593 | 3593 |
| 3594 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 3594 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
| 3595 bool opt) const { | 3595 bool opt) const { |
| 3596 const intptr_t kNumInputs = 4; | 3596 const intptr_t kNumInputs = 4; |
| 3597 const intptr_t kNumTemps = 0; | 3597 const intptr_t kNumTemps = 0; |
| 3598 LocationSummary* summary = | 3598 LocationSummary* summary = |
| 3599 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3599 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3600 summary->set_in(0, Location::RequiresFpuRegister()); | 3600 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3601 summary->set_in(1, Location::RequiresFpuRegister()); | 3601 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3602 summary->set_in(2, Location::RequiresFpuRegister()); | 3602 summary->set_in(2, Location::RequiresFpuRegister()); |
| 3603 summary->set_in(3, Location::RequiresFpuRegister()); | 3603 summary->set_in(3, Location::RequiresFpuRegister()); |
| 3604 summary->set_out(Location::SameAsFirstInput()); | 3604 summary->set_out(0, Location::SameAsFirstInput()); |
| 3605 return summary; | 3605 return summary; |
| 3606 } | 3606 } |
| 3607 | 3607 |
| 3608 | 3608 |
| 3609 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3609 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3610 XmmRegister v0 = locs()->in(0).fpu_reg(); | 3610 XmmRegister v0 = locs()->in(0).fpu_reg(); |
| 3611 XmmRegister v1 = locs()->in(1).fpu_reg(); | 3611 XmmRegister v1 = locs()->in(1).fpu_reg(); |
| 3612 XmmRegister v2 = locs()->in(2).fpu_reg(); | 3612 XmmRegister v2 = locs()->in(2).fpu_reg(); |
| 3613 XmmRegister v3 = locs()->in(3).fpu_reg(); | 3613 XmmRegister v3 = locs()->in(3).fpu_reg(); |
| 3614 ASSERT(v0 == locs()->out().fpu_reg()); | 3614 ASSERT(v0 == locs()->out(0).fpu_reg()); |
| 3615 __ subl(ESP, Immediate(16)); | 3615 __ subl(ESP, Immediate(16)); |
| 3616 __ cvtsd2ss(v0, v0); | 3616 __ cvtsd2ss(v0, v0); |
| 3617 __ movss(Address(ESP, 0), v0); | 3617 __ movss(Address(ESP, 0), v0); |
| 3618 __ movsd(v0, v1); | 3618 __ movsd(v0, v1); |
| 3619 __ cvtsd2ss(v0, v0); | 3619 __ cvtsd2ss(v0, v0); |
| 3620 __ movss(Address(ESP, 4), v0); | 3620 __ movss(Address(ESP, 4), v0); |
| 3621 __ movsd(v0, v2); | 3621 __ movsd(v0, v2); |
| 3622 __ cvtsd2ss(v0, v0); | 3622 __ cvtsd2ss(v0, v0); |
| 3623 __ movss(Address(ESP, 8), v0); | 3623 __ movss(Address(ESP, 8), v0); |
| 3624 __ movsd(v0, v3); | 3624 __ movsd(v0, v3); |
| 3625 __ cvtsd2ss(v0, v0); | 3625 __ cvtsd2ss(v0, v0); |
| 3626 __ movss(Address(ESP, 12), v0); | 3626 __ movss(Address(ESP, 12), v0); |
| 3627 __ movups(v0, Address(ESP, 0)); | 3627 __ movups(v0, Address(ESP, 0)); |
| 3628 __ addl(ESP, Immediate(16)); | 3628 __ addl(ESP, Immediate(16)); |
| 3629 } | 3629 } |
| 3630 | 3630 |
| 3631 | 3631 |
| 3632 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(bool opt) const { | 3632 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(bool opt) const { |
| 3633 const intptr_t kNumInputs = 0; | 3633 const intptr_t kNumInputs = 0; |
| 3634 const intptr_t kNumTemps = 0; | 3634 const intptr_t kNumTemps = 0; |
| 3635 LocationSummary* summary = | 3635 LocationSummary* summary = |
| 3636 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3636 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3637 summary->set_out(Location::RequiresFpuRegister()); | 3637 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3638 return summary; | 3638 return summary; |
| 3639 } | 3639 } |
| 3640 | 3640 |
| 3641 | 3641 |
| 3642 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3642 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3643 XmmRegister value = locs()->out().fpu_reg(); | 3643 XmmRegister value = locs()->out(0).fpu_reg(); |
| 3644 __ xorps(value, value); | 3644 __ xorps(value, value); |
| 3645 } | 3645 } |
| 3646 | 3646 |
| 3647 | 3647 |
| 3648 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(bool opt) const { | 3648 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(bool opt) const { |
| 3649 const intptr_t kNumInputs = 1; | 3649 const intptr_t kNumInputs = 1; |
| 3650 const intptr_t kNumTemps = 0; | 3650 const intptr_t kNumTemps = 0; |
| 3651 LocationSummary* summary = | 3651 LocationSummary* summary = |
| 3652 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3652 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3653 summary->set_in(0, Location::RequiresFpuRegister()); | 3653 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3654 summary->set_out(Location::SameAsFirstInput()); | 3654 summary->set_out(0, Location::SameAsFirstInput()); |
| 3655 return summary; | 3655 return summary; |
| 3656 } | 3656 } |
| 3657 | 3657 |
| 3658 | 3658 |
| 3659 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3659 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3660 XmmRegister value = locs()->out().fpu_reg(); | 3660 XmmRegister value = locs()->out(0).fpu_reg(); |
| 3661 ASSERT(locs()->in(0).fpu_reg() == locs()->out().fpu_reg()); | 3661 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); |
| 3662 // Convert to Float32. | 3662 // Convert to Float32. |
| 3663 __ cvtsd2ss(value, value); | 3663 __ cvtsd2ss(value, value); |
| 3664 // Splat across all lanes. | 3664 // Splat across all lanes. |
| 3665 __ shufps(value, value, Immediate(0x00)); | 3665 __ shufps(value, value, Immediate(0x00)); |
| 3666 } | 3666 } |
| 3667 | 3667 |
| 3668 | 3668 |
| 3669 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(bool opt) const { | 3669 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(bool opt) const { |
| 3670 const intptr_t kNumInputs = 2; | 3670 const intptr_t kNumInputs = 2; |
| 3671 const intptr_t kNumTemps = 0; | 3671 const intptr_t kNumTemps = 0; |
| 3672 LocationSummary* summary = | 3672 LocationSummary* summary = |
| 3673 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3673 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3674 summary->set_in(0, Location::RequiresFpuRegister()); | 3674 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3675 summary->set_in(1, Location::RequiresFpuRegister()); | 3675 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3676 summary->set_out(Location::SameAsFirstInput()); | 3676 summary->set_out(0, Location::SameAsFirstInput()); |
| 3677 return summary; | 3677 return summary; |
| 3678 } | 3678 } |
| 3679 | 3679 |
| 3680 | 3680 |
| 3681 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3681 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3682 XmmRegister left = locs()->in(0).fpu_reg(); | 3682 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3683 XmmRegister right = locs()->in(1).fpu_reg(); | 3683 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3684 | 3684 |
| 3685 ASSERT(locs()->out().fpu_reg() == left); | 3685 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3686 | 3686 |
| 3687 switch (op_kind()) { | 3687 switch (op_kind()) { |
| 3688 case MethodRecognizer::kFloat32x4Equal: | 3688 case MethodRecognizer::kFloat32x4Equal: |
| 3689 __ cmppseq(left, right); | 3689 __ cmppseq(left, right); |
| 3690 break; | 3690 break; |
| 3691 case MethodRecognizer::kFloat32x4NotEqual: | 3691 case MethodRecognizer::kFloat32x4NotEqual: |
| 3692 __ cmppsneq(left, right); | 3692 __ cmppsneq(left, right); |
| 3693 break; | 3693 break; |
| 3694 case MethodRecognizer::kFloat32x4GreaterThan: | 3694 case MethodRecognizer::kFloat32x4GreaterThan: |
| 3695 __ cmppsnle(left, right); | 3695 __ cmppsnle(left, right); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3709 } | 3709 } |
| 3710 | 3710 |
| 3711 | 3711 |
| 3712 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(bool opt) const { | 3712 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(bool opt) const { |
| 3713 const intptr_t kNumInputs = 2; | 3713 const intptr_t kNumInputs = 2; |
| 3714 const intptr_t kNumTemps = 0; | 3714 const intptr_t kNumTemps = 0; |
| 3715 LocationSummary* summary = | 3715 LocationSummary* summary = |
| 3716 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3716 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3717 summary->set_in(0, Location::RequiresFpuRegister()); | 3717 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3718 summary->set_in(1, Location::RequiresFpuRegister()); | 3718 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3719 summary->set_out(Location::SameAsFirstInput()); | 3719 summary->set_out(0, Location::SameAsFirstInput()); |
| 3720 return summary; | 3720 return summary; |
| 3721 } | 3721 } |
| 3722 | 3722 |
| 3723 | 3723 |
| 3724 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3724 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3725 XmmRegister left = locs()->in(0).fpu_reg(); | 3725 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3726 XmmRegister right = locs()->in(1).fpu_reg(); | 3726 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3727 | 3727 |
| 3728 ASSERT(locs()->out().fpu_reg() == left); | 3728 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3729 | 3729 |
| 3730 switch (op_kind()) { | 3730 switch (op_kind()) { |
| 3731 case MethodRecognizer::kFloat32x4Min: | 3731 case MethodRecognizer::kFloat32x4Min: |
| 3732 __ minps(left, right); | 3732 __ minps(left, right); |
| 3733 break; | 3733 break; |
| 3734 case MethodRecognizer::kFloat32x4Max: | 3734 case MethodRecognizer::kFloat32x4Max: |
| 3735 __ maxps(left, right); | 3735 __ maxps(left, right); |
| 3736 break; | 3736 break; |
| 3737 default: UNREACHABLE(); | 3737 default: UNREACHABLE(); |
| 3738 } | 3738 } |
| 3739 } | 3739 } |
| 3740 | 3740 |
| 3741 | 3741 |
| 3742 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(bool opt) const { | 3742 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(bool opt) const { |
| 3743 const intptr_t kNumInputs = 2; | 3743 const intptr_t kNumInputs = 2; |
| 3744 const intptr_t kNumTemps = 0; | 3744 const intptr_t kNumTemps = 0; |
| 3745 LocationSummary* summary = | 3745 LocationSummary* summary = |
| 3746 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3746 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3747 summary->set_in(0, Location::RequiresFpuRegister()); | 3747 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3748 summary->set_in(1, Location::RequiresFpuRegister()); | 3748 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3749 summary->set_out(Location::SameAsFirstInput()); | 3749 summary->set_out(0, Location::SameAsFirstInput()); |
| 3750 return summary; | 3750 return summary; |
| 3751 } | 3751 } |
| 3752 | 3752 |
| 3753 | 3753 |
| 3754 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3754 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3755 XmmRegister left = locs()->in(0).fpu_reg(); | 3755 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3756 XmmRegister right = locs()->in(1).fpu_reg(); | 3756 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3757 | 3757 |
| 3758 ASSERT(locs()->out().fpu_reg() == left); | 3758 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3759 | 3759 |
| 3760 switch (op_kind()) { | 3760 switch (op_kind()) { |
| 3761 case MethodRecognizer::kFloat32x4Scale: | 3761 case MethodRecognizer::kFloat32x4Scale: |
| 3762 __ cvtsd2ss(left, left); | 3762 __ cvtsd2ss(left, left); |
| 3763 __ shufps(left, left, Immediate(0x00)); | 3763 __ shufps(left, left, Immediate(0x00)); |
| 3764 __ mulps(left, right); | 3764 __ mulps(left, right); |
| 3765 break; | 3765 break; |
| 3766 default: UNREACHABLE(); | 3766 default: UNREACHABLE(); |
| 3767 } | 3767 } |
| 3768 } | 3768 } |
| 3769 | 3769 |
| 3770 | 3770 |
| 3771 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(bool opt) const { | 3771 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(bool opt) const { |
| 3772 const intptr_t kNumInputs = 1; | 3772 const intptr_t kNumInputs = 1; |
| 3773 const intptr_t kNumTemps = 0; | 3773 const intptr_t kNumTemps = 0; |
| 3774 LocationSummary* summary = | 3774 LocationSummary* summary = |
| 3775 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3775 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3776 summary->set_in(0, Location::RequiresFpuRegister()); | 3776 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3777 summary->set_out(Location::SameAsFirstInput()); | 3777 summary->set_out(0, Location::SameAsFirstInput()); |
| 3778 return summary; | 3778 return summary; |
| 3779 } | 3779 } |
| 3780 | 3780 |
| 3781 | 3781 |
| 3782 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3782 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3783 XmmRegister left = locs()->in(0).fpu_reg(); | 3783 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3784 | 3784 |
| 3785 ASSERT(locs()->out().fpu_reg() == left); | 3785 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3786 | 3786 |
| 3787 switch (op_kind()) { | 3787 switch (op_kind()) { |
| 3788 case MethodRecognizer::kFloat32x4Sqrt: | 3788 case MethodRecognizer::kFloat32x4Sqrt: |
| 3789 __ sqrtps(left); | 3789 __ sqrtps(left); |
| 3790 break; | 3790 break; |
| 3791 case MethodRecognizer::kFloat32x4Reciprocal: | 3791 case MethodRecognizer::kFloat32x4Reciprocal: |
| 3792 __ reciprocalps(left); | 3792 __ reciprocalps(left); |
| 3793 break; | 3793 break; |
| 3794 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 3794 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
| 3795 __ rsqrtps(left); | 3795 __ rsqrtps(left); |
| 3796 break; | 3796 break; |
| 3797 default: UNREACHABLE(); | 3797 default: UNREACHABLE(); |
| 3798 } | 3798 } |
| 3799 } | 3799 } |
| 3800 | 3800 |
| 3801 | 3801 |
| 3802 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(bool opt) const { | 3802 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(bool opt) const { |
| 3803 const intptr_t kNumInputs = 1; | 3803 const intptr_t kNumInputs = 1; |
| 3804 const intptr_t kNumTemps = 0; | 3804 const intptr_t kNumTemps = 0; |
| 3805 LocationSummary* summary = | 3805 LocationSummary* summary = |
| 3806 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3806 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3807 summary->set_in(0, Location::RequiresFpuRegister()); | 3807 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3808 summary->set_out(Location::SameAsFirstInput()); | 3808 summary->set_out(0, Location::SameAsFirstInput()); |
| 3809 return summary; | 3809 return summary; |
| 3810 } | 3810 } |
| 3811 | 3811 |
| 3812 | 3812 |
| 3813 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3813 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3814 XmmRegister left = locs()->in(0).fpu_reg(); | 3814 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3815 | 3815 |
| 3816 ASSERT(locs()->out().fpu_reg() == left); | 3816 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3817 switch (op_kind()) { | 3817 switch (op_kind()) { |
| 3818 case MethodRecognizer::kFloat32x4Negate: | 3818 case MethodRecognizer::kFloat32x4Negate: |
| 3819 __ negateps(left); | 3819 __ negateps(left); |
| 3820 break; | 3820 break; |
| 3821 case MethodRecognizer::kFloat32x4Absolute: | 3821 case MethodRecognizer::kFloat32x4Absolute: |
| 3822 __ absps(left); | 3822 __ absps(left); |
| 3823 break; | 3823 break; |
| 3824 default: UNREACHABLE(); | 3824 default: UNREACHABLE(); |
| 3825 } | 3825 } |
| 3826 } | 3826 } |
| 3827 | 3827 |
| 3828 | 3828 |
| 3829 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(bool opt) const { | 3829 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(bool opt) const { |
| 3830 const intptr_t kNumInputs = 3; | 3830 const intptr_t kNumInputs = 3; |
| 3831 const intptr_t kNumTemps = 0; | 3831 const intptr_t kNumTemps = 0; |
| 3832 LocationSummary* summary = | 3832 LocationSummary* summary = |
| 3833 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3833 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3834 summary->set_in(0, Location::RequiresFpuRegister()); | 3834 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3835 summary->set_in(1, Location::RequiresFpuRegister()); | 3835 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3836 summary->set_in(2, Location::RequiresFpuRegister()); | 3836 summary->set_in(2, Location::RequiresFpuRegister()); |
| 3837 summary->set_out(Location::SameAsFirstInput()); | 3837 summary->set_out(0, Location::SameAsFirstInput()); |
| 3838 return summary; | 3838 return summary; |
| 3839 } | 3839 } |
| 3840 | 3840 |
| 3841 | 3841 |
| 3842 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3842 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3843 XmmRegister left = locs()->in(0).fpu_reg(); | 3843 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3844 XmmRegister lower = locs()->in(1).fpu_reg(); | 3844 XmmRegister lower = locs()->in(1).fpu_reg(); |
| 3845 XmmRegister upper = locs()->in(2).fpu_reg(); | 3845 XmmRegister upper = locs()->in(2).fpu_reg(); |
| 3846 ASSERT(locs()->out().fpu_reg() == left); | 3846 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3847 __ minps(left, upper); | 3847 __ minps(left, upper); |
| 3848 __ maxps(left, lower); | 3848 __ maxps(left, lower); |
| 3849 } | 3849 } |
| 3850 | 3850 |
| 3851 | 3851 |
| 3852 LocationSummary* Float32x4WithInstr::MakeLocationSummary(bool opt) const { | 3852 LocationSummary* Float32x4WithInstr::MakeLocationSummary(bool opt) const { |
| 3853 const intptr_t kNumInputs = 2; | 3853 const intptr_t kNumInputs = 2; |
| 3854 const intptr_t kNumTemps = 0; | 3854 const intptr_t kNumTemps = 0; |
| 3855 LocationSummary* summary = | 3855 LocationSummary* summary = |
| 3856 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3856 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3857 summary->set_in(0, Location::RequiresFpuRegister()); | 3857 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3858 summary->set_in(1, Location::RequiresFpuRegister()); | 3858 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3859 summary->set_out(Location::SameAsFirstInput()); | 3859 summary->set_out(0, Location::SameAsFirstInput()); |
| 3860 return summary; | 3860 return summary; |
| 3861 } | 3861 } |
| 3862 | 3862 |
| 3863 | 3863 |
| 3864 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3864 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3865 XmmRegister replacement = locs()->in(0).fpu_reg(); | 3865 XmmRegister replacement = locs()->in(0).fpu_reg(); |
| 3866 XmmRegister value = locs()->in(1).fpu_reg(); | 3866 XmmRegister value = locs()->in(1).fpu_reg(); |
| 3867 | 3867 |
| 3868 ASSERT(locs()->out().fpu_reg() == replacement); | 3868 ASSERT(locs()->out(0).fpu_reg() == replacement); |
| 3869 | 3869 |
| 3870 switch (op_kind()) { | 3870 switch (op_kind()) { |
| 3871 case MethodRecognizer::kFloat32x4WithX: | 3871 case MethodRecognizer::kFloat32x4WithX: |
| 3872 __ cvtsd2ss(replacement, replacement); | 3872 __ cvtsd2ss(replacement, replacement); |
| 3873 __ subl(ESP, Immediate(16)); | 3873 __ subl(ESP, Immediate(16)); |
| 3874 // Move value to stack. | 3874 // Move value to stack. |
| 3875 __ movups(Address(ESP, 0), value); | 3875 __ movups(Address(ESP, 0), value); |
| 3876 // Write over X value. | 3876 // Write over X value. |
| 3877 __ movss(Address(ESP, 0), replacement); | 3877 __ movss(Address(ESP, 0), replacement); |
| 3878 // Move updated value into output register. | 3878 // Move updated value into output register. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3916 } | 3916 } |
| 3917 } | 3917 } |
| 3918 | 3918 |
| 3919 | 3919 |
| 3920 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(bool opt) const { | 3920 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(bool opt) const { |
| 3921 const intptr_t kNumInputs = 1; | 3921 const intptr_t kNumInputs = 1; |
| 3922 const intptr_t kNumTemps = 0; | 3922 const intptr_t kNumTemps = 0; |
| 3923 LocationSummary* summary = | 3923 LocationSummary* summary = |
| 3924 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3924 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3925 summary->set_in(0, Location::RequiresFpuRegister()); | 3925 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3926 summary->set_out(Location::SameAsFirstInput()); | 3926 summary->set_out(0, Location::SameAsFirstInput()); |
| 3927 return summary; | 3927 return summary; |
| 3928 } | 3928 } |
| 3929 | 3929 |
| 3930 | 3930 |
| 3931 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3931 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3932 // NOP. | 3932 // NOP. |
| 3933 } | 3933 } |
| 3934 | 3934 |
| 3935 | 3935 |
| 3936 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(bool opt) const { | 3936 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(bool opt) const { |
| 3937 const intptr_t kNumInputs = 1; | 3937 const intptr_t kNumInputs = 1; |
| 3938 const intptr_t kNumTemps = 0; | 3938 const intptr_t kNumTemps = 0; |
| 3939 LocationSummary* summary = | 3939 LocationSummary* summary = |
| 3940 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3940 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3941 summary->set_in(0, Location::RequiresFpuRegister()); | 3941 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3942 summary->set_out(Location::SameAsFirstInput()); | 3942 summary->set_out(0, Location::SameAsFirstInput()); |
| 3943 return summary; | 3943 return summary; |
| 3944 } | 3944 } |
| 3945 | 3945 |
| 3946 | 3946 |
| 3947 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3947 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3948 XmmRegister value = locs()->in(0).fpu_reg(); | 3948 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3949 | 3949 |
| 3950 ASSERT(locs()->out().fpu_reg() == value); | 3950 ASSERT(locs()->out(0).fpu_reg() == value); |
| 3951 | 3951 |
| 3952 switch (op_kind()) { | 3952 switch (op_kind()) { |
| 3953 case MethodRecognizer::kFloat64x2GetX: | 3953 case MethodRecognizer::kFloat64x2GetX: |
| 3954 // nop. | 3954 // nop. |
| 3955 break; | 3955 break; |
| 3956 case MethodRecognizer::kFloat64x2GetY: | 3956 case MethodRecognizer::kFloat64x2GetY: |
| 3957 __ shufpd(value, value, Immediate(0x33)); | 3957 __ shufpd(value, value, Immediate(0x33)); |
| 3958 break; | 3958 break; |
| 3959 default: UNREACHABLE(); | 3959 default: UNREACHABLE(); |
| 3960 } | 3960 } |
| 3961 } | 3961 } |
| 3962 | 3962 |
| 3963 | 3963 |
| 3964 | 3964 |
| 3965 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(bool opt) const { | 3965 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(bool opt) const { |
| 3966 const intptr_t kNumInputs = 0; | 3966 const intptr_t kNumInputs = 0; |
| 3967 const intptr_t kNumTemps = 0; | 3967 const intptr_t kNumTemps = 0; |
| 3968 LocationSummary* summary = | 3968 LocationSummary* summary = |
| 3969 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3969 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3970 summary->set_out(Location::RequiresFpuRegister()); | 3970 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3971 return summary; | 3971 return summary; |
| 3972 } | 3972 } |
| 3973 | 3973 |
| 3974 | 3974 |
| 3975 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3975 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3976 XmmRegister value = locs()->out().fpu_reg(); | 3976 XmmRegister value = locs()->out(0).fpu_reg(); |
| 3977 __ xorpd(value, value); | 3977 __ xorpd(value, value); |
| 3978 } | 3978 } |
| 3979 | 3979 |
| 3980 | 3980 |
| 3981 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(bool opt) const { | 3981 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(bool opt) const { |
| 3982 const intptr_t kNumInputs = 1; | 3982 const intptr_t kNumInputs = 1; |
| 3983 const intptr_t kNumTemps = 0; | 3983 const intptr_t kNumTemps = 0; |
| 3984 LocationSummary* summary = | 3984 LocationSummary* summary = |
| 3985 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3985 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3986 summary->set_in(0, Location::RequiresFpuRegister()); | 3986 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3987 summary->set_out(Location::SameAsFirstInput()); | 3987 summary->set_out(0, Location::SameAsFirstInput()); |
| 3988 return summary; | 3988 return summary; |
| 3989 } | 3989 } |
| 3990 | 3990 |
| 3991 | 3991 |
| 3992 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3992 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3993 XmmRegister value = locs()->out().fpu_reg(); | 3993 XmmRegister value = locs()->out(0).fpu_reg(); |
| 3994 __ shufpd(value, value, Immediate(0x0)); | 3994 __ shufpd(value, value, Immediate(0x0)); |
| 3995 } | 3995 } |
| 3996 | 3996 |
| 3997 | 3997 |
| 3998 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 3998 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
| 3999 bool opt) const { | 3999 bool opt) const { |
| 4000 const intptr_t kNumInputs = 2; | 4000 const intptr_t kNumInputs = 2; |
| 4001 const intptr_t kNumTemps = 0; | 4001 const intptr_t kNumTemps = 0; |
| 4002 LocationSummary* summary = | 4002 LocationSummary* summary = |
| 4003 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4003 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4004 summary->set_in(0, Location::RequiresFpuRegister()); | 4004 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4005 summary->set_in(1, Location::RequiresFpuRegister()); | 4005 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4006 summary->set_out(Location::SameAsFirstInput()); | 4006 summary->set_out(0, Location::SameAsFirstInput()); |
| 4007 return summary; | 4007 return summary; |
| 4008 } | 4008 } |
| 4009 | 4009 |
| 4010 | 4010 |
| 4011 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4011 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4012 XmmRegister v0 = locs()->in(0).fpu_reg(); | 4012 XmmRegister v0 = locs()->in(0).fpu_reg(); |
| 4013 XmmRegister v1 = locs()->in(1).fpu_reg(); | 4013 XmmRegister v1 = locs()->in(1).fpu_reg(); |
| 4014 ASSERT(v0 == locs()->out().fpu_reg()); | 4014 ASSERT(v0 == locs()->out(0).fpu_reg()); |
| 4015 __ subl(ESP, Immediate(16)); | 4015 __ subl(ESP, Immediate(16)); |
| 4016 __ movsd(Address(ESP, 0), v0); | 4016 __ movsd(Address(ESP, 0), v0); |
| 4017 __ movsd(Address(ESP, 8), v1); | 4017 __ movsd(Address(ESP, 8), v1); |
| 4018 __ movups(v0, Address(ESP, 0)); | 4018 __ movups(v0, Address(ESP, 0)); |
| 4019 __ addl(ESP, Immediate(16)); | 4019 __ addl(ESP, Immediate(16)); |
| 4020 } | 4020 } |
| 4021 | 4021 |
| 4022 | 4022 |
| 4023 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4023 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
| 4024 bool opt) const { | 4024 bool opt) const { |
| 4025 const intptr_t kNumInputs = 1; | 4025 const intptr_t kNumInputs = 1; |
| 4026 const intptr_t kNumTemps = 0; | 4026 const intptr_t kNumTemps = 0; |
| 4027 LocationSummary* summary = | 4027 LocationSummary* summary = |
| 4028 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4028 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4029 summary->set_in(0, Location::RequiresFpuRegister()); | 4029 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4030 summary->set_out(Location::SameAsFirstInput()); | 4030 summary->set_out(0, Location::SameAsFirstInput()); |
| 4031 return summary; | 4031 return summary; |
| 4032 } | 4032 } |
| 4033 | 4033 |
| 4034 | 4034 |
| 4035 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4035 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4036 XmmRegister value = locs()->out().fpu_reg(); | 4036 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4037 __ cvtpd2ps(value, value); | 4037 __ cvtpd2ps(value, value); |
| 4038 } | 4038 } |
| 4039 | 4039 |
| 4040 | 4040 |
| 4041 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4041 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
| 4042 bool opt) const { | 4042 bool opt) const { |
| 4043 const intptr_t kNumInputs = 1; | 4043 const intptr_t kNumInputs = 1; |
| 4044 const intptr_t kNumTemps = 0; | 4044 const intptr_t kNumTemps = 0; |
| 4045 LocationSummary* summary = | 4045 LocationSummary* summary = |
| 4046 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4046 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4047 summary->set_in(0, Location::RequiresFpuRegister()); | 4047 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4048 summary->set_out(Location::SameAsFirstInput()); | 4048 summary->set_out(0, Location::SameAsFirstInput()); |
| 4049 return summary; | 4049 return summary; |
| 4050 } | 4050 } |
| 4051 | 4051 |
| 4052 | 4052 |
| 4053 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4053 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4054 XmmRegister value = locs()->out().fpu_reg(); | 4054 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4055 __ cvtps2pd(value, value); | 4055 __ cvtps2pd(value, value); |
| 4056 } | 4056 } |
| 4057 | 4057 |
| 4058 | 4058 |
| 4059 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(bool opt) const { | 4059 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(bool opt) const { |
| 4060 const intptr_t kNumInputs = 1; | 4060 const intptr_t kNumInputs = 1; |
| 4061 const intptr_t kNumTemps = 0; | 4061 const intptr_t kNumTemps = 0; |
| 4062 LocationSummary* summary = | 4062 LocationSummary* summary = |
| 4063 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4063 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4064 summary->set_in(0, Location::RequiresFpuRegister()); | 4064 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4065 if (representation() == kTagged) { | 4065 if (representation() == kTagged) { |
| 4066 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4066 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
| 4067 summary->set_out(Location::RequiresRegister()); | 4067 summary->set_out(0, Location::RequiresRegister()); |
| 4068 } else { | 4068 } else { |
| 4069 ASSERT(representation() == kUnboxedFloat64x2); | 4069 ASSERT(representation() == kUnboxedFloat64x2); |
| 4070 summary->set_out(Location::SameAsFirstInput()); | 4070 summary->set_out(0, Location::SameAsFirstInput()); |
| 4071 } | 4071 } |
| 4072 return summary; | 4072 return summary; |
| 4073 } | 4073 } |
| 4074 | 4074 |
| 4075 | 4075 |
| 4076 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4076 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4077 XmmRegister left = locs()->in(0).fpu_reg(); | 4077 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4078 | 4078 |
| 4079 ASSERT((op_kind() == MethodRecognizer::kFloat64x2GetSignMask) || | 4079 ASSERT((op_kind() == MethodRecognizer::kFloat64x2GetSignMask) || |
| 4080 (locs()->out().fpu_reg() == left)); | 4080 (locs()->out(0).fpu_reg() == left)); |
| 4081 | 4081 |
| 4082 switch (op_kind()) { | 4082 switch (op_kind()) { |
| 4083 case MethodRecognizer::kFloat64x2Negate: | 4083 case MethodRecognizer::kFloat64x2Negate: |
| 4084 __ negatepd(left); | 4084 __ negatepd(left); |
| 4085 break; | 4085 break; |
| 4086 case MethodRecognizer::kFloat64x2Abs: | 4086 case MethodRecognizer::kFloat64x2Abs: |
| 4087 __ abspd(left); | 4087 __ abspd(left); |
| 4088 break; | 4088 break; |
| 4089 case MethodRecognizer::kFloat64x2Sqrt: | 4089 case MethodRecognizer::kFloat64x2Sqrt: |
| 4090 __ sqrtpd(left); | 4090 __ sqrtpd(left); |
| 4091 break; | 4091 break; |
| 4092 case MethodRecognizer::kFloat64x2GetSignMask: | 4092 case MethodRecognizer::kFloat64x2GetSignMask: |
| 4093 __ movmskpd(locs()->out().reg(), left); | 4093 __ movmskpd(locs()->out(0).reg(), left); |
| 4094 __ SmiTag(locs()->out().reg()); | 4094 __ SmiTag(locs()->out(0).reg()); |
| 4095 break; | 4095 break; |
| 4096 default: UNREACHABLE(); | 4096 default: UNREACHABLE(); |
| 4097 } | 4097 } |
| 4098 } | 4098 } |
| 4099 | 4099 |
| 4100 | 4100 |
| 4101 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(bool opt) const { | 4101 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(bool opt) const { |
| 4102 const intptr_t kNumInputs = 2; | 4102 const intptr_t kNumInputs = 2; |
| 4103 const intptr_t kNumTemps = 0; | 4103 const intptr_t kNumTemps = 0; |
| 4104 LocationSummary* summary = | 4104 LocationSummary* summary = |
| 4105 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4105 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4106 summary->set_in(0, Location::RequiresFpuRegister()); | 4106 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4107 summary->set_in(1, Location::RequiresFpuRegister()); | 4107 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4108 summary->set_out(Location::SameAsFirstInput()); | 4108 summary->set_out(0, Location::SameAsFirstInput()); |
| 4109 return summary; | 4109 return summary; |
| 4110 } | 4110 } |
| 4111 | 4111 |
| 4112 | 4112 |
| 4113 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4113 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4114 XmmRegister left = locs()->in(0).fpu_reg(); | 4114 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4115 XmmRegister right = locs()->in(1).fpu_reg(); | 4115 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4116 ASSERT((locs()->out().fpu_reg() == left)); | 4116 ASSERT((locs()->out(0).fpu_reg() == left)); |
| 4117 | 4117 |
| 4118 switch (op_kind()) { | 4118 switch (op_kind()) { |
| 4119 case MethodRecognizer::kFloat64x2Scale: | 4119 case MethodRecognizer::kFloat64x2Scale: |
| 4120 __ shufpd(right, right, Immediate(0x00)); | 4120 __ shufpd(right, right, Immediate(0x00)); |
| 4121 __ mulpd(left, right); | 4121 __ mulpd(left, right); |
| 4122 break; | 4122 break; |
| 4123 case MethodRecognizer::kFloat64x2WithX: | 4123 case MethodRecognizer::kFloat64x2WithX: |
| 4124 __ subl(ESP, Immediate(16)); | 4124 __ subl(ESP, Immediate(16)); |
| 4125 // Move value to stack. | 4125 // Move value to stack. |
| 4126 __ movups(Address(ESP, 0), left); | 4126 __ movups(Address(ESP, 0), left); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 4154 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4154 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
| 4155 bool opt) const { | 4155 bool opt) const { |
| 4156 const intptr_t kNumInputs = 4; | 4156 const intptr_t kNumInputs = 4; |
| 4157 const intptr_t kNumTemps = 0; | 4157 const intptr_t kNumTemps = 0; |
| 4158 LocationSummary* summary = | 4158 LocationSummary* summary = |
| 4159 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4159 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4160 summary->set_in(0, Location::RequiresRegister()); | 4160 summary->set_in(0, Location::RequiresRegister()); |
| 4161 summary->set_in(1, Location::RequiresRegister()); | 4161 summary->set_in(1, Location::RequiresRegister()); |
| 4162 summary->set_in(2, Location::RequiresRegister()); | 4162 summary->set_in(2, Location::RequiresRegister()); |
| 4163 summary->set_in(3, Location::RequiresRegister()); | 4163 summary->set_in(3, Location::RequiresRegister()); |
| 4164 summary->set_out(Location::RequiresFpuRegister()); | 4164 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4165 return summary; | 4165 return summary; |
| 4166 } | 4166 } |
| 4167 | 4167 |
| 4168 | 4168 |
| 4169 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4169 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4170 Register v0 = locs()->in(0).reg(); | 4170 Register v0 = locs()->in(0).reg(); |
| 4171 Register v1 = locs()->in(1).reg(); | 4171 Register v1 = locs()->in(1).reg(); |
| 4172 Register v2 = locs()->in(2).reg(); | 4172 Register v2 = locs()->in(2).reg(); |
| 4173 Register v3 = locs()->in(3).reg(); | 4173 Register v3 = locs()->in(3).reg(); |
| 4174 XmmRegister result = locs()->out().fpu_reg(); | 4174 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4175 Label x_false, x_done; | 4175 Label x_false, x_done; |
| 4176 Label y_false, y_done; | 4176 Label y_false, y_done; |
| 4177 Label z_false, z_done; | 4177 Label z_false, z_done; |
| 4178 Label w_false, w_done; | 4178 Label w_false, w_done; |
| 4179 __ subl(ESP, Immediate(16)); | 4179 __ subl(ESP, Immediate(16)); |
| 4180 __ CompareObject(v0, Bool::True()); | 4180 __ CompareObject(v0, Bool::True()); |
| 4181 __ j(NOT_EQUAL, &x_false); | 4181 __ j(NOT_EQUAL, &x_false); |
| 4182 __ movl(Address(ESP, 0), Immediate(0xFFFFFFFF)); | 4182 __ movl(Address(ESP, 0), Immediate(0xFFFFFFFF)); |
| 4183 __ jmp(&x_done); | 4183 __ jmp(&x_done); |
| 4184 __ Bind(&x_false); | 4184 __ Bind(&x_false); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 4213 __ addl(ESP, Immediate(16)); | 4213 __ addl(ESP, Immediate(16)); |
| 4214 } | 4214 } |
| 4215 | 4215 |
| 4216 | 4216 |
| 4217 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(bool opt) const { | 4217 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(bool opt) const { |
| 4218 const intptr_t kNumInputs = 1; | 4218 const intptr_t kNumInputs = 1; |
| 4219 const intptr_t kNumTemps = 0; | 4219 const intptr_t kNumTemps = 0; |
| 4220 LocationSummary* summary = | 4220 LocationSummary* summary = |
| 4221 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4221 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4222 summary->set_in(0, Location::RequiresFpuRegister()); | 4222 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4223 summary->set_out(Location::RequiresRegister()); | 4223 summary->set_out(0, Location::RequiresRegister()); |
| 4224 return summary; | 4224 return summary; |
| 4225 } | 4225 } |
| 4226 | 4226 |
| 4227 | 4227 |
| 4228 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4228 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4229 XmmRegister value = locs()->in(0).fpu_reg(); | 4229 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4230 Register result = locs()->out().reg(); | 4230 Register result = locs()->out(0).reg(); |
| 4231 Label done; | 4231 Label done; |
| 4232 Label non_zero; | 4232 Label non_zero; |
| 4233 __ subl(ESP, Immediate(16)); | 4233 __ subl(ESP, Immediate(16)); |
| 4234 // Move value to stack. | 4234 // Move value to stack. |
| 4235 __ movups(Address(ESP, 0), value); | 4235 __ movups(Address(ESP, 0), value); |
| 4236 switch (op_kind()) { | 4236 switch (op_kind()) { |
| 4237 case MethodRecognizer::kInt32x4GetFlagX: | 4237 case MethodRecognizer::kInt32x4GetFlagX: |
| 4238 __ movl(result, Address(ESP, 0)); | 4238 __ movl(result, Address(ESP, 0)); |
| 4239 break; | 4239 break; |
| 4240 case MethodRecognizer::kInt32x4GetFlagY: | 4240 case MethodRecognizer::kInt32x4GetFlagY: |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4261 | 4261 |
| 4262 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(bool opt) const { | 4262 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(bool opt) const { |
| 4263 const intptr_t kNumInputs = 3; | 4263 const intptr_t kNumInputs = 3; |
| 4264 const intptr_t kNumTemps = 1; | 4264 const intptr_t kNumTemps = 1; |
| 4265 LocationSummary* summary = | 4265 LocationSummary* summary = |
| 4266 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4266 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4267 summary->set_in(0, Location::RequiresFpuRegister()); | 4267 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4268 summary->set_in(1, Location::RequiresFpuRegister()); | 4268 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4269 summary->set_in(2, Location::RequiresFpuRegister()); | 4269 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4270 summary->set_temp(0, Location::RequiresFpuRegister()); | 4270 summary->set_temp(0, Location::RequiresFpuRegister()); |
| 4271 summary->set_out(Location::SameAsFirstInput()); | 4271 summary->set_out(0, Location::SameAsFirstInput()); |
| 4272 return summary; | 4272 return summary; |
| 4273 } | 4273 } |
| 4274 | 4274 |
| 4275 | 4275 |
| 4276 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4276 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4277 XmmRegister mask = locs()->in(0).fpu_reg(); | 4277 XmmRegister mask = locs()->in(0).fpu_reg(); |
| 4278 XmmRegister trueValue = locs()->in(1).fpu_reg(); | 4278 XmmRegister trueValue = locs()->in(1).fpu_reg(); |
| 4279 XmmRegister falseValue = locs()->in(2).fpu_reg(); | 4279 XmmRegister falseValue = locs()->in(2).fpu_reg(); |
| 4280 XmmRegister out = locs()->out().fpu_reg(); | 4280 XmmRegister out = locs()->out(0).fpu_reg(); |
| 4281 XmmRegister temp = locs()->temp(0).fpu_reg(); | 4281 XmmRegister temp = locs()->temp(0).fpu_reg(); |
| 4282 ASSERT(out == mask); | 4282 ASSERT(out == mask); |
| 4283 // Copy mask. | 4283 // Copy mask. |
| 4284 __ movaps(temp, mask); | 4284 __ movaps(temp, mask); |
| 4285 // Invert it. | 4285 // Invert it. |
| 4286 __ notps(temp); | 4286 __ notps(temp); |
| 4287 // mask = mask & trueValue. | 4287 // mask = mask & trueValue. |
| 4288 __ andps(mask, trueValue); | 4288 __ andps(mask, trueValue); |
| 4289 // temp = temp & falseValue. | 4289 // temp = temp & falseValue. |
| 4290 __ andps(temp, falseValue); | 4290 __ andps(temp, falseValue); |
| 4291 // out = mask | temp. | 4291 // out = mask | temp. |
| 4292 __ orps(mask, temp); | 4292 __ orps(mask, temp); |
| 4293 } | 4293 } |
| 4294 | 4294 |
| 4295 | 4295 |
| 4296 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const { | 4296 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const { |
| 4297 const intptr_t kNumInputs = 2; | 4297 const intptr_t kNumInputs = 2; |
| 4298 const intptr_t kNumTemps = 0; | 4298 const intptr_t kNumTemps = 0; |
| 4299 LocationSummary* summary = | 4299 LocationSummary* summary = |
| 4300 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4300 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4301 summary->set_in(0, Location::RequiresFpuRegister()); | 4301 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4302 summary->set_in(1, Location::RequiresRegister()); | 4302 summary->set_in(1, Location::RequiresRegister()); |
| 4303 summary->set_out(Location::SameAsFirstInput()); | 4303 summary->set_out(0, Location::SameAsFirstInput()); |
| 4304 return summary; | 4304 return summary; |
| 4305 } | 4305 } |
| 4306 | 4306 |
| 4307 | 4307 |
| 4308 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4308 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4309 XmmRegister mask = locs()->in(0).fpu_reg(); | 4309 XmmRegister mask = locs()->in(0).fpu_reg(); |
| 4310 Register flag = locs()->in(1).reg(); | 4310 Register flag = locs()->in(1).reg(); |
| 4311 ASSERT(mask == locs()->out().fpu_reg()); | 4311 ASSERT(mask == locs()->out(0).fpu_reg()); |
| 4312 __ subl(ESP, Immediate(16)); | 4312 __ subl(ESP, Immediate(16)); |
| 4313 // Copy mask to stack. | 4313 // Copy mask to stack. |
| 4314 __ movups(Address(ESP, 0), mask); | 4314 __ movups(Address(ESP, 0), mask); |
| 4315 Label falsePath, exitPath; | 4315 Label falsePath, exitPath; |
| 4316 __ CompareObject(flag, Bool::True()); | 4316 __ CompareObject(flag, Bool::True()); |
| 4317 __ j(NOT_EQUAL, &falsePath); | 4317 __ j(NOT_EQUAL, &falsePath); |
| 4318 switch (op_kind()) { | 4318 switch (op_kind()) { |
| 4319 case MethodRecognizer::kInt32x4WithFlagX: | 4319 case MethodRecognizer::kInt32x4WithFlagX: |
| 4320 __ movl(Address(ESP, 0), Immediate(0xFFFFFFFF)); | 4320 __ movl(Address(ESP, 0), Immediate(0xFFFFFFFF)); |
| 4321 __ jmp(&exitPath); | 4321 __ jmp(&exitPath); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 4348 __ addl(ESP, Immediate(16)); | 4348 __ addl(ESP, Immediate(16)); |
| 4349 } | 4349 } |
| 4350 | 4350 |
| 4351 | 4351 |
| 4352 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(bool opt) const { | 4352 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(bool opt) const { |
| 4353 const intptr_t kNumInputs = 1; | 4353 const intptr_t kNumInputs = 1; |
| 4354 const intptr_t kNumTemps = 0; | 4354 const intptr_t kNumTemps = 0; |
| 4355 LocationSummary* summary = | 4355 LocationSummary* summary = |
| 4356 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4356 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4357 summary->set_in(0, Location::RequiresFpuRegister()); | 4357 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4358 summary->set_out(Location::SameAsFirstInput()); | 4358 summary->set_out(0, Location::SameAsFirstInput()); |
| 4359 return summary; | 4359 return summary; |
| 4360 } | 4360 } |
| 4361 | 4361 |
| 4362 | 4362 |
| 4363 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4363 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4364 // NOP. | 4364 // NOP. |
| 4365 } | 4365 } |
| 4366 | 4366 |
| 4367 | 4367 |
| 4368 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(bool opt) const { | 4368 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(bool opt) const { |
| 4369 const intptr_t kNumInputs = 2; | 4369 const intptr_t kNumInputs = 2; |
| 4370 const intptr_t kNumTemps = 0; | 4370 const intptr_t kNumTemps = 0; |
| 4371 LocationSummary* summary = | 4371 LocationSummary* summary = |
| 4372 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4372 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4373 summary->set_in(0, Location::RequiresFpuRegister()); | 4373 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4374 summary->set_in(1, Location::RequiresFpuRegister()); | 4374 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4375 summary->set_out(Location::SameAsFirstInput()); | 4375 summary->set_out(0, Location::SameAsFirstInput()); |
| 4376 return summary; | 4376 return summary; |
| 4377 } | 4377 } |
| 4378 | 4378 |
| 4379 | 4379 |
| 4380 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4380 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4381 XmmRegister left = locs()->in(0).fpu_reg(); | 4381 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4382 XmmRegister right = locs()->in(1).fpu_reg(); | 4382 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4383 ASSERT(left == locs()->out().fpu_reg()); | 4383 ASSERT(left == locs()->out(0).fpu_reg()); |
| 4384 switch (op_kind()) { | 4384 switch (op_kind()) { |
| 4385 case Token::kBIT_AND: { | 4385 case Token::kBIT_AND: { |
| 4386 __ andps(left, right); | 4386 __ andps(left, right); |
| 4387 break; | 4387 break; |
| 4388 } | 4388 } |
| 4389 case Token::kBIT_OR: { | 4389 case Token::kBIT_OR: { |
| 4390 __ orps(left, right); | 4390 __ orps(left, right); |
| 4391 break; | 4391 break; |
| 4392 } | 4392 } |
| 4393 case Token::kBIT_XOR: { | 4393 case Token::kBIT_XOR: { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4409 if ((kind() == MethodRecognizer::kMathSin) || | 4409 if ((kind() == MethodRecognizer::kMathSin) || |
| 4410 (kind() == MethodRecognizer::kMathCos)) { | 4410 (kind() == MethodRecognizer::kMathCos)) { |
| 4411 const intptr_t kNumInputs = 1; | 4411 const intptr_t kNumInputs = 1; |
| 4412 const intptr_t kNumTemps = 1; | 4412 const intptr_t kNumTemps = 1; |
| 4413 LocationSummary* summary = | 4413 LocationSummary* summary = |
| 4414 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4414 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4415 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 4415 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); |
| 4416 // EDI is chosen because it is callee saved so we do not need to back it | 4416 // EDI is chosen because it is callee saved so we do not need to back it |
| 4417 // up before calling into the runtime. | 4417 // up before calling into the runtime. |
| 4418 summary->set_temp(0, Location::RegisterLocation(EDI)); | 4418 summary->set_temp(0, Location::RegisterLocation(EDI)); |
| 4419 summary->set_out(Location::FpuRegisterLocation(XMM1)); | 4419 summary->set_out(0, Location::FpuRegisterLocation(XMM1)); |
| 4420 return summary; | 4420 return summary; |
| 4421 } | 4421 } |
| 4422 ASSERT(kind() == MethodRecognizer::kMathSqrt); | 4422 ASSERT(kind() == MethodRecognizer::kMathSqrt); |
| 4423 const intptr_t kNumInputs = 1; | 4423 const intptr_t kNumInputs = 1; |
| 4424 const intptr_t kNumTemps = 0; | 4424 const intptr_t kNumTemps = 0; |
| 4425 LocationSummary* summary = | 4425 LocationSummary* summary = |
| 4426 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4426 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4427 summary->set_in(0, Location::RequiresFpuRegister()); | 4427 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4428 summary->set_out(Location::RequiresFpuRegister()); | 4428 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4429 return summary; | 4429 return summary; |
| 4430 } | 4430 } |
| 4431 | 4431 |
| 4432 | 4432 |
| 4433 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4433 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4434 if (kind() == MethodRecognizer::kMathSqrt) { | 4434 if (kind() == MethodRecognizer::kMathSqrt) { |
| 4435 __ sqrtsd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); | 4435 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 4436 } else { | 4436 } else { |
| 4437 ASSERT((kind() == MethodRecognizer::kMathSin) || | 4437 ASSERT((kind() == MethodRecognizer::kMathSin) || |
| 4438 (kind() == MethodRecognizer::kMathCos)); | 4438 (kind() == MethodRecognizer::kMathCos)); |
| 4439 // Save ESP. | 4439 // Save ESP. |
| 4440 __ movl(locs()->temp(0).reg(), ESP); | 4440 __ movl(locs()->temp(0).reg(), ESP); |
| 4441 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); | 4441 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); |
| 4442 __ movsd(Address(ESP, 0), locs()->in(0).fpu_reg()); | 4442 __ movsd(Address(ESP, 0), locs()->in(0).fpu_reg()); |
| 4443 __ CallRuntime(TargetFunction(), InputCount()); | 4443 __ CallRuntime(TargetFunction(), InputCount()); |
| 4444 __ fstpl(Address(ESP, 0)); | 4444 __ fstpl(Address(ESP, 0)); |
| 4445 __ movsd(locs()->out().fpu_reg(), Address(ESP, 0)); | 4445 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); |
| 4446 // Restore ESP. | 4446 // Restore ESP. |
| 4447 __ movl(ESP, locs()->temp(0).reg()); | 4447 __ movl(ESP, locs()->temp(0).reg()); |
| 4448 } | 4448 } |
| 4449 } | 4449 } |
| 4450 | 4450 |
| 4451 | 4451 |
| 4452 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const { | 4452 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const { |
| 4453 if (result_cid() == kDoubleCid) { | 4453 if (result_cid() == kDoubleCid) { |
| 4454 const intptr_t kNumInputs = 2; | 4454 const intptr_t kNumInputs = 2; |
| 4455 const intptr_t kNumTemps = 1; | 4455 const intptr_t kNumTemps = 1; |
| 4456 LocationSummary* summary = | 4456 LocationSummary* summary = |
| 4457 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4457 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4458 summary->set_in(0, Location::RequiresFpuRegister()); | 4458 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4459 summary->set_in(1, Location::RequiresFpuRegister()); | 4459 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4460 // Reuse the left register so that code can be made shorter. | 4460 // Reuse the left register so that code can be made shorter. |
| 4461 summary->set_out(Location::SameAsFirstInput()); | 4461 summary->set_out(0, Location::SameAsFirstInput()); |
| 4462 summary->set_temp(0, Location::RequiresRegister()); | 4462 summary->set_temp(0, Location::RequiresRegister()); |
| 4463 return summary; | 4463 return summary; |
| 4464 } | 4464 } |
| 4465 | 4465 |
| 4466 ASSERT(result_cid() == kSmiCid); | 4466 ASSERT(result_cid() == kSmiCid); |
| 4467 const intptr_t kNumInputs = 2; | 4467 const intptr_t kNumInputs = 2; |
| 4468 const intptr_t kNumTemps = 0; | 4468 const intptr_t kNumTemps = 0; |
| 4469 LocationSummary* summary = | 4469 LocationSummary* summary = |
| 4470 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4470 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4471 summary->set_in(0, Location::RequiresRegister()); | 4471 summary->set_in(0, Location::RequiresRegister()); |
| 4472 summary->set_in(1, Location::RequiresRegister()); | 4472 summary->set_in(1, Location::RequiresRegister()); |
| 4473 // Reuse the left register so that code can be made shorter. | 4473 // Reuse the left register so that code can be made shorter. |
| 4474 summary->set_out(Location::SameAsFirstInput()); | 4474 summary->set_out(0, Location::SameAsFirstInput()); |
| 4475 return summary; | 4475 return summary; |
| 4476 } | 4476 } |
| 4477 | 4477 |
| 4478 | 4478 |
| 4479 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4479 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4480 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 4480 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
| 4481 (op_kind() == MethodRecognizer::kMathMax)); | 4481 (op_kind() == MethodRecognizer::kMathMax)); |
| 4482 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); | 4482 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); |
| 4483 if (result_cid() == kDoubleCid) { | 4483 if (result_cid() == kDoubleCid) { |
| 4484 Label done, returns_nan, are_equal; | 4484 Label done, returns_nan, are_equal; |
| 4485 XmmRegister left = locs()->in(0).fpu_reg(); | 4485 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4486 XmmRegister right = locs()->in(1).fpu_reg(); | 4486 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4487 XmmRegister result = locs()->out().fpu_reg(); | 4487 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4488 Register temp = locs()->temp(0).reg(); | 4488 Register temp = locs()->temp(0).reg(); |
| 4489 __ comisd(left, right); | 4489 __ comisd(left, right); |
| 4490 __ j(PARITY_EVEN, &returns_nan, Assembler::kNearJump); | 4490 __ j(PARITY_EVEN, &returns_nan, Assembler::kNearJump); |
| 4491 __ j(EQUAL, &are_equal, Assembler::kNearJump); | 4491 __ j(EQUAL, &are_equal, Assembler::kNearJump); |
| 4492 const Condition double_condition = | 4492 const Condition double_condition = |
| 4493 is_min ? TokenKindToDoubleCondition(Token::kLT) | 4493 is_min ? TokenKindToDoubleCondition(Token::kLT) |
| 4494 : TokenKindToDoubleCondition(Token::kGT); | 4494 : TokenKindToDoubleCondition(Token::kGT); |
| 4495 ASSERT(left == result); | 4495 ASSERT(left == result); |
| 4496 __ j(double_condition, &done, Assembler::kNearJump); | 4496 __ j(double_condition, &done, Assembler::kNearJump); |
| 4497 __ movsd(result, right); | 4497 __ movsd(result, right); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4519 __ j(ZERO, &done, Assembler::kNearJump); // Positive -> return left. | 4519 __ j(ZERO, &done, Assembler::kNearJump); // Positive -> return left. |
| 4520 } | 4520 } |
| 4521 __ movsd(result, right); | 4521 __ movsd(result, right); |
| 4522 __ Bind(&done); | 4522 __ Bind(&done); |
| 4523 return; | 4523 return; |
| 4524 } | 4524 } |
| 4525 | 4525 |
| 4526 ASSERT(result_cid() == kSmiCid); | 4526 ASSERT(result_cid() == kSmiCid); |
| 4527 Register left = locs()->in(0).reg(); | 4527 Register left = locs()->in(0).reg(); |
| 4528 Register right = locs()->in(1).reg(); | 4528 Register right = locs()->in(1).reg(); |
| 4529 Register result = locs()->out().reg(); | 4529 Register result = locs()->out(0).reg(); |
| 4530 __ cmpl(left, right); | 4530 __ cmpl(left, right); |
| 4531 ASSERT(result == left); | 4531 ASSERT(result == left); |
| 4532 if (is_min) { | 4532 if (is_min) { |
| 4533 __ cmovgel(result, right); | 4533 __ cmovgel(result, right); |
| 4534 } else { | 4534 } else { |
| 4535 __ cmovlessl(result, right); | 4535 __ cmovlessl(result, right); |
| 4536 } | 4536 } |
| 4537 } | 4537 } |
| 4538 | 4538 |
| 4539 | 4539 |
| 4540 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const { | 4540 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const { |
| 4541 const intptr_t kNumInputs = 1; | 4541 const intptr_t kNumInputs = 1; |
| 4542 return LocationSummary::Make(kNumInputs, | 4542 return LocationSummary::Make(kNumInputs, |
| 4543 Location::SameAsFirstInput(), | 4543 Location::SameAsFirstInput(), |
| 4544 LocationSummary::kNoCall); | 4544 LocationSummary::kNoCall); |
| 4545 } | 4545 } |
| 4546 | 4546 |
| 4547 | 4547 |
| 4548 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4548 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4549 Register value = locs()->in(0).reg(); | 4549 Register value = locs()->in(0).reg(); |
| 4550 ASSERT(value == locs()->out().reg()); | 4550 ASSERT(value == locs()->out(0).reg()); |
| 4551 switch (op_kind()) { | 4551 switch (op_kind()) { |
| 4552 case Token::kNEGATE: { | 4552 case Token::kNEGATE: { |
| 4553 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 4553 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 4554 kDeoptUnaryOp); | 4554 kDeoptUnaryOp); |
| 4555 __ negl(value); | 4555 __ negl(value); |
| 4556 __ j(OVERFLOW, deopt); | 4556 __ j(OVERFLOW, deopt); |
| 4557 break; | 4557 break; |
| 4558 } | 4558 } |
| 4559 case Token::kBIT_NOT: | 4559 case Token::kBIT_NOT: |
| 4560 __ notl(value); | 4560 __ notl(value); |
| 4561 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | 4561 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
| 4562 break; | 4562 break; |
| 4563 default: | 4563 default: |
| 4564 UNREACHABLE(); | 4564 UNREACHABLE(); |
| 4565 } | 4565 } |
| 4566 } | 4566 } |
| 4567 | 4567 |
| 4568 | 4568 |
| 4569 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const { | 4569 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const { |
| 4570 const intptr_t kNumInputs = 1; | 4570 const intptr_t kNumInputs = 1; |
| 4571 const intptr_t kNumTemps = 0; | 4571 const intptr_t kNumTemps = 0; |
| 4572 LocationSummary* summary = | 4572 LocationSummary* summary = |
| 4573 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4573 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4574 summary->set_in(0, Location::RequiresFpuRegister()); | 4574 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4575 summary->set_out(Location::SameAsFirstInput()); | 4575 summary->set_out(0, Location::SameAsFirstInput()); |
| 4576 return summary; | 4576 return summary; |
| 4577 } | 4577 } |
| 4578 | 4578 |
| 4579 | 4579 |
| 4580 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4580 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4581 XmmRegister value = locs()->in(0).fpu_reg(); | 4581 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4582 ASSERT(locs()->out().fpu_reg() == value); | 4582 ASSERT(locs()->out(0).fpu_reg() == value); |
| 4583 __ DoubleNegate(value); | 4583 __ DoubleNegate(value); |
| 4584 } | 4584 } |
| 4585 | 4585 |
| 4586 | 4586 |
| 4587 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const { | 4587 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const { |
| 4588 const intptr_t kNumInputs = 1; | 4588 const intptr_t kNumInputs = 1; |
| 4589 const intptr_t kNumTemps = 0; | 4589 const intptr_t kNumTemps = 0; |
| 4590 LocationSummary* result = | 4590 LocationSummary* result = |
| 4591 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4591 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4592 result->set_in(0, Location::WritableRegister()); | 4592 result->set_in(0, Location::WritableRegister()); |
| 4593 result->set_out(Location::RequiresFpuRegister()); | 4593 result->set_out(0, Location::RequiresFpuRegister()); |
| 4594 return result; | 4594 return result; |
| 4595 } | 4595 } |
| 4596 | 4596 |
| 4597 | 4597 |
| 4598 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4598 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4599 Register value = locs()->in(0).reg(); | 4599 Register value = locs()->in(0).reg(); |
| 4600 FpuRegister result = locs()->out().fpu_reg(); | 4600 FpuRegister result = locs()->out(0).fpu_reg(); |
| 4601 __ SmiUntag(value); | 4601 __ SmiUntag(value); |
| 4602 __ cvtsi2sd(result, value); | 4602 __ cvtsi2sd(result, value); |
| 4603 } | 4603 } |
| 4604 | 4604 |
| 4605 | 4605 |
| 4606 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const { | 4606 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const { |
| 4607 const intptr_t kNumInputs = 1; | 4607 const intptr_t kNumInputs = 1; |
| 4608 const intptr_t kNumTemps = 0; | 4608 const intptr_t kNumTemps = 0; |
| 4609 LocationSummary* result = | 4609 LocationSummary* result = |
| 4610 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4610 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4611 result->set_in(0, Location::RegisterLocation(ECX)); | 4611 result->set_in(0, Location::RegisterLocation(ECX)); |
| 4612 result->set_out(Location::RegisterLocation(EAX)); | 4612 result->set_out(0, Location::RegisterLocation(EAX)); |
| 4613 return result; | 4613 return result; |
| 4614 } | 4614 } |
| 4615 | 4615 |
| 4616 | 4616 |
| 4617 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4617 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4618 Register result = locs()->out().reg(); | 4618 Register result = locs()->out(0).reg(); |
| 4619 Register value_obj = locs()->in(0).reg(); | 4619 Register value_obj = locs()->in(0).reg(); |
| 4620 XmmRegister value_double = XMM0; | 4620 XmmRegister value_double = XMM0; |
| 4621 ASSERT(result == EAX); | 4621 ASSERT(result == EAX); |
| 4622 ASSERT(result != value_obj); | 4622 ASSERT(result != value_obj); |
| 4623 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); | 4623 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); |
| 4624 __ cvttsd2si(result, value_double); | 4624 __ cvttsd2si(result, value_double); |
| 4625 // Overflow is signalled with minint. | 4625 // Overflow is signalled with minint. |
| 4626 Label do_call, done; | 4626 Label do_call, done; |
| 4627 // Check for overflow and that it fits into Smi. | 4627 // Check for overflow and that it fits into Smi. |
| 4628 __ cmpl(result, Immediate(0xC0000000)); | 4628 __ cmpl(result, Immediate(0xC0000000)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4646 __ Bind(&done); | 4646 __ Bind(&done); |
| 4647 } | 4647 } |
| 4648 | 4648 |
| 4649 | 4649 |
| 4650 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const { | 4650 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const { |
| 4651 const intptr_t kNumInputs = 1; | 4651 const intptr_t kNumInputs = 1; |
| 4652 const intptr_t kNumTemps = 0; | 4652 const intptr_t kNumTemps = 0; |
| 4653 LocationSummary* result = new LocationSummary( | 4653 LocationSummary* result = new LocationSummary( |
| 4654 kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4654 kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4655 result->set_in(0, Location::RequiresFpuRegister()); | 4655 result->set_in(0, Location::RequiresFpuRegister()); |
| 4656 result->set_out(Location::RequiresRegister()); | 4656 result->set_out(0, Location::RequiresRegister()); |
| 4657 return result; | 4657 return result; |
| 4658 } | 4658 } |
| 4659 | 4659 |
| 4660 | 4660 |
| 4661 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4661 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4662 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); | 4662 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); |
| 4663 Register result = locs()->out().reg(); | 4663 Register result = locs()->out(0).reg(); |
| 4664 XmmRegister value = locs()->in(0).fpu_reg(); | 4664 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4665 __ cvttsd2si(result, value); | 4665 __ cvttsd2si(result, value); |
| 4666 // Check for overflow and that it fits into Smi. | 4666 // Check for overflow and that it fits into Smi. |
| 4667 __ cmpl(result, Immediate(0xC0000000)); | 4667 __ cmpl(result, Immediate(0xC0000000)); |
| 4668 __ j(NEGATIVE, deopt); | 4668 __ j(NEGATIVE, deopt); |
| 4669 __ SmiTag(result); | 4669 __ SmiTag(result); |
| 4670 } | 4670 } |
| 4671 | 4671 |
| 4672 | 4672 |
| 4673 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const { | 4673 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const { |
| 4674 const intptr_t kNumInputs = 1; | 4674 const intptr_t kNumInputs = 1; |
| 4675 const intptr_t kNumTemps = 0; | 4675 const intptr_t kNumTemps = 0; |
| 4676 LocationSummary* result = | 4676 LocationSummary* result = |
| 4677 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4677 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4678 result->set_in(0, Location::RequiresFpuRegister()); | 4678 result->set_in(0, Location::RequiresFpuRegister()); |
| 4679 result->set_out(Location::RequiresFpuRegister()); | 4679 result->set_out(0, Location::RequiresFpuRegister()); |
| 4680 return result; | 4680 return result; |
| 4681 } | 4681 } |
| 4682 | 4682 |
| 4683 | 4683 |
| 4684 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4684 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4685 XmmRegister value = locs()->in(0).fpu_reg(); | 4685 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4686 XmmRegister result = locs()->out().fpu_reg(); | 4686 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4687 switch (recognized_kind()) { | 4687 switch (recognized_kind()) { |
| 4688 case MethodRecognizer::kDoubleTruncate: | 4688 case MethodRecognizer::kDoubleTruncate: |
| 4689 __ roundsd(result, value, Assembler::kRoundToZero); | 4689 __ roundsd(result, value, Assembler::kRoundToZero); |
| 4690 break; | 4690 break; |
| 4691 case MethodRecognizer::kDoubleFloor: | 4691 case MethodRecognizer::kDoubleFloor: |
| 4692 __ roundsd(result, value, Assembler::kRoundDown); | 4692 __ roundsd(result, value, Assembler::kRoundDown); |
| 4693 break; | 4693 break; |
| 4694 case MethodRecognizer::kDoubleCeil: | 4694 case MethodRecognizer::kDoubleCeil: |
| 4695 __ roundsd(result, value, Assembler::kRoundUp); | 4695 __ roundsd(result, value, Assembler::kRoundUp); |
| 4696 break; | 4696 break; |
| 4697 default: | 4697 default: |
| 4698 UNREACHABLE(); | 4698 UNREACHABLE(); |
| 4699 } | 4699 } |
| 4700 } | 4700 } |
| 4701 | 4701 |
| 4702 | 4702 |
| 4703 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(bool opt) const { | 4703 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(bool opt) const { |
| 4704 const intptr_t kNumInputs = 1; | 4704 const intptr_t kNumInputs = 1; |
| 4705 const intptr_t kNumTemps = 0; | 4705 const intptr_t kNumTemps = 0; |
| 4706 LocationSummary* result = | 4706 LocationSummary* result = |
| 4707 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4707 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4708 result->set_in(0, Location::RequiresFpuRegister()); | 4708 result->set_in(0, Location::RequiresFpuRegister()); |
| 4709 result->set_out(Location::SameAsFirstInput()); | 4709 result->set_out(0, Location::SameAsFirstInput()); |
| 4710 return result; | 4710 return result; |
| 4711 } | 4711 } |
| 4712 | 4712 |
| 4713 | 4713 |
| 4714 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4714 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4715 __ cvtsd2ss(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); | 4715 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 4716 } | 4716 } |
| 4717 | 4717 |
| 4718 | 4718 |
| 4719 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(bool opt) const { | 4719 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(bool opt) const { |
| 4720 const intptr_t kNumInputs = 1; | 4720 const intptr_t kNumInputs = 1; |
| 4721 const intptr_t kNumTemps = 0; | 4721 const intptr_t kNumTemps = 0; |
| 4722 LocationSummary* result = | 4722 LocationSummary* result = |
| 4723 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4723 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4724 result->set_in(0, Location::RequiresFpuRegister()); | 4724 result->set_in(0, Location::RequiresFpuRegister()); |
| 4725 result->set_out(Location::SameAsFirstInput()); | 4725 result->set_out(0, Location::SameAsFirstInput()); |
| 4726 return result; | 4726 return result; |
| 4727 } | 4727 } |
| 4728 | 4728 |
| 4729 | 4729 |
| 4730 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4730 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4731 __ cvtss2sd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); | 4731 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 4732 } | 4732 } |
| 4733 | 4733 |
| 4734 | 4734 |
| 4735 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { | 4735 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { |
| 4736 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 4736 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 4737 const intptr_t kNumTemps = 1; | 4737 const intptr_t kNumTemps = 1; |
| 4738 LocationSummary* result = | 4738 LocationSummary* result = |
| 4739 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); | 4739 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); |
| 4740 // EDI is chosen because it is callee saved so we do not need to back it | 4740 // EDI is chosen because it is callee saved so we do not need to back it |
| 4741 // up before calling into the runtime. | 4741 // up before calling into the runtime. |
| 4742 result->set_temp(0, Location::RegisterLocation(EDI)); | 4742 result->set_temp(0, Location::RegisterLocation(EDI)); |
| 4743 result->set_in(0, Location::FpuRegisterLocation(XMM1)); | 4743 result->set_in(0, Location::FpuRegisterLocation(XMM1)); |
| 4744 if (InputCount() == 2) { | 4744 if (InputCount() == 2) { |
| 4745 result->set_in(1, Location::FpuRegisterLocation(XMM2)); | 4745 result->set_in(1, Location::FpuRegisterLocation(XMM2)); |
| 4746 } | 4746 } |
| 4747 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 4747 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 4748 // Temp index 1. | 4748 // Temp index 1. |
| 4749 result->AddTemp(Location::RegisterLocation(EAX)); | 4749 result->AddTemp(Location::RegisterLocation(EAX)); |
| 4750 // Temp index 2. | 4750 // Temp index 2. |
| 4751 result->AddTemp(Location::FpuRegisterLocation(XMM4)); | 4751 result->AddTemp(Location::FpuRegisterLocation(XMM4)); |
| 4752 } | 4752 } |
| 4753 result->set_out(Location::FpuRegisterLocation(XMM3)); | 4753 result->set_out(0, Location::FpuRegisterLocation(XMM3)); |
| 4754 return result; | 4754 return result; |
| 4755 } | 4755 } |
| 4756 | 4756 |
| 4757 | 4757 |
| 4758 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4758 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4759 // Save ESP. | 4759 // Save ESP. |
| 4760 __ movl(locs()->temp(kSavedSpTempIndex).reg(), ESP); | 4760 __ movl(locs()->temp(kSavedSpTempIndex).reg(), ESP); |
| 4761 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); | 4761 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); |
| 4762 for (intptr_t i = 0; i < InputCount(); i++) { | 4762 for (intptr_t i = 0; i < InputCount(); i++) { |
| 4763 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); | 4763 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); |
| 4764 } | 4764 } |
| 4765 Label do_call, skip_call; | 4765 Label do_call, skip_call; |
| 4766 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 4766 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 4767 // Pseudo code: | 4767 // Pseudo code: |
| 4768 // if (exponent == 0.0) return 1.0; | 4768 // if (exponent == 0.0) return 1.0; |
| 4769 // if (base == 1.0) return 1.0; | 4769 // if (base == 1.0) return 1.0; |
| 4770 // if (base.isNaN || exponent.isNaN) { | 4770 // if (base.isNaN || exponent.isNaN) { |
| 4771 // return double.NAN; | 4771 // return double.NAN; |
| 4772 // } | 4772 // } |
| 4773 XmmRegister base = locs()->in(0).fpu_reg(); | 4773 XmmRegister base = locs()->in(0).fpu_reg(); |
| 4774 XmmRegister exp = locs()->in(1).fpu_reg(); | 4774 XmmRegister exp = locs()->in(1).fpu_reg(); |
| 4775 XmmRegister result = locs()->out().fpu_reg(); | 4775 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4776 Register temp = locs()->temp(kObjectTempIndex).reg(); | 4776 Register temp = locs()->temp(kObjectTempIndex).reg(); |
| 4777 XmmRegister zero_temp = locs()->temp(kDoubleTempIndex).fpu_reg(); | 4777 XmmRegister zero_temp = locs()->temp(kDoubleTempIndex).fpu_reg(); |
| 4778 | 4778 |
| 4779 Label check_base_is_one; | 4779 Label check_base_is_one; |
| 4780 // Check if exponent is 0.0 -> return 1.0; | 4780 // Check if exponent is 0.0 -> return 1.0; |
| 4781 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0))); | 4781 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0))); |
| 4782 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); | 4782 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); |
| 4783 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); | 4783 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); |
| 4784 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 4784 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 4785 // 'result' contains 1.0. | 4785 // 'result' contains 1.0. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4796 | 4796 |
| 4797 __ Bind(&base_is_nan); | 4797 __ Bind(&base_is_nan); |
| 4798 // Returns NaN. | 4798 // Returns NaN. |
| 4799 __ movsd(result, base); | 4799 __ movsd(result, base); |
| 4800 __ jmp(&skip_call, Assembler::kNearJump); | 4800 __ jmp(&skip_call, Assembler::kNearJump); |
| 4801 // exp is Nan case is handled correctly in the C-library. | 4801 // exp is Nan case is handled correctly in the C-library. |
| 4802 } | 4802 } |
| 4803 __ Bind(&do_call); | 4803 __ Bind(&do_call); |
| 4804 __ CallRuntime(TargetFunction(), InputCount()); | 4804 __ CallRuntime(TargetFunction(), InputCount()); |
| 4805 __ fstpl(Address(ESP, 0)); | 4805 __ fstpl(Address(ESP, 0)); |
| 4806 __ movsd(locs()->out().fpu_reg(), Address(ESP, 0)); | 4806 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); |
| 4807 __ Bind(&skip_call); | 4807 __ Bind(&skip_call); |
| 4808 // Restore ESP. | 4808 // Restore ESP. |
| 4809 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); | 4809 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); |
| 4810 } | 4810 } |
| 4811 | 4811 |
| 4812 | 4812 |
| 4813 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { | 4813 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { |
| 4814 if (kind() == MergedMathInstr::kTruncDivMod) { | 4814 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 4815 const intptr_t kNumInputs = 2; | 4815 const intptr_t kNumInputs = 2; |
| 4816 const intptr_t kNumTemps = 1; | 4816 const intptr_t kNumTemps = 1; |
| 4817 LocationSummary* summary = | 4817 LocationSummary* summary = |
| 4818 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4818 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4819 // Both inputs must be writable because they will be untagged. | 4819 // Both inputs must be writable because they will be untagged. |
| 4820 summary->set_in(0, Location::RegisterLocation(EAX)); | 4820 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 4821 summary->set_in(1, Location::WritableRegister()); | 4821 summary->set_in(1, Location::WritableRegister()); |
| 4822 summary->set_out(Location::RequiresRegister()); | 4822 summary->set_out(0, Location::RequiresRegister()); |
| 4823 // Will be used for sign extension and division. | 4823 // Will be used for sign extension and division. |
| 4824 summary->set_temp(0, Location::RegisterLocation(EDX)); | 4824 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 4825 return summary; | 4825 return summary; |
| 4826 } | 4826 } |
| 4827 if (kind() == MergedMathInstr::kSinCos) { | 4827 if (kind() == MergedMathInstr::kSinCos) { |
| 4828 const intptr_t kNumInputs = 1; | 4828 const intptr_t kNumInputs = 1; |
| 4829 const intptr_t kNumTemps = 0; | 4829 const intptr_t kNumTemps = 0; |
| 4830 LocationSummary* summary = | 4830 LocationSummary* summary = |
| 4831 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4831 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4832 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 4832 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); |
| 4833 summary->set_out(Location::RegisterLocation(EAX)); | 4833 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 4834 return summary; | 4834 return summary; |
| 4835 } | 4835 } |
| 4836 UNIMPLEMENTED(); | 4836 UNIMPLEMENTED(); |
| 4837 return NULL; | 4837 return NULL; |
| 4838 } | 4838 } |
| 4839 | 4839 |
| 4840 | 4840 |
| 4841 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); | 4841 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); |
| 4842 | 4842 |
| 4843 extern const RuntimeEntry kSinCosRuntimeEntry( | 4843 extern const RuntimeEntry kSinCosRuntimeEntry( |
| 4844 "libc_sincos", reinterpret_cast<RuntimeFunction>( | 4844 "libc_sincos", reinterpret_cast<RuntimeFunction>( |
| 4845 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); | 4845 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); |
| 4846 | 4846 |
| 4847 | 4847 |
| 4848 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4848 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4849 Label* deopt = NULL; | 4849 Label* deopt = NULL; |
| 4850 if (CanDeoptimize()) { | 4850 if (CanDeoptimize()) { |
| 4851 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 4851 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| 4852 } | 4852 } |
| 4853 | 4853 |
| 4854 if (kind() == MergedMathInstr::kTruncDivMod) { | 4854 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 4855 Register left = locs()->in(0).reg(); | 4855 Register left = locs()->in(0).reg(); |
| 4856 Register right = locs()->in(1).reg(); | 4856 Register right = locs()->in(1).reg(); |
| 4857 Register result = locs()->out().reg(); | 4857 Register result = locs()->out(0).reg(); |
| 4858 Range* right_range = InputAt(1)->definition()->range(); | 4858 Range* right_range = InputAt(1)->definition()->range(); |
| 4859 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 4859 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 4860 // Handle divide by zero in runtime. | 4860 // Handle divide by zero in runtime. |
| 4861 __ testl(right, right); | 4861 __ testl(right, right); |
| 4862 __ j(ZERO, deopt); | 4862 __ j(ZERO, deopt); |
| 4863 } | 4863 } |
| 4864 ASSERT(left == EAX); | 4864 ASSERT(left == EAX); |
| 4865 ASSERT((right != EDX) && (right != EAX)); | 4865 ASSERT((right != EDX) && (right != EAX)); |
| 4866 ASSERT(locs()->temp(0).reg() == EDX); | 4866 ASSERT(locs()->temp(0).reg() == EDX); |
| 4867 ASSERT((result != EDX) && (result != EAX)); | 4867 ASSERT((result != EDX) && (result != EAX)); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4930 __ pushl(EAX); | 4930 __ pushl(EAX); |
| 4931 __ movsd(Address(ESP, 0), locs()->in(0).fpu_reg()); | 4931 __ movsd(Address(ESP, 0), locs()->in(0).fpu_reg()); |
| 4932 __ fldl(Address(ESP, 0)); | 4932 __ fldl(Address(ESP, 0)); |
| 4933 __ fsincos(); | 4933 __ fsincos(); |
| 4934 __ fstpl(Address(ESP, 0)); | 4934 __ fstpl(Address(ESP, 0)); |
| 4935 __ movsd(XMM1, Address(ESP, 0)); | 4935 __ movsd(XMM1, Address(ESP, 0)); |
| 4936 __ fstpl(Address(ESP, 0)); | 4936 __ fstpl(Address(ESP, 0)); |
| 4937 __ movsd(XMM0, Address(ESP, 0)); | 4937 __ movsd(XMM0, Address(ESP, 0)); |
| 4938 __ addl(ESP, Immediate(2 * kWordSize)); | 4938 __ addl(ESP, Immediate(2 * kWordSize)); |
| 4939 | 4939 |
| 4940 Register result = locs()->out().reg(); | 4940 Register result = locs()->out(0).reg(); |
| 4941 const TypedData& res_array = TypedData::ZoneHandle( | 4941 const TypedData& res_array = TypedData::ZoneHandle( |
| 4942 TypedData::New(kTypedDataFloat64ArrayCid, 2, Heap::kOld)); | 4942 TypedData::New(kTypedDataFloat64ArrayCid, 2, Heap::kOld)); |
| 4943 __ LoadObject(result, res_array); | 4943 __ LoadObject(result, res_array); |
| 4944 const intptr_t index_scale = | 4944 const intptr_t index_scale = |
| 4945 FlowGraphCompiler::ElementSizeFor(kTypedDataFloat64ArrayCid); | 4945 FlowGraphCompiler::ElementSizeFor(kTypedDataFloat64ArrayCid); |
| 4946 Address sin_address( | 4946 Address sin_address( |
| 4947 FlowGraphCompiler::ElementAddressForIntIndex( | 4947 FlowGraphCompiler::ElementAddressForIntIndex( |
| 4948 kTypedDataFloat64ArrayCid, index_scale, result, | 4948 kTypedDataFloat64ArrayCid, index_scale, result, |
| 4949 MergedMathInstr::ResultIndexOf(MethodRecognizer::kMathSin))); | 4949 MergedMathInstr::ResultIndexOf(MethodRecognizer::kMathSin))); |
| 4950 Address cos_address( | 4950 Address cos_address( |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5000 deopt, | 5000 deopt, |
| 5001 deopt_id(), | 5001 deopt_id(), |
| 5002 instance_call()->token_pos(), | 5002 instance_call()->token_pos(), |
| 5003 locs()); | 5003 locs()); |
| 5004 } | 5004 } |
| 5005 | 5005 |
| 5006 | 5006 |
| 5007 LocationSummary* BranchInstr::MakeLocationSummary(bool opt) const { | 5007 LocationSummary* BranchInstr::MakeLocationSummary(bool opt) const { |
| 5008 comparison()->InitializeLocationSummary(opt); | 5008 comparison()->InitializeLocationSummary(opt); |
| 5009 // Branches don't produce a result. | 5009 // Branches don't produce a result. |
| 5010 comparison()->locs()->set_out(Location::NoLocation()); | 5010 comparison()->locs()->set_out(0, Location::NoLocation()); |
| 5011 return comparison()->locs(); | 5011 return comparison()->locs(); |
| 5012 } | 5012 } |
| 5013 | 5013 |
| 5014 | 5014 |
| 5015 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5015 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5016 comparison()->EmitBranchCode(compiler, this); | 5016 comparison()->EmitBranchCode(compiler, this); |
| 5017 } | 5017 } |
| 5018 | 5018 |
| 5019 | 5019 |
| 5020 LocationSummary* CheckClassInstr::MakeLocationSummary(bool opt) const { | 5020 LocationSummary* CheckClassInstr::MakeLocationSummary(bool opt) const { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5171 const intptr_t value_cid = value()->Type()->ToCid(); | 5171 const intptr_t value_cid = value()->Type()->ToCid(); |
| 5172 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kMintCid)); | 5172 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kMintCid)); |
| 5173 const bool needs_writable_input = (value_cid == kSmiCid); | 5173 const bool needs_writable_input = (value_cid == kSmiCid); |
| 5174 const intptr_t kNumTemps = needs_temp ? 1 : 0; | 5174 const intptr_t kNumTemps = needs_temp ? 1 : 0; |
| 5175 LocationSummary* summary = | 5175 LocationSummary* summary = |
| 5176 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5176 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5177 summary->set_in(0, needs_writable_input | 5177 summary->set_in(0, needs_writable_input |
| 5178 ? Location::WritableRegister() | 5178 ? Location::WritableRegister() |
| 5179 : Location::RequiresRegister()); | 5179 : Location::RequiresRegister()); |
| 5180 if (needs_temp) summary->set_temp(0, Location::RequiresRegister()); | 5180 if (needs_temp) summary->set_temp(0, Location::RequiresRegister()); |
| 5181 summary->set_out(Location::RequiresFpuRegister()); | 5181 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5182 return summary; | 5182 return summary; |
| 5183 } | 5183 } |
| 5184 | 5184 |
| 5185 | 5185 |
| 5186 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5186 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5187 const intptr_t value_cid = value()->Type()->ToCid(); | 5187 const intptr_t value_cid = value()->Type()->ToCid(); |
| 5188 const Register value = locs()->in(0).reg(); | 5188 const Register value = locs()->in(0).reg(); |
| 5189 const XmmRegister result = locs()->out().fpu_reg(); | 5189 const XmmRegister result = locs()->out(0).fpu_reg(); |
| 5190 | 5190 |
| 5191 if (value_cid == kMintCid) { | 5191 if (value_cid == kMintCid) { |
| 5192 __ movsd(result, FieldAddress(value, Mint::value_offset())); | 5192 __ movsd(result, FieldAddress(value, Mint::value_offset())); |
| 5193 } else if (value_cid == kSmiCid) { | 5193 } else if (value_cid == kSmiCid) { |
| 5194 __ SmiUntag(value); // Untag input before conversion. | 5194 __ SmiUntag(value); // Untag input before conversion. |
| 5195 __ movd(result, value); | 5195 __ movd(result, value); |
| 5196 __ pmovsxdq(result, result); | 5196 __ pmovsxdq(result, result); |
| 5197 } else { | 5197 } else { |
| 5198 Register temp = locs()->temp(0).reg(); | 5198 Register temp = locs()->temp(0).reg(); |
| 5199 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptUnboxInteger); | 5199 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptUnboxInteger); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5218 const intptr_t kNumInputs = 1; | 5218 const intptr_t kNumInputs = 1; |
| 5219 const intptr_t kNumTemps = 2; | 5219 const intptr_t kNumTemps = 2; |
| 5220 LocationSummary* summary = | 5220 LocationSummary* summary = |
| 5221 new LocationSummary(kNumInputs, | 5221 new LocationSummary(kNumInputs, |
| 5222 kNumTemps, | 5222 kNumTemps, |
| 5223 LocationSummary::kCallOnSlowPath); | 5223 LocationSummary::kCallOnSlowPath); |
| 5224 summary->set_in(0, Location::RequiresFpuRegister()); | 5224 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5225 summary->set_temp(0, Location::RegisterLocation(EAX)); | 5225 summary->set_temp(0, Location::RegisterLocation(EAX)); |
| 5226 summary->set_temp(1, Location::RegisterLocation(EDX)); | 5226 summary->set_temp(1, Location::RegisterLocation(EDX)); |
| 5227 // TODO(fschneider): Save one temp by using result register as a temp. | 5227 // TODO(fschneider): Save one temp by using result register as a temp. |
| 5228 summary->set_out(Location::RequiresRegister()); | 5228 summary->set_out(0, Location::RequiresRegister()); |
| 5229 return summary; | 5229 return summary; |
| 5230 } | 5230 } |
| 5231 | 5231 |
| 5232 | 5232 |
| 5233 class BoxIntegerSlowPath : public SlowPathCode { | 5233 class BoxIntegerSlowPath : public SlowPathCode { |
| 5234 public: | 5234 public: |
| 5235 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) | 5235 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) |
| 5236 : instruction_(instruction) { } | 5236 : instruction_(instruction) { } |
| 5237 | 5237 |
| 5238 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5238 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5239 __ Comment("BoxIntegerSlowPath"); | 5239 __ Comment("BoxIntegerSlowPath"); |
| 5240 __ Bind(entry_label()); | 5240 __ Bind(entry_label()); |
| 5241 const Class& mint_class = | 5241 const Class& mint_class = |
| 5242 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()); | 5242 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()); |
| 5243 const Code& stub = | 5243 const Code& stub = |
| 5244 Code::Handle(StubCode::GetAllocationStubForClass(mint_class)); | 5244 Code::Handle(StubCode::GetAllocationStubForClass(mint_class)); |
| 5245 const ExternalLabel label(mint_class.ToCString(), stub.EntryPoint()); | 5245 const ExternalLabel label(mint_class.ToCString(), stub.EntryPoint()); |
| 5246 | 5246 |
| 5247 LocationSummary* locs = instruction_->locs(); | 5247 LocationSummary* locs = instruction_->locs(); |
| 5248 locs->live_registers()->Remove(locs->out()); | 5248 locs->live_registers()->Remove(locs->out(0)); |
| 5249 | 5249 |
| 5250 compiler->SaveLiveRegisters(locs); | 5250 compiler->SaveLiveRegisters(locs); |
| 5251 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 5251 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 5252 &label, | 5252 &label, |
| 5253 PcDescriptors::kOther, | 5253 PcDescriptors::kOther, |
| 5254 locs); | 5254 locs); |
| 5255 __ MoveRegister(locs->out().reg(), EAX); | 5255 __ MoveRegister(locs->out(0).reg(), EAX); |
| 5256 compiler->RestoreLiveRegisters(locs); | 5256 compiler->RestoreLiveRegisters(locs); |
| 5257 | 5257 |
| 5258 __ jmp(exit_label()); | 5258 __ jmp(exit_label()); |
| 5259 } | 5259 } |
| 5260 | 5260 |
| 5261 private: | 5261 private: |
| 5262 BoxIntegerInstr* instruction_; | 5262 BoxIntegerInstr* instruction_; |
| 5263 }; | 5263 }; |
| 5264 | 5264 |
| 5265 | 5265 |
| 5266 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5266 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5267 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | 5267 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
| 5268 compiler->AddSlowPathCode(slow_path); | 5268 compiler->AddSlowPathCode(slow_path); |
| 5269 | 5269 |
| 5270 Register out_reg = locs()->out().reg(); | 5270 Register out_reg = locs()->out(0).reg(); |
| 5271 XmmRegister value = locs()->in(0).fpu_reg(); | 5271 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5272 | 5272 |
| 5273 // Unboxed operations produce smis or mint-sized values. | 5273 // Unboxed operations produce smis or mint-sized values. |
| 5274 // Check if value fits into a smi. | 5274 // Check if value fits into a smi. |
| 5275 Label not_smi, done; | 5275 Label not_smi, done; |
| 5276 __ pextrd(EDX, value, Immediate(1)); // Upper half. | 5276 __ pextrd(EDX, value, Immediate(1)); // Upper half. |
| 5277 __ pextrd(EAX, value, Immediate(0)); // Lower half. | 5277 __ pextrd(EAX, value, Immediate(0)); // Lower half. |
| 5278 // 1. Compute (x + -kMinSmi) which has to be in the range | 5278 // 1. Compute (x + -kMinSmi) which has to be in the range |
| 5279 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. | 5279 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. |
| 5280 __ addl(EAX, Immediate(0x40000000)); | 5280 __ addl(EAX, Immediate(0x40000000)); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 5311 case Token::kBIT_XOR: { | 5311 case Token::kBIT_XOR: { |
| 5312 const intptr_t kNumTemps = | 5312 const intptr_t kNumTemps = |
| 5313 FLAG_throw_on_javascript_int_overflow ? 1 : 0; | 5313 FLAG_throw_on_javascript_int_overflow ? 1 : 0; |
| 5314 LocationSummary* summary = | 5314 LocationSummary* summary = |
| 5315 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5315 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5316 summary->set_in(0, Location::RequiresFpuRegister()); | 5316 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5317 summary->set_in(1, Location::RequiresFpuRegister()); | 5317 summary->set_in(1, Location::RequiresFpuRegister()); |
| 5318 if (FLAG_throw_on_javascript_int_overflow) { | 5318 if (FLAG_throw_on_javascript_int_overflow) { |
| 5319 summary->set_temp(0, Location::RequiresRegister()); | 5319 summary->set_temp(0, Location::RequiresRegister()); |
| 5320 } | 5320 } |
| 5321 summary->set_out(Location::SameAsFirstInput()); | 5321 summary->set_out(0, Location::SameAsFirstInput()); |
| 5322 return summary; | 5322 return summary; |
| 5323 } | 5323 } |
| 5324 case Token::kADD: | 5324 case Token::kADD: |
| 5325 case Token::kSUB: { | 5325 case Token::kSUB: { |
| 5326 const intptr_t kNumTemps = 2; | 5326 const intptr_t kNumTemps = 2; |
| 5327 LocationSummary* summary = | 5327 LocationSummary* summary = |
| 5328 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5328 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5329 summary->set_in(0, Location::RequiresFpuRegister()); | 5329 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5330 summary->set_in(1, Location::RequiresFpuRegister()); | 5330 summary->set_in(1, Location::RequiresFpuRegister()); |
| 5331 summary->set_temp(0, Location::RequiresRegister()); | 5331 summary->set_temp(0, Location::RequiresRegister()); |
| 5332 summary->set_temp(1, Location::RequiresRegister()); | 5332 summary->set_temp(1, Location::RequiresRegister()); |
| 5333 summary->set_out(Location::SameAsFirstInput()); | 5333 summary->set_out(0, Location::SameAsFirstInput()); |
| 5334 return summary; | 5334 return summary; |
| 5335 } | 5335 } |
| 5336 default: | 5336 default: |
| 5337 UNREACHABLE(); | 5337 UNREACHABLE(); |
| 5338 return NULL; | 5338 return NULL; |
| 5339 } | 5339 } |
| 5340 } | 5340 } |
| 5341 | 5341 |
| 5342 | 5342 |
| 5343 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5343 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5344 XmmRegister left = locs()->in(0).fpu_reg(); | 5344 XmmRegister left = locs()->in(0).fpu_reg(); |
| 5345 XmmRegister right = locs()->in(1).fpu_reg(); | 5345 XmmRegister right = locs()->in(1).fpu_reg(); |
| 5346 | 5346 |
| 5347 ASSERT(locs()->out().fpu_reg() == left); | 5347 ASSERT(locs()->out(0).fpu_reg() == left); |
| 5348 | 5348 |
| 5349 Label* deopt = NULL; | 5349 Label* deopt = NULL; |
| 5350 if (FLAG_throw_on_javascript_int_overflow) { | 5350 if (FLAG_throw_on_javascript_int_overflow) { |
| 5351 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp); | 5351 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp); |
| 5352 } | 5352 } |
| 5353 switch (op_kind()) { | 5353 switch (op_kind()) { |
| 5354 case Token::kBIT_AND: __ andpd(left, right); break; | 5354 case Token::kBIT_AND: __ andpd(left, right); break; |
| 5355 case Token::kBIT_OR: __ orpd(left, right); break; | 5355 case Token::kBIT_OR: __ orpd(left, right); break; |
| 5356 case Token::kBIT_XOR: __ xorpd(left, right); break; | 5356 case Token::kBIT_XOR: __ xorpd(left, right); break; |
| 5357 case Token::kADD: | 5357 case Token::kADD: |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5397 const intptr_t kNumInputs = 2; | 5397 const intptr_t kNumInputs = 2; |
| 5398 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; | 5398 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; |
| 5399 LocationSummary* summary = | 5399 LocationSummary* summary = |
| 5400 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5400 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5401 summary->set_in(0, Location::RequiresFpuRegister()); | 5401 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5402 summary->set_in(1, Location::RegisterLocation(ECX)); | 5402 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 5403 summary->set_temp(0, Location::RequiresRegister()); | 5403 summary->set_temp(0, Location::RequiresRegister()); |
| 5404 if (op_kind() == Token::kSHL) { | 5404 if (op_kind() == Token::kSHL) { |
| 5405 summary->set_temp(1, Location::RequiresRegister()); | 5405 summary->set_temp(1, Location::RequiresRegister()); |
| 5406 } | 5406 } |
| 5407 summary->set_out(Location::SameAsFirstInput()); | 5407 summary->set_out(0, Location::SameAsFirstInput()); |
| 5408 return summary; | 5408 return summary; |
| 5409 } | 5409 } |
| 5410 | 5410 |
| 5411 | 5411 |
| 5412 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5412 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5413 XmmRegister left = locs()->in(0).fpu_reg(); | 5413 XmmRegister left = locs()->in(0).fpu_reg(); |
| 5414 ASSERT(locs()->in(1).reg() == ECX); | 5414 ASSERT(locs()->in(1).reg() == ECX); |
| 5415 ASSERT(locs()->out().fpu_reg() == left); | 5415 ASSERT(locs()->out(0).fpu_reg() == left); |
| 5416 | 5416 |
| 5417 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5417 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 5418 kDeoptShiftMintOp); | 5418 kDeoptShiftMintOp); |
| 5419 Label done; | 5419 Label done; |
| 5420 __ testl(ECX, ECX); | 5420 __ testl(ECX, ECX); |
| 5421 __ j(ZERO, &done); // Shift by 0 is a nop. | 5421 __ j(ZERO, &done); // Shift by 0 is a nop. |
| 5422 __ subl(ESP, Immediate(2 * kWordSize)); | 5422 __ subl(ESP, Immediate(2 * kWordSize)); |
| 5423 __ movq(Address(ESP, 0), left); | 5423 __ movq(Address(ESP, 0), left); |
| 5424 // Deoptimize if shift count is > 31. | 5424 // Deoptimize if shift count is > 31. |
| 5425 // sarl operation masks the count to 5 bits and | 5425 // sarl operation masks the count to 5 bits and |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5467 } | 5467 } |
| 5468 | 5468 |
| 5469 | 5469 |
| 5470 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { | 5470 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { |
| 5471 const intptr_t kNumInputs = 1; | 5471 const intptr_t kNumInputs = 1; |
| 5472 const intptr_t kNumTemps = | 5472 const intptr_t kNumTemps = |
| 5473 FLAG_throw_on_javascript_int_overflow ? 1 : 0; | 5473 FLAG_throw_on_javascript_int_overflow ? 1 : 0; |
| 5474 LocationSummary* summary = | 5474 LocationSummary* summary = |
| 5475 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5475 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5476 summary->set_in(0, Location::RequiresFpuRegister()); | 5476 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5477 summary->set_out(Location::SameAsFirstInput()); | 5477 summary->set_out(0, Location::SameAsFirstInput()); |
| 5478 if (FLAG_throw_on_javascript_int_overflow) { | 5478 if (FLAG_throw_on_javascript_int_overflow) { |
| 5479 summary->set_temp(0, Location::RequiresRegister()); | 5479 summary->set_temp(0, Location::RequiresRegister()); |
| 5480 } | 5480 } |
| 5481 return summary; | 5481 return summary; |
| 5482 } | 5482 } |
| 5483 | 5483 |
| 5484 | 5484 |
| 5485 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5485 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5486 ASSERT(op_kind() == Token::kBIT_NOT); | 5486 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5487 XmmRegister value = locs()->in(0).fpu_reg(); | 5487 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5488 ASSERT(value == locs()->out().fpu_reg()); | 5488 ASSERT(value == locs()->out(0).fpu_reg()); |
| 5489 Label* deopt = NULL; | 5489 Label* deopt = NULL; |
| 5490 if (FLAG_throw_on_javascript_int_overflow) { | 5490 if (FLAG_throw_on_javascript_int_overflow) { |
| 5491 deopt = compiler->AddDeoptStub(deopt_id(), | 5491 deopt = compiler->AddDeoptStub(deopt_id(), |
| 5492 kDeoptUnaryMintOp); | 5492 kDeoptUnaryMintOp); |
| 5493 } | 5493 } |
| 5494 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 5494 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. |
| 5495 __ pxor(value, XMM0); | 5495 __ pxor(value, XMM0); |
| 5496 if (FLAG_throw_on_javascript_int_overflow) { | 5496 if (FLAG_throw_on_javascript_int_overflow) { |
| 5497 Register tmp = locs()->temp(0).reg(); | 5497 Register tmp = locs()->temp(0).reg(); |
| 5498 EmitJavascriptIntOverflowCheck(compiler, deopt, value, tmp); | 5498 EmitJavascriptIntOverflowCheck(compiler, deopt, value, tmp); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5586 | 5586 |
| 5587 | 5587 |
| 5588 LocationSummary* CurrentContextInstr::MakeLocationSummary(bool opt) const { | 5588 LocationSummary* CurrentContextInstr::MakeLocationSummary(bool opt) const { |
| 5589 return LocationSummary::Make(0, | 5589 return LocationSummary::Make(0, |
| 5590 Location::RequiresRegister(), | 5590 Location::RequiresRegister(), |
| 5591 LocationSummary::kNoCall); | 5591 LocationSummary::kNoCall); |
| 5592 } | 5592 } |
| 5593 | 5593 |
| 5594 | 5594 |
| 5595 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5595 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5596 __ MoveRegister(locs()->out().reg(), CTX); | 5596 __ MoveRegister(locs()->out(0).reg(), CTX); |
| 5597 } | 5597 } |
| 5598 | 5598 |
| 5599 | 5599 |
| 5600 LocationSummary* StrictCompareInstr::MakeLocationSummary(bool opt) const { | 5600 LocationSummary* StrictCompareInstr::MakeLocationSummary(bool opt) const { |
| 5601 const intptr_t kNumInputs = 2; | 5601 const intptr_t kNumInputs = 2; |
| 5602 const intptr_t kNumTemps = 0; | 5602 const intptr_t kNumTemps = 0; |
| 5603 if (needs_number_check()) { | 5603 if (needs_number_check()) { |
| 5604 LocationSummary* locs = | 5604 LocationSummary* locs = |
| 5605 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 5605 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5606 locs->set_in(0, Location::RegisterLocation(EAX)); | 5606 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 5607 locs->set_in(1, Location::RegisterLocation(ECX)); | 5607 locs->set_in(1, Location::RegisterLocation(ECX)); |
| 5608 locs->set_out(Location::RegisterLocation(EAX)); | 5608 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 5609 return locs; | 5609 return locs; |
| 5610 } | 5610 } |
| 5611 LocationSummary* locs = | 5611 LocationSummary* locs = |
| 5612 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5612 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5613 locs->set_in(0, Location::RegisterOrConstant(left())); | 5613 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 5614 // Only one of the inputs can be a constant. Choose register if the first one | 5614 // Only one of the inputs can be a constant. Choose register if the first one |
| 5615 // is a constant. | 5615 // is a constant. |
| 5616 locs->set_in(1, locs->in(0).IsConstant() | 5616 locs->set_in(1, locs->in(0).IsConstant() |
| 5617 ? Location::RequiresRegister() | 5617 ? Location::RequiresRegister() |
| 5618 : Location::RegisterOrConstant(right())); | 5618 : Location::RegisterOrConstant(right())); |
| 5619 locs->set_out(Location::RequiresRegister()); | 5619 locs->set_out(0, Location::RequiresRegister()); |
| 5620 return locs; | 5620 return locs; |
| 5621 } | 5621 } |
| 5622 | 5622 |
| 5623 | 5623 |
| 5624 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 5624 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 5625 BranchLabels labels) { | 5625 BranchLabels labels) { |
| 5626 Location left = locs()->in(0); | 5626 Location left = locs()->in(0); |
| 5627 Location right = locs()->in(1); | 5627 Location right = locs()->in(1); |
| 5628 ASSERT(!left.IsConstant() || !right.IsConstant()); | 5628 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 5629 if (left.IsConstant()) { | 5629 if (left.IsConstant()) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5648 | 5648 |
| 5649 | 5649 |
| 5650 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5650 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5651 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 5651 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 5652 | 5652 |
| 5653 Label is_true, is_false; | 5653 Label is_true, is_false; |
| 5654 BranchLabels labels = { &is_true, &is_false, &is_false }; | 5654 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 5655 Condition true_condition = EmitComparisonCode(compiler, labels); | 5655 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 5656 EmitBranchOnCondition(compiler, true_condition, labels); | 5656 EmitBranchOnCondition(compiler, true_condition, labels); |
| 5657 | 5657 |
| 5658 Register result = locs()->out().reg(); | 5658 Register result = locs()->out(0).reg(); |
| 5659 Label done; | 5659 Label done; |
| 5660 __ Bind(&is_false); | 5660 __ Bind(&is_false); |
| 5661 __ LoadObject(result, Bool::False()); | 5661 __ LoadObject(result, Bool::False()); |
| 5662 __ jmp(&done, Assembler::kNearJump); | 5662 __ jmp(&done, Assembler::kNearJump); |
| 5663 __ Bind(&is_true); | 5663 __ Bind(&is_true); |
| 5664 __ LoadObject(result, Bool::True()); | 5664 __ LoadObject(result, Bool::True()); |
| 5665 __ Bind(&done); | 5665 __ Bind(&done); |
| 5666 } | 5666 } |
| 5667 | 5667 |
| 5668 | 5668 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5679 // Detect pattern when one value is zero and another is a power of 2. | 5679 // Detect pattern when one value is zero and another is a power of 2. |
| 5680 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 5680 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 5681 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 5681 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 5682 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 5682 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 5683 } | 5683 } |
| 5684 | 5684 |
| 5685 | 5685 |
| 5686 LocationSummary* IfThenElseInstr::MakeLocationSummary(bool opt) const { | 5686 LocationSummary* IfThenElseInstr::MakeLocationSummary(bool opt) const { |
| 5687 comparison()->InitializeLocationSummary(opt); | 5687 comparison()->InitializeLocationSummary(opt); |
| 5688 // TODO(vegorov): support byte register constraints in the register allocator. | 5688 // TODO(vegorov): support byte register constraints in the register allocator. |
| 5689 comparison()->locs()->set_out(Location::RegisterLocation(EDX)); | 5689 comparison()->locs()->set_out(0, Location::RegisterLocation(EDX)); |
| 5690 return comparison()->locs(); | 5690 return comparison()->locs(); |
| 5691 } | 5691 } |
| 5692 | 5692 |
| 5693 | 5693 |
| 5694 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5694 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5695 ASSERT(locs()->out().reg() == EDX); | 5695 ASSERT(locs()->out(0).reg() == EDX); |
| 5696 | 5696 |
| 5697 // Clear upper part of the out register. We are going to use setcc on it | 5697 // Clear upper part of the out register. We are going to use setcc on it |
| 5698 // which is a byte move. | 5698 // which is a byte move. |
| 5699 __ xorl(EDX, EDX); | 5699 __ xorl(EDX, EDX); |
| 5700 | 5700 |
| 5701 // Emit comparison code. This must not overwrite the result register. | 5701 // Emit comparison code. This must not overwrite the result register. |
| 5702 BranchLabels labels = { NULL, NULL, NULL }; | 5702 BranchLabels labels = { NULL, NULL, NULL }; |
| 5703 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 5703 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 5704 | 5704 |
| 5705 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 5705 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5738 } | 5738 } |
| 5739 } | 5739 } |
| 5740 } | 5740 } |
| 5741 | 5741 |
| 5742 | 5742 |
| 5743 LocationSummary* ClosureCallInstr::MakeLocationSummary(bool opt) const { | 5743 LocationSummary* ClosureCallInstr::MakeLocationSummary(bool opt) const { |
| 5744 const intptr_t kNumInputs = 0; | 5744 const intptr_t kNumInputs = 0; |
| 5745 const intptr_t kNumTemps = 1; | 5745 const intptr_t kNumTemps = 1; |
| 5746 LocationSummary* result = | 5746 LocationSummary* result = |
| 5747 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 5747 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5748 result->set_out(Location::RegisterLocation(EAX)); | 5748 result->set_out(0, Location::RegisterLocation(EAX)); |
| 5749 result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor. | 5749 result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor. |
| 5750 return result; | 5750 return result; |
| 5751 } | 5751 } |
| 5752 | 5752 |
| 5753 | 5753 |
| 5754 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5754 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5755 // The arguments to the stub include the closure, as does the arguments | 5755 // The arguments to the stub include the closure, as does the arguments |
| 5756 // descriptor. | 5756 // descriptor. |
| 5757 Register temp_reg = locs()->temp(0).reg(); | 5757 Register temp_reg = locs()->temp(0).reg(); |
| 5758 int argument_count = ArgumentCount(); | 5758 int argument_count = ArgumentCount(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5772 | 5772 |
| 5773 LocationSummary* BooleanNegateInstr::MakeLocationSummary(bool opt) const { | 5773 LocationSummary* BooleanNegateInstr::MakeLocationSummary(bool opt) const { |
| 5774 return LocationSummary::Make(1, | 5774 return LocationSummary::Make(1, |
| 5775 Location::RequiresRegister(), | 5775 Location::RequiresRegister(), |
| 5776 LocationSummary::kNoCall); | 5776 LocationSummary::kNoCall); |
| 5777 } | 5777 } |
| 5778 | 5778 |
| 5779 | 5779 |
| 5780 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5780 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5781 Register value = locs()->in(0).reg(); | 5781 Register value = locs()->in(0).reg(); |
| 5782 Register result = locs()->out().reg(); | 5782 Register result = locs()->out(0).reg(); |
| 5783 | 5783 |
| 5784 Label done; | 5784 Label done; |
| 5785 __ LoadObject(result, Bool::True()); | 5785 __ LoadObject(result, Bool::True()); |
| 5786 __ CompareRegisters(result, value); | 5786 __ CompareRegisters(result, value); |
| 5787 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 5787 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 5788 __ LoadObject(result, Bool::False()); | 5788 __ LoadObject(result, Bool::False()); |
| 5789 __ Bind(&done); | 5789 __ Bind(&done); |
| 5790 } | 5790 } |
| 5791 | 5791 |
| 5792 | 5792 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5803 PcDescriptors::kOther, | 5803 PcDescriptors::kOther, |
| 5804 locs()); | 5804 locs()); |
| 5805 __ Drop(ArgumentCount()); // Discard arguments. | 5805 __ Drop(ArgumentCount()); // Discard arguments. |
| 5806 } | 5806 } |
| 5807 | 5807 |
| 5808 } // namespace dart | 5808 } // namespace dart |
| 5809 | 5809 |
| 5810 #undef __ | 5810 #undef __ |
| 5811 | 5811 |
| 5812 #endif // defined TARGET_ARCH_IA32 | 5812 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |