| 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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 11 matching lines...) Expand all Loading... |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DECLARE_FLAG(int, optimization_counter_threshold); | 24 DECLARE_FLAG(int, optimization_counter_threshold); |
| 25 DECLARE_FLAG(bool, propagate_ic_data); | 25 DECLARE_FLAG(bool, propagate_ic_data); |
| 26 DECLARE_FLAG(bool, use_osr); | 26 DECLARE_FLAG(bool, use_osr); |
| 27 | 27 |
| 28 // Generic summary for call instructions that have all arguments pushed | 28 // Generic summary for call instructions that have all arguments pushed |
| 29 // on the stack and return the result in a fixed register V0. | 29 // on the stack and return the result in a fixed register V0. |
| 30 LocationSummary* Instruction::MakeCallSummary() { | 30 LocationSummary* Instruction::MakeCallSummary() { |
| 31 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); | 31 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); |
| 32 result->set_out(Location::RegisterLocation(V0)); | 32 result->set_out(0, Location::RegisterLocation(V0)); |
| 33 return result; | 33 return result; |
| 34 } | 34 } |
| 35 | 35 |
| 36 | 36 |
| 37 LocationSummary* PushArgumentInstr::MakeLocationSummary(bool opt) const { | 37 LocationSummary* PushArgumentInstr::MakeLocationSummary(bool opt) const { |
| 38 const intptr_t kNumInputs = 1; | 38 const intptr_t kNumInputs = 1; |
| 39 const intptr_t kNumTemps= 0; | 39 const intptr_t kNumTemps= 0; |
| 40 LocationSummary* locs = | 40 LocationSummary* locs = |
| 41 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 41 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 42 locs->set_in(0, Location::AnyOrConstant(value())); | 42 locs->set_in(0, Location::AnyOrConstant(value())); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 } | 122 } |
| 123 | 123 |
| 124 | 124 |
| 125 LocationSummary* IfThenElseInstr::MakeLocationSummary(bool opt) const { | 125 LocationSummary* IfThenElseInstr::MakeLocationSummary(bool opt) const { |
| 126 comparison()->InitializeLocationSummary(opt); | 126 comparison()->InitializeLocationSummary(opt); |
| 127 return comparison()->locs(); | 127 return comparison()->locs(); |
| 128 } | 128 } |
| 129 | 129 |
| 130 | 130 |
| 131 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 131 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 132 const Register result = locs()->out().reg(); | 132 const Register result = locs()->out(0).reg(); |
| 133 | 133 |
| 134 Location left = locs()->in(0); | 134 Location left = locs()->in(0); |
| 135 Location right = locs()->in(1); | 135 Location right = locs()->in(1); |
| 136 ASSERT(!left.IsConstant() || !right.IsConstant()); | 136 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 137 | 137 |
| 138 // Clear out register. | 138 // Clear out register. |
| 139 __ mov(result, ZR); | 139 __ mov(result, ZR); |
| 140 | 140 |
| 141 // Emit comparison code. This must not overwrite the result register. | 141 // Emit comparison code. This must not overwrite the result register. |
| 142 BranchLabels labels = { NULL, NULL, NULL }; | 142 BranchLabels labels = { NULL, NULL, NULL }; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 } | 202 } |
| 203 } | 203 } |
| 204 } | 204 } |
| 205 | 205 |
| 206 | 206 |
| 207 LocationSummary* ClosureCallInstr::MakeLocationSummary(bool opt) const { | 207 LocationSummary* ClosureCallInstr::MakeLocationSummary(bool opt) const { |
| 208 const intptr_t kNumInputs = 0; | 208 const intptr_t kNumInputs = 0; |
| 209 const intptr_t kNumTemps = 1; | 209 const intptr_t kNumTemps = 1; |
| 210 LocationSummary* result = | 210 LocationSummary* result = |
| 211 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 211 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 212 result->set_out(Location::RegisterLocation(V0)); | 212 result->set_out(0, Location::RegisterLocation(V0)); |
| 213 result->set_temp(0, Location::RegisterLocation(S4)); // Arg. descriptor. | 213 result->set_temp(0, Location::RegisterLocation(S4)); // Arg. descriptor. |
| 214 return result; | 214 return result; |
| 215 } | 215 } |
| 216 | 216 |
| 217 | 217 |
| 218 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 218 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 219 // The arguments to the stub include the closure, as does the arguments | 219 // The arguments to the stub include the closure, as does the arguments |
| 220 // descriptor. | 220 // descriptor. |
| 221 Register temp_reg = locs()->temp(0).reg(); | 221 Register temp_reg = locs()->temp(0).reg(); |
| 222 int argument_count = ArgumentCount(); | 222 int argument_count = ArgumentCount(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 236 | 236 |
| 237 LocationSummary* LoadLocalInstr::MakeLocationSummary(bool opt) const { | 237 LocationSummary* LoadLocalInstr::MakeLocationSummary(bool opt) const { |
| 238 return LocationSummary::Make(0, | 238 return LocationSummary::Make(0, |
| 239 Location::RequiresRegister(), | 239 Location::RequiresRegister(), |
| 240 LocationSummary::kNoCall); | 240 LocationSummary::kNoCall); |
| 241 } | 241 } |
| 242 | 242 |
| 243 | 243 |
| 244 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 244 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 245 __ TraceSimMsg("LoadLocalInstr"); | 245 __ TraceSimMsg("LoadLocalInstr"); |
| 246 Register result = locs()->out().reg(); | 246 Register result = locs()->out(0).reg(); |
| 247 __ lw(result, Address(FP, local().index() * kWordSize)); | 247 __ lw(result, Address(FP, local().index() * kWordSize)); |
| 248 } | 248 } |
| 249 | 249 |
| 250 | 250 |
| 251 LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const { | 251 LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const { |
| 252 return LocationSummary::Make(1, | 252 return LocationSummary::Make(1, |
| 253 Location::SameAsFirstInput(), | 253 Location::SameAsFirstInput(), |
| 254 LocationSummary::kNoCall); | 254 LocationSummary::kNoCall); |
| 255 } | 255 } |
| 256 | 256 |
| 257 | 257 |
| 258 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 258 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 259 __ TraceSimMsg("StoreLocalInstr"); | 259 __ TraceSimMsg("StoreLocalInstr"); |
| 260 Register value = locs()->in(0).reg(); | 260 Register value = locs()->in(0).reg(); |
| 261 Register result = locs()->out().reg(); | 261 Register result = locs()->out(0).reg(); |
| 262 ASSERT(result == value); // Assert that register assignment is correct. | 262 ASSERT(result == value); // Assert that register assignment is correct. |
| 263 __ sw(value, Address(FP, local().index() * kWordSize)); | 263 __ sw(value, Address(FP, local().index() * kWordSize)); |
| 264 } | 264 } |
| 265 | 265 |
| 266 | 266 |
| 267 LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const { | 267 LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const { |
| 268 return LocationSummary::Make(0, | 268 return LocationSummary::Make(0, |
| 269 Location::RequiresRegister(), | 269 Location::RequiresRegister(), |
| 270 LocationSummary::kNoCall); | 270 LocationSummary::kNoCall); |
| 271 } | 271 } |
| 272 | 272 |
| 273 | 273 |
| 274 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 274 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 275 // The register allocator drops constant definitions that have no uses. | 275 // The register allocator drops constant definitions that have no uses. |
| 276 if (!locs()->out().IsInvalid()) { | 276 if (!locs()->out(0).IsInvalid()) { |
| 277 __ TraceSimMsg("ConstantInstr"); | 277 __ TraceSimMsg("ConstantInstr"); |
| 278 Register result = locs()->out().reg(); | 278 Register result = locs()->out(0).reg(); |
| 279 __ LoadObject(result, value()); | 279 __ LoadObject(result, value()); |
| 280 } | 280 } |
| 281 } | 281 } |
| 282 | 282 |
| 283 | 283 |
| 284 LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const { | 284 LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const { |
| 285 const intptr_t kNumInputs = 3; | 285 const intptr_t kNumInputs = 3; |
| 286 const intptr_t kNumTemps = 0; | 286 const intptr_t kNumTemps = 0; |
| 287 LocationSummary* summary = | 287 LocationSummary* summary = |
| 288 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 288 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 289 summary->set_in(0, Location::RegisterLocation(A0)); // Value. | 289 summary->set_in(0, Location::RegisterLocation(A0)); // Value. |
| 290 summary->set_in(1, Location::RegisterLocation(A2)); // Instantiator. | 290 summary->set_in(1, Location::RegisterLocation(A2)); // Instantiator. |
| 291 summary->set_in(2, Location::RegisterLocation(A1)); // Type arguments. | 291 summary->set_in(2, Location::RegisterLocation(A1)); // Type arguments. |
| 292 summary->set_out(Location::RegisterLocation(A0)); | 292 summary->set_out(0, Location::RegisterLocation(A0)); |
| 293 return summary; | 293 return summary; |
| 294 } | 294 } |
| 295 | 295 |
| 296 | 296 |
| 297 LocationSummary* AssertBooleanInstr::MakeLocationSummary(bool opt) const { | 297 LocationSummary* AssertBooleanInstr::MakeLocationSummary(bool opt) const { |
| 298 const intptr_t kNumInputs = 1; | 298 const intptr_t kNumInputs = 1; |
| 299 const intptr_t kNumTemps = 0; | 299 const intptr_t kNumTemps = 0; |
| 300 LocationSummary* locs = | 300 LocationSummary* locs = |
| 301 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 301 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 302 locs->set_in(0, Location::RegisterLocation(A0)); | 302 locs->set_in(0, Location::RegisterLocation(A0)); |
| 303 locs->set_out(Location::RegisterLocation(A0)); | 303 locs->set_out(0, Location::RegisterLocation(A0)); |
| 304 return locs; | 304 return locs; |
| 305 } | 305 } |
| 306 | 306 |
| 307 | 307 |
| 308 static void EmitAssertBoolean(Register reg, | 308 static void EmitAssertBoolean(Register reg, |
| 309 intptr_t token_pos, | 309 intptr_t token_pos, |
| 310 intptr_t deopt_id, | 310 intptr_t deopt_id, |
| 311 LocationSummary* locs, | 311 LocationSummary* locs, |
| 312 FlowGraphCompiler* compiler) { | 312 FlowGraphCompiler* compiler) { |
| 313 // Check that the type of the value is allowed in conditional context. | 313 // Check that the type of the value is allowed in conditional context. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 324 1, | 324 1, |
| 325 locs); | 325 locs); |
| 326 // We should never return here. | 326 // We should never return here. |
| 327 __ break_(0); | 327 __ break_(0); |
| 328 __ Bind(&done); | 328 __ Bind(&done); |
| 329 } | 329 } |
| 330 | 330 |
| 331 | 331 |
| 332 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 332 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 333 Register obj = locs()->in(0).reg(); | 333 Register obj = locs()->in(0).reg(); |
| 334 Register result = locs()->out().reg(); | 334 Register result = locs()->out(0).reg(); |
| 335 | 335 |
| 336 __ TraceSimMsg("AssertBooleanInstr"); | 336 __ TraceSimMsg("AssertBooleanInstr"); |
| 337 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 337 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 338 ASSERT(obj == result); | 338 ASSERT(obj == result); |
| 339 } | 339 } |
| 340 | 340 |
| 341 | 341 |
| 342 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { | 342 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { |
| 343 const intptr_t kNumInputs = 2; | 343 const intptr_t kNumInputs = 2; |
| 344 if (operation_cid() == kMintCid) { | 344 if (operation_cid() == kMintCid) { |
| 345 const intptr_t kNumTemps = 1; | 345 const intptr_t kNumTemps = 1; |
| 346 LocationSummary* locs = | 346 LocationSummary* locs = |
| 347 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 347 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 348 locs->set_in(0, Location::RequiresFpuRegister()); | 348 locs->set_in(0, Location::RequiresFpuRegister()); |
| 349 locs->set_in(1, Location::RequiresFpuRegister()); | 349 locs->set_in(1, Location::RequiresFpuRegister()); |
| 350 locs->set_temp(0, Location::RequiresRegister()); | 350 locs->set_temp(0, Location::RequiresRegister()); |
| 351 locs->set_out(Location::RequiresRegister()); | 351 locs->set_out(0, Location::RequiresRegister()); |
| 352 return locs; | 352 return locs; |
| 353 } | 353 } |
| 354 if (operation_cid() == kDoubleCid) { | 354 if (operation_cid() == kDoubleCid) { |
| 355 const intptr_t kNumTemps = 0; | 355 const intptr_t kNumTemps = 0; |
| 356 LocationSummary* locs = | 356 LocationSummary* locs = |
| 357 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 357 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 358 locs->set_in(0, Location::RequiresFpuRegister()); | 358 locs->set_in(0, Location::RequiresFpuRegister()); |
| 359 locs->set_in(1, Location::RequiresFpuRegister()); | 359 locs->set_in(1, Location::RequiresFpuRegister()); |
| 360 locs->set_out(Location::RequiresRegister()); | 360 locs->set_out(0, Location::RequiresRegister()); |
| 361 return locs; | 361 return locs; |
| 362 } | 362 } |
| 363 if (operation_cid() == kSmiCid) { | 363 if (operation_cid() == kSmiCid) { |
| 364 const intptr_t kNumTemps = 0; | 364 const intptr_t kNumTemps = 0; |
| 365 LocationSummary* locs = | 365 LocationSummary* locs = |
| 366 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 366 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 367 locs->set_in(0, Location::RegisterOrConstant(left())); | 367 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 368 // Only one input can be a constant operand. The case of two constant | 368 // Only one input can be a constant operand. The case of two constant |
| 369 // operands should be handled by constant propagation. | 369 // operands should be handled by constant propagation. |
| 370 locs->set_in(1, locs->in(0).IsConstant() | 370 locs->set_in(1, locs->in(0).IsConstant() |
| 371 ? Location::RequiresRegister() | 371 ? Location::RequiresRegister() |
| 372 : Location::RegisterOrConstant(right())); | 372 : Location::RegisterOrConstant(right())); |
| 373 locs->set_out(Location::RequiresRegister()); | 373 locs->set_out(0, Location::RequiresRegister()); |
| 374 return locs; | 374 return locs; |
| 375 } | 375 } |
| 376 UNREACHABLE(); | 376 UNREACHABLE(); |
| 377 return NULL; | 377 return NULL; |
| 378 } | 378 } |
| 379 | 379 |
| 380 | 380 |
| 381 static void LoadValueCid(FlowGraphCompiler* compiler, | 381 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 382 Register value_cid_reg, | 382 Register value_cid_reg, |
| 383 Register value_reg, | 383 Register value_reg, |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 | 561 |
| 562 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 562 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 563 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 563 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 564 __ Comment("EqualityCompareInstr"); | 564 __ Comment("EqualityCompareInstr"); |
| 565 | 565 |
| 566 Label is_true, is_false; | 566 Label is_true, is_false; |
| 567 BranchLabels labels = { &is_true, &is_false, &is_false }; | 567 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 568 Condition true_condition = EmitComparisonCode(compiler, labels); | 568 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 569 EmitBranchOnCondition(compiler, true_condition, labels); | 569 EmitBranchOnCondition(compiler, true_condition, labels); |
| 570 | 570 |
| 571 Register result = locs()->out().reg(); | 571 Register result = locs()->out(0).reg(); |
| 572 Label done; | 572 Label done; |
| 573 __ Bind(&is_false); | 573 __ Bind(&is_false); |
| 574 __ LoadObject(result, Bool::False()); | 574 __ LoadObject(result, Bool::False()); |
| 575 __ b(&done); | 575 __ b(&done); |
| 576 __ Bind(&is_true); | 576 __ Bind(&is_true); |
| 577 __ LoadObject(result, Bool::True()); | 577 __ LoadObject(result, Bool::True()); |
| 578 __ Bind(&done); | 578 __ Bind(&done); |
| 579 } | 579 } |
| 580 | 580 |
| 581 | 581 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 const intptr_t kNumInputs = 2; | 640 const intptr_t kNumInputs = 2; |
| 641 const intptr_t kNumTemps = 0; | 641 const intptr_t kNumTemps = 0; |
| 642 if (operation_cid() == kMintCid) { | 642 if (operation_cid() == kMintCid) { |
| 643 const intptr_t kNumTemps = 2; | 643 const intptr_t kNumTemps = 2; |
| 644 LocationSummary* locs = | 644 LocationSummary* locs = |
| 645 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 645 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 646 locs->set_in(0, Location::RequiresFpuRegister()); | 646 locs->set_in(0, Location::RequiresFpuRegister()); |
| 647 locs->set_in(1, Location::RequiresFpuRegister()); | 647 locs->set_in(1, Location::RequiresFpuRegister()); |
| 648 locs->set_temp(0, Location::RequiresRegister()); | 648 locs->set_temp(0, Location::RequiresRegister()); |
| 649 locs->set_temp(1, Location::RequiresRegister()); | 649 locs->set_temp(1, Location::RequiresRegister()); |
| 650 locs->set_out(Location::RequiresRegister()); | 650 locs->set_out(0, Location::RequiresRegister()); |
| 651 return locs; | 651 return locs; |
| 652 } | 652 } |
| 653 if (operation_cid() == kDoubleCid) { | 653 if (operation_cid() == kDoubleCid) { |
| 654 LocationSummary* summary = | 654 LocationSummary* summary = |
| 655 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 655 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 656 summary->set_in(0, Location::RequiresFpuRegister()); | 656 summary->set_in(0, Location::RequiresFpuRegister()); |
| 657 summary->set_in(1, Location::RequiresFpuRegister()); | 657 summary->set_in(1, Location::RequiresFpuRegister()); |
| 658 summary->set_out(Location::RequiresRegister()); | 658 summary->set_out(0, Location::RequiresRegister()); |
| 659 return summary; | 659 return summary; |
| 660 } | 660 } |
| 661 ASSERT(operation_cid() == kSmiCid); | 661 ASSERT(operation_cid() == kSmiCid); |
| 662 LocationSummary* summary = | 662 LocationSummary* summary = |
| 663 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 663 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 664 summary->set_in(0, Location::RegisterOrConstant(left())); | 664 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 665 // Only one input can be a constant operand. The case of two constant | 665 // Only one input can be a constant operand. The case of two constant |
| 666 // operands should be handled by constant propagation. | 666 // operands should be handled by constant propagation. |
| 667 summary->set_in(1, summary->in(0).IsConstant() | 667 summary->set_in(1, summary->in(0).IsConstant() |
| 668 ? Location::RequiresRegister() | 668 ? Location::RequiresRegister() |
| 669 : Location::RegisterOrConstant(right())); | 669 : Location::RegisterOrConstant(right())); |
| 670 summary->set_out(Location::RequiresRegister()); | 670 summary->set_out(0, Location::RequiresRegister()); |
| 671 return summary; | 671 return summary; |
| 672 } | 672 } |
| 673 | 673 |
| 674 | 674 |
| 675 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 675 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 676 BranchLabels labels) { | 676 BranchLabels labels) { |
| 677 if (operation_cid() == kSmiCid) { | 677 if (operation_cid() == kSmiCid) { |
| 678 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 678 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 679 } else { | 679 } else { |
| 680 ASSERT(operation_cid() == kDoubleCid); | 680 ASSERT(operation_cid() == kDoubleCid); |
| 681 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 681 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 682 } | 682 } |
| 683 } | 683 } |
| 684 | 684 |
| 685 | 685 |
| 686 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 686 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 687 __ TraceSimMsg("RelationalOpInstr"); | 687 __ TraceSimMsg("RelationalOpInstr"); |
| 688 | 688 |
| 689 Label is_true, is_false; | 689 Label is_true, is_false; |
| 690 BranchLabels labels = { &is_true, &is_false, &is_false }; | 690 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 691 Condition true_condition = EmitComparisonCode(compiler, labels); | 691 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 692 EmitBranchOnCondition(compiler, true_condition, labels); | 692 EmitBranchOnCondition(compiler, true_condition, labels); |
| 693 | 693 |
| 694 Register result = locs()->out().reg(); | 694 Register result = locs()->out(0).reg(); |
| 695 Label done; | 695 Label done; |
| 696 __ Bind(&is_false); | 696 __ Bind(&is_false); |
| 697 __ LoadObject(result, Bool::False()); | 697 __ LoadObject(result, Bool::False()); |
| 698 __ b(&done); | 698 __ b(&done); |
| 699 __ Bind(&is_true); | 699 __ Bind(&is_true); |
| 700 __ LoadObject(result, Bool::True()); | 700 __ LoadObject(result, Bool::True()); |
| 701 __ Bind(&done); | 701 __ Bind(&done); |
| 702 } | 702 } |
| 703 | 703 |
| 704 | 704 |
| 705 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 705 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 706 BranchInstr* branch) { | 706 BranchInstr* branch) { |
| 707 __ TraceSimMsg("RelationalOpInstr"); | 707 __ TraceSimMsg("RelationalOpInstr"); |
| 708 | 708 |
| 709 BranchLabels labels = compiler->CreateBranchLabels(branch); | 709 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 710 Condition true_condition = EmitComparisonCode(compiler, labels); | 710 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 711 EmitBranchOnCondition(compiler, true_condition, labels); | 711 EmitBranchOnCondition(compiler, true_condition, labels); |
| 712 } | 712 } |
| 713 | 713 |
| 714 | 714 |
| 715 LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const { | 715 LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const { |
| 716 const intptr_t kNumInputs = 0; | 716 const intptr_t kNumInputs = 0; |
| 717 const intptr_t kNumTemps = 3; | 717 const intptr_t kNumTemps = 3; |
| 718 LocationSummary* locs = | 718 LocationSummary* locs = |
| 719 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 719 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 720 locs->set_temp(0, Location::RegisterLocation(A1)); | 720 locs->set_temp(0, Location::RegisterLocation(A1)); |
| 721 locs->set_temp(1, Location::RegisterLocation(A2)); | 721 locs->set_temp(1, Location::RegisterLocation(A2)); |
| 722 locs->set_temp(2, Location::RegisterLocation(T5)); | 722 locs->set_temp(2, Location::RegisterLocation(T5)); |
| 723 locs->set_out(Location::RegisterLocation(V0)); | 723 locs->set_out(0, Location::RegisterLocation(V0)); |
| 724 return locs; | 724 return locs; |
| 725 } | 725 } |
| 726 | 726 |
| 727 | 727 |
| 728 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 728 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 729 __ TraceSimMsg("NativeCallInstr"); | 729 __ TraceSimMsg("NativeCallInstr"); |
| 730 ASSERT(locs()->temp(0).reg() == A1); | 730 ASSERT(locs()->temp(0).reg() == A1); |
| 731 ASSERT(locs()->temp(1).reg() == A2); | 731 ASSERT(locs()->temp(1).reg() == A2); |
| 732 ASSERT(locs()->temp(2).reg() == T5); | 732 ASSERT(locs()->temp(2).reg() == T5); |
| 733 Register result = locs()->out().reg(); | 733 Register result = locs()->out(0).reg(); |
| 734 | 734 |
| 735 // Push the result place holder initialized to NULL. | 735 // Push the result place holder initialized to NULL. |
| 736 __ PushObject(Object::ZoneHandle()); | 736 __ PushObject(Object::ZoneHandle()); |
| 737 // Pass a pointer to the first argument in A2. | 737 // Pass a pointer to the first argument in A2. |
| 738 if (!function().HasOptionalParameters()) { | 738 if (!function().HasOptionalParameters()) { |
| 739 __ AddImmediate(A2, FP, (kParamEndSlotFromFp + | 739 __ AddImmediate(A2, FP, (kParamEndSlotFromFp + |
| 740 function().NumParameters()) * kWordSize); | 740 function().NumParameters()) * kWordSize); |
| 741 } else { | 741 } else { |
| 742 __ AddImmediate(A2, FP, kFirstLocalSlotFromFp * kWordSize); | 742 __ AddImmediate(A2, FP, kFirstLocalSlotFromFp * kWordSize); |
| 743 } | 743 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 const intptr_t kNumInputs = 1; | 778 const intptr_t kNumInputs = 1; |
| 779 // TODO(fschneider): Allow immediate operands for the char code. | 779 // TODO(fschneider): Allow immediate operands for the char code. |
| 780 return LocationSummary::Make(kNumInputs, | 780 return LocationSummary::Make(kNumInputs, |
| 781 Location::RequiresRegister(), | 781 Location::RequiresRegister(), |
| 782 LocationSummary::kNoCall); | 782 LocationSummary::kNoCall); |
| 783 } | 783 } |
| 784 | 784 |
| 785 | 785 |
| 786 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 786 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 787 Register char_code = locs()->in(0).reg(); | 787 Register char_code = locs()->in(0).reg(); |
| 788 Register result = locs()->out().reg(); | 788 Register result = locs()->out(0).reg(); |
| 789 | 789 |
| 790 __ TraceSimMsg("StringFromCharCodeInstr"); | 790 __ TraceSimMsg("StringFromCharCodeInstr"); |
| 791 | 791 |
| 792 __ LoadImmediate(result, | 792 __ LoadImmediate(result, |
| 793 reinterpret_cast<uword>(Symbols::PredefinedAddress())); | 793 reinterpret_cast<uword>(Symbols::PredefinedAddress())); |
| 794 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 794 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
| 795 __ sll(TMP, char_code, 1); // Char code is a smi. | 795 __ sll(TMP, char_code, 1); // Char code is a smi. |
| 796 __ addu(TMP, TMP, result); | 796 __ addu(TMP, TMP, result); |
| 797 __ lw(result, Address(TMP)); | 797 __ lw(result, Address(TMP)); |
| 798 } | 798 } |
| 799 | 799 |
| 800 | 800 |
| 801 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(bool opt) const { | 801 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(bool opt) const { |
| 802 const intptr_t kNumInputs = 1; | 802 const intptr_t kNumInputs = 1; |
| 803 return LocationSummary::Make(kNumInputs, | 803 return LocationSummary::Make(kNumInputs, |
| 804 Location::RequiresRegister(), | 804 Location::RequiresRegister(), |
| 805 LocationSummary::kNoCall); | 805 LocationSummary::kNoCall); |
| 806 } | 806 } |
| 807 | 807 |
| 808 | 808 |
| 809 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 809 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 810 __ TraceSimMsg("StringToCharCodeInstr"); | 810 __ TraceSimMsg("StringToCharCodeInstr"); |
| 811 | 811 |
| 812 ASSERT(cid_ == kOneByteStringCid); | 812 ASSERT(cid_ == kOneByteStringCid); |
| 813 Register str = locs()->in(0).reg(); | 813 Register str = locs()->in(0).reg(); |
| 814 Register result = locs()->out().reg(); | 814 Register result = locs()->out(0).reg(); |
| 815 Label done, is_one; | 815 Label done, is_one; |
| 816 __ lw(result, FieldAddress(str, String::length_offset())); | 816 __ lw(result, FieldAddress(str, String::length_offset())); |
| 817 __ BranchEqual(result, Smi::RawValue(1), &is_one); | 817 __ BranchEqual(result, Smi::RawValue(1), &is_one); |
| 818 __ LoadImmediate(result, Smi::RawValue(-1)); | 818 __ LoadImmediate(result, Smi::RawValue(-1)); |
| 819 __ b(&done); | 819 __ b(&done); |
| 820 __ Bind(&is_one); | 820 __ Bind(&is_one); |
| 821 __ lbu(result, FieldAddress(str, OneByteString::data_offset())); | 821 __ lbu(result, FieldAddress(str, OneByteString::data_offset())); |
| 822 __ SmiTag(result); | 822 __ SmiTag(result); |
| 823 __ Bind(&done); | 823 __ Bind(&done); |
| 824 } | 824 } |
| 825 | 825 |
| 826 | 826 |
| 827 LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const { | 827 LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const { |
| 828 const intptr_t kNumInputs = 1; | 828 const intptr_t kNumInputs = 1; |
| 829 const intptr_t kNumTemps = 0; | 829 const intptr_t kNumTemps = 0; |
| 830 LocationSummary* summary = | 830 LocationSummary* summary = |
| 831 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 831 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 832 summary->set_in(0, Location::RegisterLocation(A0)); | 832 summary->set_in(0, Location::RegisterLocation(A0)); |
| 833 summary->set_out(Location::RegisterLocation(V0)); | 833 summary->set_out(0, Location::RegisterLocation(V0)); |
| 834 return summary; | 834 return summary; |
| 835 } | 835 } |
| 836 | 836 |
| 837 | 837 |
| 838 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 838 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 839 Register array = locs()->in(0).reg(); | 839 Register array = locs()->in(0).reg(); |
| 840 __ Push(array); | 840 __ Push(array); |
| 841 const int kNumberOfArguments = 1; | 841 const int kNumberOfArguments = 1; |
| 842 const Array& kNoArgumentNames = Object::null_array(); | 842 const Array& kNoArgumentNames = Object::null_array(); |
| 843 compiler->GenerateStaticCall(deopt_id(), | 843 compiler->GenerateStaticCall(deopt_id(), |
| 844 token_pos(), | 844 token_pos(), |
| 845 CallFunction(), | 845 CallFunction(), |
| 846 kNumberOfArguments, | 846 kNumberOfArguments, |
| 847 kNoArgumentNames, | 847 kNoArgumentNames, |
| 848 locs()); | 848 locs()); |
| 849 ASSERT(locs()->out().reg() == V0); | 849 ASSERT(locs()->out(0).reg() == V0); |
| 850 } | 850 } |
| 851 | 851 |
| 852 | 852 |
| 853 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const { | 853 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const { |
| 854 const intptr_t kNumInputs = 1; | 854 const intptr_t kNumInputs = 1; |
| 855 return LocationSummary::Make(kNumInputs, | 855 return LocationSummary::Make(kNumInputs, |
| 856 Location::RequiresRegister(), | 856 Location::RequiresRegister(), |
| 857 LocationSummary::kNoCall); | 857 LocationSummary::kNoCall); |
| 858 } | 858 } |
| 859 | 859 |
| 860 | 860 |
| 861 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 861 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 862 Register object = locs()->in(0).reg(); | 862 Register object = locs()->in(0).reg(); |
| 863 Register result = locs()->out().reg(); | 863 Register result = locs()->out(0).reg(); |
| 864 __ LoadFromOffset(result, object, offset() - kHeapObjectTag); | 864 __ LoadFromOffset(result, object, offset() - kHeapObjectTag); |
| 865 } | 865 } |
| 866 | 866 |
| 867 | 867 |
| 868 LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const { | 868 LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const { |
| 869 const intptr_t kNumInputs = 1; | 869 const intptr_t kNumInputs = 1; |
| 870 return LocationSummary::Make(kNumInputs, | 870 return LocationSummary::Make(kNumInputs, |
| 871 Location::RequiresRegister(), | 871 Location::RequiresRegister(), |
| 872 LocationSummary::kNoCall); | 872 LocationSummary::kNoCall); |
| 873 } | 873 } |
| 874 | 874 |
| 875 | 875 |
| 876 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 876 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 877 Register object = locs()->in(0).reg(); | 877 Register object = locs()->in(0).reg(); |
| 878 Register result = locs()->out().reg(); | 878 Register result = locs()->out(0).reg(); |
| 879 Label load, done; | 879 Label load, done; |
| 880 __ andi(CMPRES1, object, Immediate(kSmiTagMask)); | 880 __ andi(CMPRES1, object, Immediate(kSmiTagMask)); |
| 881 __ bne(CMPRES1, ZR, &load); | 881 __ bne(CMPRES1, ZR, &load); |
| 882 __ LoadImmediate(result, Smi::RawValue(kSmiCid)); | 882 __ LoadImmediate(result, Smi::RawValue(kSmiCid)); |
| 883 __ b(&done); | 883 __ b(&done); |
| 884 __ Bind(&load); | 884 __ Bind(&load); |
| 885 __ LoadClassId(result, object); | 885 __ LoadClassId(result, object); |
| 886 __ SmiTag(result); | 886 __ SmiTag(result); |
| 887 __ Bind(&done); | 887 __ Bind(&done); |
| 888 } | 888 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 967 LocationSummary* locs = | 967 LocationSummary* locs = |
| 968 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 968 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 969 locs->set_in(0, Location::RequiresRegister()); | 969 locs->set_in(0, Location::RequiresRegister()); |
| 970 // The smi index is either untagged (element size == 1), or it is left smi | 970 // The smi index is either untagged (element size == 1), or it is left smi |
| 971 // tagged (for all element sizes > 1). | 971 // tagged (for all element sizes > 1). |
| 972 // TODO(regis): Revisit and see if the index can be immediate. | 972 // TODO(regis): Revisit and see if the index can be immediate. |
| 973 locs->set_in(1, Location::WritableRegister()); | 973 locs->set_in(1, Location::WritableRegister()); |
| 974 if ((representation() == kUnboxedDouble) || | 974 if ((representation() == kUnboxedDouble) || |
| 975 (representation() == kUnboxedFloat32x4) || | 975 (representation() == kUnboxedFloat32x4) || |
| 976 (representation() == kUnboxedInt32x4)) { | 976 (representation() == kUnboxedInt32x4)) { |
| 977 locs->set_out(Location::RequiresFpuRegister()); | 977 locs->set_out(0, Location::RequiresFpuRegister()); |
| 978 } else { | 978 } else { |
| 979 locs->set_out(Location::RequiresRegister()); | 979 locs->set_out(0, Location::RequiresRegister()); |
| 980 } | 980 } |
| 981 return locs; | 981 return locs; |
| 982 } | 982 } |
| 983 | 983 |
| 984 | 984 |
| 985 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 985 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 986 __ TraceSimMsg("LoadIndexedInstr"); | 986 __ TraceSimMsg("LoadIndexedInstr"); |
| 987 Register array = locs()->in(0).reg(); | 987 Register array = locs()->in(0).reg(); |
| 988 Location index = locs()->in(1); | 988 Location index = locs()->in(1); |
| 989 | 989 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 // mode, then we must load the offset into a register and add it to the | 1027 // mode, then we must load the offset into a register and add it to the |
| 1028 // index. | 1028 // index. |
| 1029 element_address = Address(index.reg(), | 1029 element_address = Address(index.reg(), |
| 1030 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); | 1030 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 1031 } | 1031 } |
| 1032 | 1032 |
| 1033 if ((representation() == kUnboxedDouble) || | 1033 if ((representation() == kUnboxedDouble) || |
| 1034 (representation() == kUnboxedMint) || | 1034 (representation() == kUnboxedMint) || |
| 1035 (representation() == kUnboxedFloat32x4) || | 1035 (representation() == kUnboxedFloat32x4) || |
| 1036 (representation() == kUnboxedInt32x4)) { | 1036 (representation() == kUnboxedInt32x4)) { |
| 1037 DRegister result = locs()->out().fpu_reg(); | 1037 DRegister result = locs()->out(0).fpu_reg(); |
| 1038 switch (class_id()) { | 1038 switch (class_id()) { |
| 1039 case kTypedDataInt32ArrayCid: | 1039 case kTypedDataInt32ArrayCid: |
| 1040 UNIMPLEMENTED(); | 1040 UNIMPLEMENTED(); |
| 1041 break; | 1041 break; |
| 1042 case kTypedDataUint32ArrayCid: | 1042 case kTypedDataUint32ArrayCid: |
| 1043 UNIMPLEMENTED(); | 1043 UNIMPLEMENTED(); |
| 1044 break; | 1044 break; |
| 1045 case kTypedDataFloat32ArrayCid: | 1045 case kTypedDataFloat32ArrayCid: |
| 1046 // Load single precision float. | 1046 // Load single precision float. |
| 1047 __ lwc1(EvenFRegisterOf(result), element_address); | 1047 __ lwc1(EvenFRegisterOf(result), element_address); |
| 1048 break; | 1048 break; |
| 1049 case kTypedDataFloat64ArrayCid: | 1049 case kTypedDataFloat64ArrayCid: |
| 1050 __ LoadDFromOffset(result, index.reg(), | 1050 __ LoadDFromOffset(result, index.reg(), |
| 1051 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); | 1051 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 1052 break; | 1052 break; |
| 1053 case kTypedDataInt32x4ArrayCid: | 1053 case kTypedDataInt32x4ArrayCid: |
| 1054 case kTypedDataFloat32x4ArrayCid: | 1054 case kTypedDataFloat32x4ArrayCid: |
| 1055 UNIMPLEMENTED(); | 1055 UNIMPLEMENTED(); |
| 1056 break; | 1056 break; |
| 1057 } | 1057 } |
| 1058 return; | 1058 return; |
| 1059 } | 1059 } |
| 1060 | 1060 |
| 1061 Register result = locs()->out().reg(); | 1061 Register result = locs()->out(0).reg(); |
| 1062 switch (class_id()) { | 1062 switch (class_id()) { |
| 1063 case kTypedDataInt8ArrayCid: | 1063 case kTypedDataInt8ArrayCid: |
| 1064 ASSERT(index_scale() == 1); | 1064 ASSERT(index_scale() == 1); |
| 1065 __ lb(result, element_address); | 1065 __ lb(result, element_address); |
| 1066 __ SmiTag(result); | 1066 __ SmiTag(result); |
| 1067 break; | 1067 break; |
| 1068 case kTypedDataUint8ArrayCid: | 1068 case kTypedDataUint8ArrayCid: |
| 1069 case kTypedDataUint8ClampedArrayCid: | 1069 case kTypedDataUint8ClampedArrayCid: |
| 1070 case kExternalTypedDataUint8ArrayCid: | 1070 case kExternalTypedDataUint8ArrayCid: |
| 1071 case kExternalTypedDataUint8ClampedArrayCid: | 1071 case kExternalTypedDataUint8ClampedArrayCid: |
| (...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1661 : instruction_(instruction), cls_(cls) { } | 1661 : instruction_(instruction), cls_(cls) { } |
| 1662 | 1662 |
| 1663 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1663 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1664 __ Comment("StoreInstanceFieldSlowPath"); | 1664 __ Comment("StoreInstanceFieldSlowPath"); |
| 1665 __ Bind(entry_label()); | 1665 __ Bind(entry_label()); |
| 1666 const Code& stub = | 1666 const Code& stub = |
| 1667 Code::Handle(StubCode::GetAllocationStubForClass(cls_)); | 1667 Code::Handle(StubCode::GetAllocationStubForClass(cls_)); |
| 1668 const ExternalLabel label(cls_.ToCString(), stub.EntryPoint()); | 1668 const ExternalLabel label(cls_.ToCString(), stub.EntryPoint()); |
| 1669 | 1669 |
| 1670 LocationSummary* locs = instruction_->locs(); | 1670 LocationSummary* locs = instruction_->locs(); |
| 1671 locs->live_registers()->Remove(locs->out()); | 1671 locs->live_registers()->Remove(locs->out(0)); |
| 1672 | 1672 |
| 1673 compiler->SaveLiveRegisters(locs); | 1673 compiler->SaveLiveRegisters(locs); |
| 1674 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 1674 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 1675 &label, | 1675 &label, |
| 1676 PcDescriptors::kOther, | 1676 PcDescriptors::kOther, |
| 1677 locs); | 1677 locs); |
| 1678 __ mov(locs->temp(0).reg(), V0); | 1678 __ mov(locs->temp(0).reg(), V0); |
| 1679 compiler->RestoreLiveRegisters(locs); | 1679 compiler->RestoreLiveRegisters(locs); |
| 1680 | 1680 |
| 1681 __ b(exit_label()); | 1681 __ b(exit_label()); |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1850 __ Bind(&skip_store); | 1850 __ Bind(&skip_store); |
| 1851 } | 1851 } |
| 1852 | 1852 |
| 1853 | 1853 |
| 1854 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const { | 1854 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const { |
| 1855 const intptr_t kNumInputs = 1; | 1855 const intptr_t kNumInputs = 1; |
| 1856 const intptr_t kNumTemps = 0; | 1856 const intptr_t kNumTemps = 0; |
| 1857 LocationSummary* summary = | 1857 LocationSummary* summary = |
| 1858 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1858 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1859 summary->set_in(0, Location::RequiresRegister()); | 1859 summary->set_in(0, Location::RequiresRegister()); |
| 1860 summary->set_out(Location::RequiresRegister()); | 1860 summary->set_out(0, Location::RequiresRegister()); |
| 1861 return summary; | 1861 return summary; |
| 1862 } | 1862 } |
| 1863 | 1863 |
| 1864 | 1864 |
| 1865 // When the parser is building an implicit static getter for optimization, | 1865 // When the parser is building an implicit static getter for optimization, |
| 1866 // it can generate a function body where deoptimization ids do not line up | 1866 // it can generate a function body where deoptimization ids do not line up |
| 1867 // with the unoptimized code. | 1867 // with the unoptimized code. |
| 1868 // | 1868 // |
| 1869 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 1869 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
| 1870 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1870 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1871 __ TraceSimMsg("LoadStaticFieldInstr"); | 1871 __ TraceSimMsg("LoadStaticFieldInstr"); |
| 1872 Register field = locs()->in(0).reg(); | 1872 Register field = locs()->in(0).reg(); |
| 1873 Register result = locs()->out().reg(); | 1873 Register result = locs()->out(0).reg(); |
| 1874 __ lw(result, FieldAddress(field, Field::value_offset())); | 1874 __ lw(result, FieldAddress(field, Field::value_offset())); |
| 1875 } | 1875 } |
| 1876 | 1876 |
| 1877 | 1877 |
| 1878 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const { | 1878 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const { |
| 1879 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall); | 1879 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall); |
| 1880 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 1880 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 1881 : Location::RequiresRegister()); | 1881 : Location::RequiresRegister()); |
| 1882 locs->set_temp(0, Location::RequiresRegister()); | 1882 locs->set_temp(0, Location::RequiresRegister()); |
| 1883 return locs; | 1883 return locs; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1901 | 1901 |
| 1902 | 1902 |
| 1903 LocationSummary* InstanceOfInstr::MakeLocationSummary(bool opt) const { | 1903 LocationSummary* InstanceOfInstr::MakeLocationSummary(bool opt) const { |
| 1904 const intptr_t kNumInputs = 3; | 1904 const intptr_t kNumInputs = 3; |
| 1905 const intptr_t kNumTemps = 0; | 1905 const intptr_t kNumTemps = 0; |
| 1906 LocationSummary* summary = | 1906 LocationSummary* summary = |
| 1907 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1907 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1908 summary->set_in(0, Location::RegisterLocation(A0)); | 1908 summary->set_in(0, Location::RegisterLocation(A0)); |
| 1909 summary->set_in(1, Location::RegisterLocation(A2)); | 1909 summary->set_in(1, Location::RegisterLocation(A2)); |
| 1910 summary->set_in(2, Location::RegisterLocation(A1)); | 1910 summary->set_in(2, Location::RegisterLocation(A1)); |
| 1911 summary->set_out(Location::RegisterLocation(V0)); | 1911 summary->set_out(0, Location::RegisterLocation(V0)); |
| 1912 return summary; | 1912 return summary; |
| 1913 } | 1913 } |
| 1914 | 1914 |
| 1915 | 1915 |
| 1916 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1916 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1917 ASSERT(locs()->in(0).reg() == A0); // Value. | 1917 ASSERT(locs()->in(0).reg() == A0); // Value. |
| 1918 ASSERT(locs()->in(1).reg() == A2); // Instantiator. | 1918 ASSERT(locs()->in(1).reg() == A2); // Instantiator. |
| 1919 ASSERT(locs()->in(2).reg() == A1); // Instantiator type arguments. | 1919 ASSERT(locs()->in(2).reg() == A1); // Instantiator type arguments. |
| 1920 | 1920 |
| 1921 __ Comment("InstanceOfInstr"); | 1921 __ Comment("InstanceOfInstr"); |
| 1922 compiler->GenerateInstanceOf(token_pos(), | 1922 compiler->GenerateInstanceOf(token_pos(), |
| 1923 deopt_id(), | 1923 deopt_id(), |
| 1924 type(), | 1924 type(), |
| 1925 negate_result(), | 1925 negate_result(), |
| 1926 locs()); | 1926 locs()); |
| 1927 ASSERT(locs()->out().reg() == V0); | 1927 ASSERT(locs()->out(0).reg() == V0); |
| 1928 } | 1928 } |
| 1929 | 1929 |
| 1930 | 1930 |
| 1931 LocationSummary* CreateArrayInstr::MakeLocationSummary(bool opt) const { | 1931 LocationSummary* CreateArrayInstr::MakeLocationSummary(bool opt) const { |
| 1932 const intptr_t kNumInputs = 2; | 1932 const intptr_t kNumInputs = 2; |
| 1933 const intptr_t kNumTemps = 0; | 1933 const intptr_t kNumTemps = 0; |
| 1934 LocationSummary* locs = | 1934 LocationSummary* locs = |
| 1935 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1935 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1936 locs->set_in(0, Location::RegisterLocation(A0)); | 1936 locs->set_in(0, Location::RegisterLocation(A0)); |
| 1937 locs->set_in(1, Location::RegisterLocation(A1)); | 1937 locs->set_in(1, Location::RegisterLocation(A1)); |
| 1938 locs->set_out(Location::RegisterLocation(V0)); | 1938 locs->set_out(0, Location::RegisterLocation(V0)); |
| 1939 return locs; | 1939 return locs; |
| 1940 } | 1940 } |
| 1941 | 1941 |
| 1942 | 1942 |
| 1943 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1943 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1944 __ TraceSimMsg("CreateArrayInstr"); | 1944 __ TraceSimMsg("CreateArrayInstr"); |
| 1945 // Allocate the array. A1 = length, A0 = element type. | 1945 // Allocate the array. A1 = length, A0 = element type. |
| 1946 ASSERT(locs()->in(0).reg() == A0); | 1946 ASSERT(locs()->in(0).reg() == A0); |
| 1947 ASSERT(locs()->in(1).reg() == A1); | 1947 ASSERT(locs()->in(1).reg() == A1); |
| 1948 compiler->GenerateCall(token_pos(), | 1948 compiler->GenerateCall(token_pos(), |
| 1949 &StubCode::AllocateArrayLabel(), | 1949 &StubCode::AllocateArrayLabel(), |
| 1950 PcDescriptors::kOther, | 1950 PcDescriptors::kOther, |
| 1951 locs()); | 1951 locs()); |
| 1952 ASSERT(locs()->out().reg() == V0); | 1952 ASSERT(locs()->out(0).reg() == V0); |
| 1953 } | 1953 } |
| 1954 | 1954 |
| 1955 | 1955 |
| 1956 class BoxDoubleSlowPath : public SlowPathCode { | 1956 class BoxDoubleSlowPath : public SlowPathCode { |
| 1957 public: | 1957 public: |
| 1958 explicit BoxDoubleSlowPath(Instruction* instruction) | 1958 explicit BoxDoubleSlowPath(Instruction* instruction) |
| 1959 : instruction_(instruction) { } | 1959 : instruction_(instruction) { } |
| 1960 | 1960 |
| 1961 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1961 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1962 __ Comment("BoxDoubleSlowPath"); | 1962 __ Comment("BoxDoubleSlowPath"); |
| 1963 __ Bind(entry_label()); | 1963 __ Bind(entry_label()); |
| 1964 const Class& double_class = compiler->double_class(); | 1964 const Class& double_class = compiler->double_class(); |
| 1965 const Code& stub = | 1965 const Code& stub = |
| 1966 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1966 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1967 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1967 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1968 | 1968 |
| 1969 LocationSummary* locs = instruction_->locs(); | 1969 LocationSummary* locs = instruction_->locs(); |
| 1970 locs->live_registers()->Remove(locs->out()); | 1970 locs->live_registers()->Remove(locs->out(0)); |
| 1971 | 1971 |
| 1972 compiler->SaveLiveRegisters(locs); | 1972 compiler->SaveLiveRegisters(locs); |
| 1973 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 1973 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 1974 &label, | 1974 &label, |
| 1975 PcDescriptors::kOther, | 1975 PcDescriptors::kOther, |
| 1976 locs); | 1976 locs); |
| 1977 if (locs->out().reg() != V0) { | 1977 if (locs->out(0).reg() != V0) { |
| 1978 __ mov(locs->out().reg(), V0); | 1978 __ mov(locs->out(0).reg(), V0); |
| 1979 } | 1979 } |
| 1980 compiler->RestoreLiveRegisters(locs); | 1980 compiler->RestoreLiveRegisters(locs); |
| 1981 | 1981 |
| 1982 __ b(exit_label()); | 1982 __ b(exit_label()); |
| 1983 } | 1983 } |
| 1984 | 1984 |
| 1985 private: | 1985 private: |
| 1986 Instruction* instruction_; | 1986 Instruction* instruction_; |
| 1987 }; | 1987 }; |
| 1988 | 1988 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1999 | 1999 |
| 2000 locs->set_in(0, Location::RequiresRegister()); | 2000 locs->set_in(0, Location::RequiresRegister()); |
| 2001 | 2001 |
| 2002 if (IsUnboxedLoad() && opt) { | 2002 if (IsUnboxedLoad() && opt) { |
| 2003 locs->AddTemp(Location::RequiresRegister()); | 2003 locs->AddTemp(Location::RequiresRegister()); |
| 2004 } else if (IsPotentialUnboxedLoad()) { | 2004 } else if (IsPotentialUnboxedLoad()) { |
| 2005 locs->AddTemp(opt ? Location::RequiresFpuRegister() | 2005 locs->AddTemp(opt ? Location::RequiresFpuRegister() |
| 2006 : Location::FpuRegisterLocation(D1)); | 2006 : Location::FpuRegisterLocation(D1)); |
| 2007 locs->AddTemp(Location::RequiresRegister()); | 2007 locs->AddTemp(Location::RequiresRegister()); |
| 2008 } | 2008 } |
| 2009 locs->set_out(Location::RequiresRegister()); | 2009 locs->set_out(0, Location::RequiresRegister()); |
| 2010 return locs; | 2010 return locs; |
| 2011 } | 2011 } |
| 2012 | 2012 |
| 2013 | 2013 |
| 2014 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2014 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2015 Register instance_reg = locs()->in(0).reg(); | 2015 Register instance_reg = locs()->in(0).reg(); |
| 2016 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2016 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
| 2017 DRegister result = locs()->out().fpu_reg(); | 2017 DRegister result = locs()->out(0).fpu_reg(); |
| 2018 Register temp = locs()->temp(0).reg(); | 2018 Register temp = locs()->temp(0).reg(); |
| 2019 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2019 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2020 intptr_t cid = field()->UnboxedFieldCid(); | 2020 intptr_t cid = field()->UnboxedFieldCid(); |
| 2021 switch (cid) { | 2021 switch (cid) { |
| 2022 case kDoubleCid: | 2022 case kDoubleCid: |
| 2023 __ LoadDFromOffset(result, temp, | 2023 __ LoadDFromOffset(result, temp, |
| 2024 Double::value_offset() - kHeapObjectTag); | 2024 Double::value_offset() - kHeapObjectTag); |
| 2025 break; | 2025 break; |
| 2026 default: | 2026 default: |
| 2027 UNREACHABLE(); | 2027 UNREACHABLE(); |
| 2028 } | 2028 } |
| 2029 return; | 2029 return; |
| 2030 } | 2030 } |
| 2031 | 2031 |
| 2032 Label done; | 2032 Label done; |
| 2033 Register result_reg = locs()->out().reg(); | 2033 Register result_reg = locs()->out(0).reg(); |
| 2034 if (IsPotentialUnboxedLoad()) { | 2034 if (IsPotentialUnboxedLoad()) { |
| 2035 Register temp = locs()->temp(1).reg(); | 2035 Register temp = locs()->temp(1).reg(); |
| 2036 DRegister value = locs()->temp(0).fpu_reg(); | 2036 DRegister value = locs()->temp(0).fpu_reg(); |
| 2037 | 2037 |
| 2038 Label load_pointer; | 2038 Label load_pointer; |
| 2039 Label load_double; | 2039 Label load_double; |
| 2040 | 2040 |
| 2041 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw())); | 2041 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw())); |
| 2042 | 2042 |
| 2043 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); | 2043 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2081 __ Bind(&done); | 2081 __ Bind(&done); |
| 2082 } | 2082 } |
| 2083 | 2083 |
| 2084 | 2084 |
| 2085 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { | 2085 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { |
| 2086 const intptr_t kNumInputs = 1; | 2086 const intptr_t kNumInputs = 1; |
| 2087 const intptr_t kNumTemps = 0; | 2087 const intptr_t kNumTemps = 0; |
| 2088 LocationSummary* locs = | 2088 LocationSummary* locs = |
| 2089 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 2089 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2090 locs->set_in(0, Location::RegisterLocation(T0)); | 2090 locs->set_in(0, Location::RegisterLocation(T0)); |
| 2091 locs->set_out(Location::RegisterLocation(T0)); | 2091 locs->set_out(0, Location::RegisterLocation(T0)); |
| 2092 return locs; | 2092 return locs; |
| 2093 } | 2093 } |
| 2094 | 2094 |
| 2095 | 2095 |
| 2096 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2096 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2097 __ TraceSimMsg("InstantiateTypeInstr"); | 2097 __ TraceSimMsg("InstantiateTypeInstr"); |
| 2098 Register instantiator_reg = locs()->in(0).reg(); | 2098 Register instantiator_reg = locs()->in(0).reg(); |
| 2099 Register result_reg = locs()->out().reg(); | 2099 Register result_reg = locs()->out(0).reg(); |
| 2100 | 2100 |
| 2101 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2101 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2102 // A runtime call to instantiate the type is required. | 2102 // A runtime call to instantiate the type is required. |
| 2103 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 2103 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 2104 __ LoadObject(TMP, Object::ZoneHandle()); | 2104 __ LoadObject(TMP, Object::ZoneHandle()); |
| 2105 __ sw(TMP, Address(SP, 2 * kWordSize)); // Make room for the result. | 2105 __ sw(TMP, Address(SP, 2 * kWordSize)); // Make room for the result. |
| 2106 __ LoadObject(TMP, type()); | 2106 __ LoadObject(TMP, type()); |
| 2107 __ sw(TMP, Address(SP, 1 * kWordSize)); | 2107 __ sw(TMP, Address(SP, 1 * kWordSize)); |
| 2108 // Push instantiator type arguments. | 2108 // Push instantiator type arguments. |
| 2109 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); | 2109 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2121 } | 2121 } |
| 2122 | 2122 |
| 2123 | 2123 |
| 2124 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2124 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
| 2125 bool opt) const { | 2125 bool opt) const { |
| 2126 const intptr_t kNumInputs = 1; | 2126 const intptr_t kNumInputs = 1; |
| 2127 const intptr_t kNumTemps = 0; | 2127 const intptr_t kNumTemps = 0; |
| 2128 LocationSummary* locs = | 2128 LocationSummary* locs = |
| 2129 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 2129 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2130 locs->set_in(0, Location::RegisterLocation(T0)); | 2130 locs->set_in(0, Location::RegisterLocation(T0)); |
| 2131 locs->set_out(Location::RegisterLocation(T0)); | 2131 locs->set_out(0, Location::RegisterLocation(T0)); |
| 2132 return locs; | 2132 return locs; |
| 2133 } | 2133 } |
| 2134 | 2134 |
| 2135 | 2135 |
| 2136 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2136 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 2137 FlowGraphCompiler* compiler) { | 2137 FlowGraphCompiler* compiler) { |
| 2138 __ TraceSimMsg("InstantiateTypeArgumentsInstr"); | 2138 __ TraceSimMsg("InstantiateTypeArgumentsInstr"); |
| 2139 Register instantiator_reg = locs()->in(0).reg(); | 2139 Register instantiator_reg = locs()->in(0).reg(); |
| 2140 Register result_reg = locs()->out().reg(); | 2140 Register result_reg = locs()->out(0).reg(); |
| 2141 ASSERT(instantiator_reg == T0); | 2141 ASSERT(instantiator_reg == T0); |
| 2142 ASSERT(instantiator_reg == result_reg); | 2142 ASSERT(instantiator_reg == result_reg); |
| 2143 | 2143 |
| 2144 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2144 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2145 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2145 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
| 2146 !type_arguments().CanShareInstantiatorTypeArguments( | 2146 !type_arguments().CanShareInstantiatorTypeArguments( |
| 2147 instantiator_class())); | 2147 instantiator_class())); |
| 2148 // If the instantiator is null and if the type argument vector | 2148 // If the instantiator is null and if the type argument vector |
| 2149 // instantiated from null becomes a vector of dynamic, then use null as | 2149 // instantiated from null becomes a vector of dynamic, then use null as |
| 2150 // the type arguments. | 2150 // the type arguments. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2194 __ Bind(&type_arguments_instantiated); | 2194 __ Bind(&type_arguments_instantiated); |
| 2195 } | 2195 } |
| 2196 | 2196 |
| 2197 | 2197 |
| 2198 LocationSummary* AllocateContextInstr::MakeLocationSummary(bool opt) const { | 2198 LocationSummary* AllocateContextInstr::MakeLocationSummary(bool opt) const { |
| 2199 const intptr_t kNumInputs = 0; | 2199 const intptr_t kNumInputs = 0; |
| 2200 const intptr_t kNumTemps = 1; | 2200 const intptr_t kNumTemps = 1; |
| 2201 LocationSummary* locs = | 2201 LocationSummary* locs = |
| 2202 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 2202 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2203 locs->set_temp(0, Location::RegisterLocation(T1)); | 2203 locs->set_temp(0, Location::RegisterLocation(T1)); |
| 2204 locs->set_out(Location::RegisterLocation(V0)); | 2204 locs->set_out(0, Location::RegisterLocation(V0)); |
| 2205 return locs; | 2205 return locs; |
| 2206 } | 2206 } |
| 2207 | 2207 |
| 2208 | 2208 |
| 2209 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2209 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2210 Register temp = T1; | 2210 Register temp = T1; |
| 2211 ASSERT(locs()->temp(0).reg() == temp); | 2211 ASSERT(locs()->temp(0).reg() == temp); |
| 2212 ASSERT(locs()->out().reg() == V0); | 2212 ASSERT(locs()->out(0).reg() == V0); |
| 2213 | 2213 |
| 2214 __ TraceSimMsg("AllocateContextInstr"); | 2214 __ TraceSimMsg("AllocateContextInstr"); |
| 2215 __ LoadImmediate(temp, num_context_variables()); | 2215 __ LoadImmediate(temp, num_context_variables()); |
| 2216 const ExternalLabel label("alloc_context", | 2216 const ExternalLabel label("alloc_context", |
| 2217 StubCode::AllocateContextEntryPoint()); | 2217 StubCode::AllocateContextEntryPoint()); |
| 2218 compiler->GenerateCall(token_pos(), | 2218 compiler->GenerateCall(token_pos(), |
| 2219 &label, | 2219 &label, |
| 2220 PcDescriptors::kOther, | 2220 PcDescriptors::kOther, |
| 2221 locs()); | 2221 locs()); |
| 2222 } | 2222 } |
| 2223 | 2223 |
| 2224 | 2224 |
| 2225 LocationSummary* CloneContextInstr::MakeLocationSummary(bool opt) const { | 2225 LocationSummary* CloneContextInstr::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(T0)); | 2230 locs->set_in(0, Location::RegisterLocation(T0)); |
| 2231 locs->set_out(Location::RegisterLocation(T0)); | 2231 locs->set_out(0, Location::RegisterLocation(T0)); |
| 2232 return locs; | 2232 return locs; |
| 2233 } | 2233 } |
| 2234 | 2234 |
| 2235 | 2235 |
| 2236 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2236 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2237 Register context_value = locs()->in(0).reg(); | 2237 Register context_value = locs()->in(0).reg(); |
| 2238 Register result = locs()->out().reg(); | 2238 Register result = locs()->out(0).reg(); |
| 2239 | 2239 |
| 2240 __ TraceSimMsg("CloneContextInstr"); | 2240 __ TraceSimMsg("CloneContextInstr"); |
| 2241 | 2241 |
| 2242 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 2242 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 2243 __ LoadObject(TMP, Object::ZoneHandle()); // Make room for the result. | 2243 __ LoadObject(TMP, Object::ZoneHandle()); // Make room for the result. |
| 2244 __ sw(TMP, Address(SP, 1 * kWordSize)); | 2244 __ sw(TMP, Address(SP, 1 * kWordSize)); |
| 2245 __ sw(context_value, Address(SP, 0 * kWordSize)); | 2245 __ sw(context_value, Address(SP, 0 * kWordSize)); |
| 2246 | 2246 |
| 2247 compiler->GenerateRuntimeCall(token_pos(), | 2247 compiler->GenerateRuntimeCall(token_pos(), |
| 2248 deopt_id(), | 2248 deopt_id(), |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2365 } | 2365 } |
| 2366 __ Bind(slow_path->exit_label()); | 2366 __ Bind(slow_path->exit_label()); |
| 2367 } | 2367 } |
| 2368 | 2368 |
| 2369 | 2369 |
| 2370 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2370 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 2371 BinarySmiOpInstr* shift_left) { | 2371 BinarySmiOpInstr* shift_left) { |
| 2372 const bool is_truncating = shift_left->is_truncating(); | 2372 const bool is_truncating = shift_left->is_truncating(); |
| 2373 const LocationSummary& locs = *shift_left->locs(); | 2373 const LocationSummary& locs = *shift_left->locs(); |
| 2374 Register left = locs.in(0).reg(); | 2374 Register left = locs.in(0).reg(); |
| 2375 Register result = locs.out().reg(); | 2375 Register result = locs.out(0).reg(); |
| 2376 Label* deopt = shift_left->CanDeoptimize() ? | 2376 Label* deopt = shift_left->CanDeoptimize() ? |
| 2377 compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL; | 2377 compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL; |
| 2378 | 2378 |
| 2379 __ TraceSimMsg("EmitSmiShiftLeft"); | 2379 __ TraceSimMsg("EmitSmiShiftLeft"); |
| 2380 | 2380 |
| 2381 if (locs.in(1).IsConstant()) { | 2381 if (locs.in(1).IsConstant()) { |
| 2382 const Object& constant = locs.in(1).constant(); | 2382 const Object& constant = locs.in(1).constant(); |
| 2383 ASSERT(constant.IsSmi()); | 2383 ASSERT(constant.IsSmi()); |
| 2384 // Immediate shift operation takes 5 bits for the count. | 2384 // Immediate shift operation takes 5 bits for the count. |
| 2385 const intptr_t kCountLimit = 0x1F; | 2385 const intptr_t kCountLimit = 0x1F; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2489 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2489 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2490 if (op_kind() == Token::kTRUNCDIV) { | 2490 if (op_kind() == Token::kTRUNCDIV) { |
| 2491 summary->set_in(0, Location::RequiresRegister()); | 2491 summary->set_in(0, Location::RequiresRegister()); |
| 2492 if (RightIsPowerOfTwoConstant()) { | 2492 if (RightIsPowerOfTwoConstant()) { |
| 2493 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 2493 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 2494 summary->set_in(1, Location::Constant(right_constant->value())); | 2494 summary->set_in(1, Location::Constant(right_constant->value())); |
| 2495 } else { | 2495 } else { |
| 2496 summary->set_in(1, Location::RequiresRegister()); | 2496 summary->set_in(1, Location::RequiresRegister()); |
| 2497 } | 2497 } |
| 2498 summary->AddTemp(Location::RequiresRegister()); | 2498 summary->AddTemp(Location::RequiresRegister()); |
| 2499 summary->set_out(Location::RequiresRegister()); | 2499 summary->set_out(0, Location::RequiresRegister()); |
| 2500 return summary; | 2500 return summary; |
| 2501 } | 2501 } |
| 2502 if (op_kind() == Token::kMOD) { | 2502 if (op_kind() == Token::kMOD) { |
| 2503 summary->set_in(0, Location::RequiresRegister()); | 2503 summary->set_in(0, Location::RequiresRegister()); |
| 2504 summary->set_in(1, Location::RequiresRegister()); | 2504 summary->set_in(1, Location::RequiresRegister()); |
| 2505 summary->AddTemp(Location::RequiresRegister()); | 2505 summary->AddTemp(Location::RequiresRegister()); |
| 2506 summary->set_out(Location::RequiresRegister()); | 2506 summary->set_out(0, Location::RequiresRegister()); |
| 2507 return summary; | 2507 return summary; |
| 2508 } | 2508 } |
| 2509 summary->set_in(0, Location::RequiresRegister()); | 2509 summary->set_in(0, Location::RequiresRegister()); |
| 2510 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 2510 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 2511 if (((op_kind() == Token::kSHL) && !is_truncating()) || | 2511 if (((op_kind() == Token::kSHL) && !is_truncating()) || |
| 2512 (op_kind() == Token::kSHR)) { | 2512 (op_kind() == Token::kSHR)) { |
| 2513 summary->AddTemp(Location::RequiresRegister()); | 2513 summary->AddTemp(Location::RequiresRegister()); |
| 2514 } else if (op_kind() == Token::kADD) { | 2514 } else if (op_kind() == Token::kADD) { |
| 2515 // Need an extra temp for the overflow detection code. | 2515 // Need an extra temp for the overflow detection code. |
| 2516 summary->set_temp(0, Location::RequiresRegister()); | 2516 summary->set_temp(0, Location::RequiresRegister()); |
| 2517 } | 2517 } |
| 2518 // We make use of 3-operand instructions by not requiring result register | 2518 // We make use of 3-operand instructions by not requiring result register |
| 2519 // to be identical to first input register as on Intel. | 2519 // to be identical to first input register as on Intel. |
| 2520 summary->set_out(Location::RequiresRegister()); | 2520 summary->set_out(0, Location::RequiresRegister()); |
| 2521 return summary; | 2521 return summary; |
| 2522 } | 2522 } |
| 2523 | 2523 |
| 2524 | 2524 |
| 2525 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2525 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2526 __ TraceSimMsg("BinarySmiOpInstr"); | 2526 __ TraceSimMsg("BinarySmiOpInstr"); |
| 2527 if (op_kind() == Token::kSHL) { | 2527 if (op_kind() == Token::kSHL) { |
| 2528 EmitSmiShiftLeft(compiler, this); | 2528 EmitSmiShiftLeft(compiler, this); |
| 2529 return; | 2529 return; |
| 2530 } | 2530 } |
| 2531 | 2531 |
| 2532 ASSERT(!is_truncating()); | 2532 ASSERT(!is_truncating()); |
| 2533 Register left = locs()->in(0).reg(); | 2533 Register left = locs()->in(0).reg(); |
| 2534 Register result = locs()->out().reg(); | 2534 Register result = locs()->out(0).reg(); |
| 2535 Label* deopt = NULL; | 2535 Label* deopt = NULL; |
| 2536 if (CanDeoptimize()) { | 2536 if (CanDeoptimize()) { |
| 2537 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 2537 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| 2538 } | 2538 } |
| 2539 | 2539 |
| 2540 if (locs()->in(1).IsConstant()) { | 2540 if (locs()->in(1).IsConstant()) { |
| 2541 const Object& constant = locs()->in(1).constant(); | 2541 const Object& constant = locs()->in(1).constant(); |
| 2542 ASSERT(constant.IsSmi()); | 2542 ASSERT(constant.IsSmi()); |
| 2543 int32_t imm = reinterpret_cast<int32_t>(constant.raw()); | 2543 int32_t imm = reinterpret_cast<int32_t>(constant.raw()); |
| 2544 switch (op_kind()) { | 2544 switch (op_kind()) { |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2862 | 2862 |
| 2863 LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const { | 2863 LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const { |
| 2864 const intptr_t kNumInputs = 1; | 2864 const intptr_t kNumInputs = 1; |
| 2865 const intptr_t kNumTemps = 1; | 2865 const intptr_t kNumTemps = 1; |
| 2866 LocationSummary* summary = | 2866 LocationSummary* summary = |
| 2867 new LocationSummary(kNumInputs, | 2867 new LocationSummary(kNumInputs, |
| 2868 kNumTemps, | 2868 kNumTemps, |
| 2869 LocationSummary::kCallOnSlowPath); | 2869 LocationSummary::kCallOnSlowPath); |
| 2870 summary->set_in(0, Location::RequiresFpuRegister()); | 2870 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2871 summary->set_temp(0, Location::RequiresRegister()); | 2871 summary->set_temp(0, Location::RequiresRegister()); |
| 2872 summary->set_out(Location::RequiresRegister()); | 2872 summary->set_out(0, Location::RequiresRegister()); |
| 2873 return summary; | 2873 return summary; |
| 2874 } | 2874 } |
| 2875 | 2875 |
| 2876 | 2876 |
| 2877 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2877 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2878 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 2878 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
| 2879 compiler->AddSlowPathCode(slow_path); | 2879 compiler->AddSlowPathCode(slow_path); |
| 2880 | 2880 |
| 2881 Register out_reg = locs()->out().reg(); | 2881 Register out_reg = locs()->out(0).reg(); |
| 2882 DRegister value = locs()->in(0).fpu_reg(); | 2882 DRegister value = locs()->in(0).fpu_reg(); |
| 2883 | 2883 |
| 2884 __ TryAllocate(compiler->double_class(), | 2884 __ TryAllocate(compiler->double_class(), |
| 2885 slow_path->entry_label(), | 2885 slow_path->entry_label(), |
| 2886 out_reg, | 2886 out_reg, |
| 2887 locs()->temp(0).reg()); | 2887 locs()->temp(0).reg()); |
| 2888 __ Bind(slow_path->exit_label()); | 2888 __ Bind(slow_path->exit_label()); |
| 2889 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); | 2889 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); |
| 2890 } | 2890 } |
| 2891 | 2891 |
| 2892 | 2892 |
| 2893 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const { | 2893 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const { |
| 2894 const intptr_t kNumInputs = 1; | 2894 const intptr_t kNumInputs = 1; |
| 2895 const intptr_t value_cid = value()->Type()->ToCid(); | 2895 const intptr_t value_cid = value()->Type()->ToCid(); |
| 2896 const bool needs_writable_input = (value_cid == kSmiCid); | 2896 const bool needs_writable_input = (value_cid == kSmiCid); |
| 2897 const intptr_t kNumTemps = 0; | 2897 const intptr_t kNumTemps = 0; |
| 2898 LocationSummary* summary = | 2898 LocationSummary* summary = |
| 2899 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2899 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2900 summary->set_in(0, needs_writable_input | 2900 summary->set_in(0, needs_writable_input |
| 2901 ? Location::WritableRegister() | 2901 ? Location::WritableRegister() |
| 2902 : Location::RequiresRegister()); | 2902 : Location::RequiresRegister()); |
| 2903 summary->set_out(Location::RequiresFpuRegister()); | 2903 summary->set_out(0, Location::RequiresFpuRegister()); |
| 2904 return summary; | 2904 return summary; |
| 2905 } | 2905 } |
| 2906 | 2906 |
| 2907 | 2907 |
| 2908 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2908 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2909 const intptr_t value_cid = value()->Type()->ToCid(); | 2909 const intptr_t value_cid = value()->Type()->ToCid(); |
| 2910 const Register value = locs()->in(0).reg(); | 2910 const Register value = locs()->in(0).reg(); |
| 2911 const DRegister result = locs()->out().fpu_reg(); | 2911 const DRegister result = locs()->out(0).fpu_reg(); |
| 2912 | 2912 |
| 2913 if (value_cid == kDoubleCid) { | 2913 if (value_cid == kDoubleCid) { |
| 2914 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); | 2914 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); |
| 2915 } else if (value_cid == kSmiCid) { | 2915 } else if (value_cid == kSmiCid) { |
| 2916 __ SmiUntag(value); // Untag input before conversion. | 2916 __ SmiUntag(value); // Untag input before conversion. |
| 2917 __ mtc1(value, STMP1); | 2917 __ mtc1(value, STMP1); |
| 2918 __ cvtdw(result, STMP1); | 2918 __ cvtdw(result, STMP1); |
| 2919 } else { | 2919 } else { |
| 2920 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); | 2920 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
| 2921 Label is_smi, done; | 2921 Label is_smi, done; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3002 } | 3002 } |
| 3003 | 3003 |
| 3004 | 3004 |
| 3005 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(bool opt) const { | 3005 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(bool opt) const { |
| 3006 const intptr_t kNumInputs = 2; | 3006 const intptr_t kNumInputs = 2; |
| 3007 const intptr_t kNumTemps = 0; | 3007 const intptr_t kNumTemps = 0; |
| 3008 LocationSummary* summary = | 3008 LocationSummary* summary = |
| 3009 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3009 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3010 summary->set_in(0, Location::RequiresFpuRegister()); | 3010 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3011 summary->set_in(1, Location::RequiresFpuRegister()); | 3011 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3012 summary->set_out(Location::RequiresFpuRegister()); | 3012 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3013 return summary; | 3013 return summary; |
| 3014 } | 3014 } |
| 3015 | 3015 |
| 3016 | 3016 |
| 3017 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3017 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3018 DRegister left = locs()->in(0).fpu_reg(); | 3018 DRegister left = locs()->in(0).fpu_reg(); |
| 3019 DRegister right = locs()->in(1).fpu_reg(); | 3019 DRegister right = locs()->in(1).fpu_reg(); |
| 3020 DRegister result = locs()->out().fpu_reg(); | 3020 DRegister result = locs()->out(0).fpu_reg(); |
| 3021 switch (op_kind()) { | 3021 switch (op_kind()) { |
| 3022 case Token::kADD: __ addd(result, left, right); break; | 3022 case Token::kADD: __ addd(result, left, right); break; |
| 3023 case Token::kSUB: __ subd(result, left, right); break; | 3023 case Token::kSUB: __ subd(result, left, right); break; |
| 3024 case Token::kMUL: __ muld(result, left, right); break; | 3024 case Token::kMUL: __ muld(result, left, right); break; |
| 3025 case Token::kDIV: __ divd(result, left, right); break; | 3025 case Token::kDIV: __ divd(result, left, right); break; |
| 3026 default: UNREACHABLE(); | 3026 default: UNREACHABLE(); |
| 3027 } | 3027 } |
| 3028 } | 3028 } |
| 3029 | 3029 |
| 3030 | 3030 |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3365 | 3365 |
| 3366 | 3366 |
| 3367 LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const { | 3367 LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const { |
| 3368 if ((kind() == MethodRecognizer::kMathSin) || | 3368 if ((kind() == MethodRecognizer::kMathSin) || |
| 3369 (kind() == MethodRecognizer::kMathCos)) { | 3369 (kind() == MethodRecognizer::kMathCos)) { |
| 3370 const intptr_t kNumInputs = 1; | 3370 const intptr_t kNumInputs = 1; |
| 3371 const intptr_t kNumTemps = 0; | 3371 const intptr_t kNumTemps = 0; |
| 3372 LocationSummary* summary = | 3372 LocationSummary* summary = |
| 3373 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 3373 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 3374 summary->set_in(0, Location::FpuRegisterLocation(D6)); | 3374 summary->set_in(0, Location::FpuRegisterLocation(D6)); |
| 3375 summary->set_out(Location::FpuRegisterLocation(D0)); | 3375 summary->set_out(0, Location::FpuRegisterLocation(D0)); |
| 3376 return summary; | 3376 return summary; |
| 3377 } | 3377 } |
| 3378 const intptr_t kNumInputs = 1; | 3378 const intptr_t kNumInputs = 1; |
| 3379 const intptr_t kNumTemps = 0; | 3379 const intptr_t kNumTemps = 0; |
| 3380 LocationSummary* summary = | 3380 LocationSummary* summary = |
| 3381 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3381 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3382 summary->set_in(0, Location::RequiresFpuRegister()); | 3382 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3383 summary->set_out(Location::RequiresFpuRegister()); | 3383 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3384 return summary; | 3384 return summary; |
| 3385 } | 3385 } |
| 3386 | 3386 |
| 3387 | 3387 |
| 3388 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3388 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3389 if (kind() == MethodRecognizer::kMathSqrt) { | 3389 if (kind() == MethodRecognizer::kMathSqrt) { |
| 3390 __ sqrtd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); | 3390 __ sqrtd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 3391 } else { | 3391 } else { |
| 3392 __ CallRuntime(TargetFunction(), InputCount()); | 3392 __ CallRuntime(TargetFunction(), InputCount()); |
| 3393 } | 3393 } |
| 3394 } | 3394 } |
| 3395 | 3395 |
| 3396 | 3396 |
| 3397 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const { | 3397 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const { |
| 3398 if (result_cid() == kDoubleCid) { | 3398 if (result_cid() == kDoubleCid) { |
| 3399 const intptr_t kNumInputs = 2; | 3399 const intptr_t kNumInputs = 2; |
| 3400 const intptr_t kNumTemps = 1; | 3400 const intptr_t kNumTemps = 1; |
| 3401 LocationSummary* summary = | 3401 LocationSummary* summary = |
| 3402 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3402 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3403 summary->set_in(0, Location::RequiresFpuRegister()); | 3403 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3404 summary->set_in(1, Location::RequiresFpuRegister()); | 3404 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3405 // Reuse the left register so that code can be made shorter. | 3405 // Reuse the left register so that code can be made shorter. |
| 3406 summary->set_out(Location::SameAsFirstInput()); | 3406 summary->set_out(0, Location::SameAsFirstInput()); |
| 3407 summary->set_temp(0, Location::RequiresRegister()); | 3407 summary->set_temp(0, Location::RequiresRegister()); |
| 3408 return summary; | 3408 return summary; |
| 3409 } | 3409 } |
| 3410 ASSERT(result_cid() == kSmiCid); | 3410 ASSERT(result_cid() == kSmiCid); |
| 3411 const intptr_t kNumInputs = 2; | 3411 const intptr_t kNumInputs = 2; |
| 3412 const intptr_t kNumTemps = 0; | 3412 const intptr_t kNumTemps = 0; |
| 3413 LocationSummary* summary = | 3413 LocationSummary* summary = |
| 3414 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3414 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3415 summary->set_in(0, Location::RequiresRegister()); | 3415 summary->set_in(0, Location::RequiresRegister()); |
| 3416 summary->set_in(1, Location::RequiresRegister()); | 3416 summary->set_in(1, Location::RequiresRegister()); |
| 3417 // Reuse the left register so that code can be made shorter. | 3417 // Reuse the left register so that code can be made shorter. |
| 3418 summary->set_out(Location::SameAsFirstInput()); | 3418 summary->set_out(0, Location::SameAsFirstInput()); |
| 3419 return summary; | 3419 return summary; |
| 3420 } | 3420 } |
| 3421 | 3421 |
| 3422 | 3422 |
| 3423 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3423 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3424 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 3424 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
| 3425 (op_kind() == MethodRecognizer::kMathMax)); | 3425 (op_kind() == MethodRecognizer::kMathMax)); |
| 3426 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); | 3426 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); |
| 3427 if (result_cid() == kDoubleCid) { | 3427 if (result_cid() == kDoubleCid) { |
| 3428 Label done, returns_nan, are_equal; | 3428 Label done, returns_nan, are_equal; |
| 3429 DRegister left = locs()->in(0).fpu_reg(); | 3429 DRegister left = locs()->in(0).fpu_reg(); |
| 3430 DRegister right = locs()->in(1).fpu_reg(); | 3430 DRegister right = locs()->in(1).fpu_reg(); |
| 3431 DRegister result = locs()->out().fpu_reg(); | 3431 DRegister result = locs()->out(0).fpu_reg(); |
| 3432 Register temp = locs()->temp(0).reg(); | 3432 Register temp = locs()->temp(0).reg(); |
| 3433 __ cund(left, right); | 3433 __ cund(left, right); |
| 3434 __ bc1t(&returns_nan); | 3434 __ bc1t(&returns_nan); |
| 3435 __ ceqd(left, right); | 3435 __ ceqd(left, right); |
| 3436 __ bc1t(&are_equal); | 3436 __ bc1t(&are_equal); |
| 3437 if (is_min) { | 3437 if (is_min) { |
| 3438 __ coltd(left, right); | 3438 __ coltd(left, right); |
| 3439 } else { | 3439 } else { |
| 3440 __ coltd(right, left); | 3440 __ coltd(right, left); |
| 3441 } | 3441 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3466 } | 3466 } |
| 3467 __ movd(result, right); | 3467 __ movd(result, right); |
| 3468 __ Bind(&done); | 3468 __ Bind(&done); |
| 3469 return; | 3469 return; |
| 3470 } | 3470 } |
| 3471 | 3471 |
| 3472 Label done; | 3472 Label done; |
| 3473 ASSERT(result_cid() == kSmiCid); | 3473 ASSERT(result_cid() == kSmiCid); |
| 3474 Register left = locs()->in(0).reg(); | 3474 Register left = locs()->in(0).reg(); |
| 3475 Register right = locs()->in(1).reg(); | 3475 Register right = locs()->in(1).reg(); |
| 3476 Register result = locs()->out().reg(); | 3476 Register result = locs()->out(0).reg(); |
| 3477 ASSERT(result == left); | 3477 ASSERT(result == left); |
| 3478 if (is_min) { | 3478 if (is_min) { |
| 3479 __ BranchSignedLessEqual(left, right, &done); | 3479 __ BranchSignedLessEqual(left, right, &done); |
| 3480 } else { | 3480 } else { |
| 3481 __ BranchSignedGreaterEqual(left, right, &done); | 3481 __ BranchSignedGreaterEqual(left, right, &done); |
| 3482 } | 3482 } |
| 3483 __ mov(result, right); | 3483 __ mov(result, right); |
| 3484 __ Bind(&done); | 3484 __ Bind(&done); |
| 3485 } | 3485 } |
| 3486 | 3486 |
| 3487 | 3487 |
| 3488 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const { | 3488 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const { |
| 3489 const intptr_t kNumInputs = 1; | 3489 const intptr_t kNumInputs = 1; |
| 3490 const intptr_t kNumTemps = 0; | 3490 const intptr_t kNumTemps = 0; |
| 3491 LocationSummary* summary = | 3491 LocationSummary* summary = |
| 3492 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3492 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3493 summary->set_in(0, Location::RequiresRegister()); | 3493 summary->set_in(0, Location::RequiresRegister()); |
| 3494 // We make use of 3-operand instructions by not requiring result register | 3494 // We make use of 3-operand instructions by not requiring result register |
| 3495 // to be identical to first input register as on Intel. | 3495 // to be identical to first input register as on Intel. |
| 3496 summary->set_out(Location::RequiresRegister()); | 3496 summary->set_out(0, Location::RequiresRegister()); |
| 3497 return summary; | 3497 return summary; |
| 3498 } | 3498 } |
| 3499 | 3499 |
| 3500 | 3500 |
| 3501 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3501 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3502 Register value = locs()->in(0).reg(); | 3502 Register value = locs()->in(0).reg(); |
| 3503 Register result = locs()->out().reg(); | 3503 Register result = locs()->out(0).reg(); |
| 3504 switch (op_kind()) { | 3504 switch (op_kind()) { |
| 3505 case Token::kNEGATE: { | 3505 case Token::kNEGATE: { |
| 3506 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3506 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 3507 kDeoptUnaryOp); | 3507 kDeoptUnaryOp); |
| 3508 __ SubuDetectOverflow(result, ZR, value, CMPRES1); | 3508 __ SubuDetectOverflow(result, ZR, value, CMPRES1); |
| 3509 __ bltz(CMPRES1, deopt); | 3509 __ bltz(CMPRES1, deopt); |
| 3510 break; | 3510 break; |
| 3511 } | 3511 } |
| 3512 case Token::kBIT_NOT: | 3512 case Token::kBIT_NOT: |
| 3513 __ nor(result, value, ZR); | 3513 __ nor(result, value, ZR); |
| 3514 __ addiu(result, result, Immediate(-1)); // Remove inverted smi-tag. | 3514 __ addiu(result, result, Immediate(-1)); // Remove inverted smi-tag. |
| 3515 break; | 3515 break; |
| 3516 default: | 3516 default: |
| 3517 UNREACHABLE(); | 3517 UNREACHABLE(); |
| 3518 } | 3518 } |
| 3519 } | 3519 } |
| 3520 | 3520 |
| 3521 | 3521 |
| 3522 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const { | 3522 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const { |
| 3523 const intptr_t kNumInputs = 1; | 3523 const intptr_t kNumInputs = 1; |
| 3524 const intptr_t kNumTemps = 1; | 3524 const intptr_t kNumTemps = 1; |
| 3525 LocationSummary* summary = | 3525 LocationSummary* summary = |
| 3526 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3526 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3527 summary->set_in(0, Location::RequiresFpuRegister()); | 3527 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3528 summary->set_out(Location::RequiresFpuRegister()); | 3528 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3529 summary->set_temp(0, Location::RequiresFpuRegister()); | 3529 summary->set_temp(0, Location::RequiresFpuRegister()); |
| 3530 return summary; | 3530 return summary; |
| 3531 } | 3531 } |
| 3532 | 3532 |
| 3533 | 3533 |
| 3534 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3534 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3535 // TODO(zra): Implement vneg. | 3535 // TODO(zra): Implement vneg. |
| 3536 const Double& minus_one = Double::ZoneHandle(Double::NewCanonical(-1)); | 3536 const Double& minus_one = Double::ZoneHandle(Double::NewCanonical(-1)); |
| 3537 __ LoadObject(TMP, minus_one); | 3537 __ LoadObject(TMP, minus_one); |
| 3538 FpuRegister result = locs()->out().fpu_reg(); | 3538 FpuRegister result = locs()->out(0).fpu_reg(); |
| 3539 FpuRegister value = locs()->in(0).fpu_reg(); | 3539 FpuRegister value = locs()->in(0).fpu_reg(); |
| 3540 FpuRegister temp_fp = locs()->temp(0).fpu_reg(); | 3540 FpuRegister temp_fp = locs()->temp(0).fpu_reg(); |
| 3541 __ LoadDFromOffset(temp_fp, TMP, Double::value_offset() - kHeapObjectTag); | 3541 __ LoadDFromOffset(temp_fp, TMP, Double::value_offset() - kHeapObjectTag); |
| 3542 __ muld(result, value, temp_fp); | 3542 __ muld(result, value, temp_fp); |
| 3543 } | 3543 } |
| 3544 | 3544 |
| 3545 | 3545 |
| 3546 | 3546 |
| 3547 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const { | 3547 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const { |
| 3548 const intptr_t kNumInputs = 1; | 3548 const intptr_t kNumInputs = 1; |
| 3549 const intptr_t kNumTemps = 0; | 3549 const intptr_t kNumTemps = 0; |
| 3550 LocationSummary* result = | 3550 LocationSummary* result = |
| 3551 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3551 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3552 result->set_in(0, Location::WritableRegister()); | 3552 result->set_in(0, Location::WritableRegister()); |
| 3553 result->set_out(Location::RequiresFpuRegister()); | 3553 result->set_out(0, Location::RequiresFpuRegister()); |
| 3554 return result; | 3554 return result; |
| 3555 } | 3555 } |
| 3556 | 3556 |
| 3557 | 3557 |
| 3558 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3558 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3559 Register value = locs()->in(0).reg(); | 3559 Register value = locs()->in(0).reg(); |
| 3560 FpuRegister result = locs()->out().fpu_reg(); | 3560 FpuRegister result = locs()->out(0).fpu_reg(); |
| 3561 __ SmiUntag(value); | 3561 __ SmiUntag(value); |
| 3562 __ mtc1(value, STMP1); | 3562 __ mtc1(value, STMP1); |
| 3563 __ cvtdw(result, STMP1); | 3563 __ cvtdw(result, STMP1); |
| 3564 } | 3564 } |
| 3565 | 3565 |
| 3566 | 3566 |
| 3567 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const { | 3567 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const { |
| 3568 const intptr_t kNumInputs = 1; | 3568 const intptr_t kNumInputs = 1; |
| 3569 const intptr_t kNumTemps = 0; | 3569 const intptr_t kNumTemps = 0; |
| 3570 LocationSummary* result = | 3570 LocationSummary* result = |
| 3571 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 3571 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 3572 result->set_in(0, Location::RegisterLocation(T1)); | 3572 result->set_in(0, Location::RegisterLocation(T1)); |
| 3573 result->set_out(Location::RegisterLocation(V0)); | 3573 result->set_out(0, Location::RegisterLocation(V0)); |
| 3574 return result; | 3574 return result; |
| 3575 } | 3575 } |
| 3576 | 3576 |
| 3577 | 3577 |
| 3578 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3578 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3579 Register result = locs()->out().reg(); | 3579 Register result = locs()->out(0).reg(); |
| 3580 Register value_obj = locs()->in(0).reg(); | 3580 Register value_obj = locs()->in(0).reg(); |
| 3581 ASSERT(result == V0); | 3581 ASSERT(result == V0); |
| 3582 ASSERT(result != value_obj); | 3582 ASSERT(result != value_obj); |
| 3583 __ LoadDFromOffset(DTMP, value_obj, Double::value_offset() - kHeapObjectTag); | 3583 __ LoadDFromOffset(DTMP, value_obj, Double::value_offset() - kHeapObjectTag); |
| 3584 __ cvtwd(STMP1, DTMP); | 3584 __ cvtwd(STMP1, DTMP); |
| 3585 __ mfc1(result, STMP1); | 3585 __ mfc1(result, STMP1); |
| 3586 | 3586 |
| 3587 // Overflow is signaled with minint. | 3587 // Overflow is signaled with minint. |
| 3588 Label do_call, done; | 3588 Label do_call, done; |
| 3589 // Check for overflow and that it fits into Smi. | 3589 // Check for overflow and that it fits into Smi. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3609 __ Bind(&done); | 3609 __ Bind(&done); |
| 3610 } | 3610 } |
| 3611 | 3611 |
| 3612 | 3612 |
| 3613 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const { | 3613 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const { |
| 3614 const intptr_t kNumInputs = 1; | 3614 const intptr_t kNumInputs = 1; |
| 3615 const intptr_t kNumTemps = 0; | 3615 const intptr_t kNumTemps = 0; |
| 3616 LocationSummary* result = new LocationSummary( | 3616 LocationSummary* result = new LocationSummary( |
| 3617 kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3617 kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3618 result->set_in(0, Location::RequiresFpuRegister()); | 3618 result->set_in(0, Location::RequiresFpuRegister()); |
| 3619 result->set_out(Location::RequiresRegister()); | 3619 result->set_out(0, Location::RequiresRegister()); |
| 3620 return result; | 3620 return result; |
| 3621 } | 3621 } |
| 3622 | 3622 |
| 3623 | 3623 |
| 3624 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3624 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3625 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); | 3625 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); |
| 3626 Register result = locs()->out().reg(); | 3626 Register result = locs()->out(0).reg(); |
| 3627 DRegister value = locs()->in(0).fpu_reg(); | 3627 DRegister value = locs()->in(0).fpu_reg(); |
| 3628 __ cvtwd(STMP1, value); | 3628 __ cvtwd(STMP1, value); |
| 3629 __ mfc1(result, STMP1); | 3629 __ mfc1(result, STMP1); |
| 3630 | 3630 |
| 3631 // Check for overflow and that it fits into Smi. | 3631 // Check for overflow and that it fits into Smi. |
| 3632 __ LoadImmediate(TMP, 0xC0000000); | 3632 __ LoadImmediate(TMP, 0xC0000000); |
| 3633 __ subu(CMPRES1, result, TMP); | 3633 __ subu(CMPRES1, result, TMP); |
| 3634 __ bltz(CMPRES1, deopt); | 3634 __ bltz(CMPRES1, deopt); |
| 3635 __ SmiTag(result); | 3635 __ SmiTag(result); |
| 3636 } | 3636 } |
| 3637 | 3637 |
| 3638 | 3638 |
| 3639 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const { | 3639 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const { |
| 3640 UNIMPLEMENTED(); | 3640 UNIMPLEMENTED(); |
| 3641 return NULL; | 3641 return NULL; |
| 3642 } | 3642 } |
| 3643 | 3643 |
| 3644 | 3644 |
| 3645 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3645 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3646 UNIMPLEMENTED(); | 3646 UNIMPLEMENTED(); |
| 3647 } | 3647 } |
| 3648 | 3648 |
| 3649 | 3649 |
| 3650 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(bool opt) const { | 3650 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(bool opt) const { |
| 3651 const intptr_t kNumInputs = 1; | 3651 const intptr_t kNumInputs = 1; |
| 3652 const intptr_t kNumTemps = 0; | 3652 const intptr_t kNumTemps = 0; |
| 3653 LocationSummary* result = | 3653 LocationSummary* result = |
| 3654 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3654 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3655 result->set_in(0, Location::RequiresFpuRegister()); | 3655 result->set_in(0, Location::RequiresFpuRegister()); |
| 3656 result->set_out(Location::SameAsFirstInput()); | 3656 result->set_out(0, Location::SameAsFirstInput()); |
| 3657 return result; | 3657 return result; |
| 3658 } | 3658 } |
| 3659 | 3659 |
| 3660 | 3660 |
| 3661 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3661 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3662 DRegister value = locs()->in(0).fpu_reg(); | 3662 DRegister value = locs()->in(0).fpu_reg(); |
| 3663 FRegister result = EvenFRegisterOf(locs()->out().fpu_reg()); | 3663 FRegister result = EvenFRegisterOf(locs()->out(0).fpu_reg()); |
| 3664 __ cvtsd(result, value); | 3664 __ cvtsd(result, value); |
| 3665 } | 3665 } |
| 3666 | 3666 |
| 3667 | 3667 |
| 3668 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(bool opt) const { | 3668 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(bool opt) const { |
| 3669 const intptr_t kNumInputs = 1; | 3669 const intptr_t kNumInputs = 1; |
| 3670 const intptr_t kNumTemps = 0; | 3670 const intptr_t kNumTemps = 0; |
| 3671 LocationSummary* result = | 3671 LocationSummary* result = |
| 3672 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3672 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3673 result->set_in(0, Location::RequiresFpuRegister()); | 3673 result->set_in(0, Location::RequiresFpuRegister()); |
| 3674 result->set_out(Location::SameAsFirstInput()); | 3674 result->set_out(0, Location::SameAsFirstInput()); |
| 3675 return result; | 3675 return result; |
| 3676 } | 3676 } |
| 3677 | 3677 |
| 3678 | 3678 |
| 3679 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3679 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3680 FRegister value = EvenFRegisterOf(locs()->in(0).fpu_reg()); | 3680 FRegister value = EvenFRegisterOf(locs()->in(0).fpu_reg()); |
| 3681 DRegister result = locs()->out().fpu_reg(); | 3681 DRegister result = locs()->out(0).fpu_reg(); |
| 3682 __ cvtds(result, value); | 3682 __ cvtds(result, value); |
| 3683 } | 3683 } |
| 3684 | 3684 |
| 3685 | 3685 |
| 3686 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { | 3686 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { |
| 3687 // Calling convention on MIPS uses D6 and D7 to pass the first two | 3687 // Calling convention on MIPS uses D6 and D7 to pass the first two |
| 3688 // double arguments. | 3688 // double arguments. |
| 3689 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 3689 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 3690 const intptr_t kNumTemps = 0; | 3690 const intptr_t kNumTemps = 0; |
| 3691 LocationSummary* result = | 3691 LocationSummary* result = |
| 3692 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); | 3692 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); |
| 3693 result->set_in(0, Location::FpuRegisterLocation(D6)); | 3693 result->set_in(0, Location::FpuRegisterLocation(D6)); |
| 3694 if (InputCount() == 2) { | 3694 if (InputCount() == 2) { |
| 3695 result->set_in(1, Location::FpuRegisterLocation(D7)); | 3695 result->set_in(1, Location::FpuRegisterLocation(D7)); |
| 3696 } | 3696 } |
| 3697 result->set_out(Location::FpuRegisterLocation(D0)); | 3697 result->set_out(0, Location::FpuRegisterLocation(D0)); |
| 3698 return result; | 3698 return result; |
| 3699 } | 3699 } |
| 3700 | 3700 |
| 3701 | 3701 |
| 3702 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3702 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3703 // For pow-function return NaN if exponent is NaN. | 3703 // For pow-function return NaN if exponent is NaN. |
| 3704 Label do_call, skip_call; | 3704 Label do_call, skip_call; |
| 3705 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 3705 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 3706 // Pseudo code: | 3706 // Pseudo code: |
| 3707 // if (exponent == 0.0) return 0.0; | 3707 // if (exponent == 0.0) return 0.0; |
| 3708 // if (base == 1.0) return 1.0; | 3708 // if (base == 1.0) return 1.0; |
| 3709 // if (base.isNaN || exponent.isNaN) { | 3709 // if (base.isNaN || exponent.isNaN) { |
| 3710 // return double.NAN; | 3710 // return double.NAN; |
| 3711 // } | 3711 // } |
| 3712 DRegister base = locs()->in(0).fpu_reg(); | 3712 DRegister base = locs()->in(0).fpu_reg(); |
| 3713 DRegister exp = locs()->in(1).fpu_reg(); | 3713 DRegister exp = locs()->in(1).fpu_reg(); |
| 3714 DRegister result = locs()->out().fpu_reg(); | 3714 DRegister result = locs()->out(0).fpu_reg(); |
| 3715 | 3715 |
| 3716 Label check_base_is_one; | 3716 Label check_base_is_one; |
| 3717 | 3717 |
| 3718 // Check if exponent is 0.0 -> return 1.0; | 3718 // Check if exponent is 0.0 -> return 1.0; |
| 3719 __ LoadObject(TMP, Double::ZoneHandle(Double::NewCanonical(0))); | 3719 __ LoadObject(TMP, Double::ZoneHandle(Double::NewCanonical(0))); |
| 3720 __ LoadDFromOffset(DTMP, TMP, Double::value_offset() - kHeapObjectTag); | 3720 __ LoadDFromOffset(DTMP, TMP, Double::value_offset() - kHeapObjectTag); |
| 3721 __ LoadObject(TMP, Double::ZoneHandle(Double::NewCanonical(1))); | 3721 __ LoadObject(TMP, Double::ZoneHandle(Double::NewCanonical(1))); |
| 3722 __ LoadDFromOffset(result, TMP, Double::value_offset() - kHeapObjectTag); | 3722 __ LoadDFromOffset(result, TMP, Double::value_offset() - kHeapObjectTag); |
| 3723 // 'result' contains 1.0. | 3723 // 'result' contains 1.0. |
| 3724 __ cund(exp, exp); | 3724 __ cund(exp, exp); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3749 if (kind() == MergedMathInstr::kTruncDivMod) { | 3749 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 3750 const intptr_t kNumInputs = 2; | 3750 const intptr_t kNumInputs = 2; |
| 3751 const intptr_t kNumTemps = 3; | 3751 const intptr_t kNumTemps = 3; |
| 3752 LocationSummary* summary = | 3752 LocationSummary* summary = |
| 3753 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3753 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3754 summary->set_in(0, Location::RequiresRegister()); | 3754 summary->set_in(0, Location::RequiresRegister()); |
| 3755 summary->set_in(1, Location::RequiresRegister()); | 3755 summary->set_in(1, Location::RequiresRegister()); |
| 3756 summary->set_temp(0, Location::RequiresRegister()); | 3756 summary->set_temp(0, Location::RequiresRegister()); |
| 3757 summary->set_temp(1, Location::RequiresRegister()); // result_div. | 3757 summary->set_temp(1, Location::RequiresRegister()); // result_div. |
| 3758 summary->set_temp(2, Location::RequiresRegister()); // result_mod. | 3758 summary->set_temp(2, Location::RequiresRegister()); // result_mod. |
| 3759 summary->set_out(Location::RequiresRegister()); | 3759 summary->set_out(0, Location::RequiresRegister()); |
| 3760 return summary; | 3760 return summary; |
| 3761 } | 3761 } |
| 3762 UNIMPLEMENTED(); | 3762 UNIMPLEMENTED(); |
| 3763 return NULL; | 3763 return NULL; |
| 3764 } | 3764 } |
| 3765 | 3765 |
| 3766 | 3766 |
| 3767 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3767 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3768 Label* deopt = NULL; | 3768 Label* deopt = NULL; |
| 3769 if (CanDeoptimize()) { | 3769 if (CanDeoptimize()) { |
| 3770 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 3770 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| 3771 } | 3771 } |
| 3772 if (kind() == MergedMathInstr::kTruncDivMod) { | 3772 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 3773 Register left = locs()->in(0).reg(); | 3773 Register left = locs()->in(0).reg(); |
| 3774 Register right = locs()->in(1).reg(); | 3774 Register right = locs()->in(1).reg(); |
| 3775 Register result = locs()->out().reg(); | 3775 Register result = locs()->out(0).reg(); |
| 3776 Register temp = locs()->temp(0).reg(); | 3776 Register temp = locs()->temp(0).reg(); |
| 3777 Register result_div = locs()->temp(1).reg(); | 3777 Register result_div = locs()->temp(1).reg(); |
| 3778 Register result_mod = locs()->temp(2).reg(); | 3778 Register result_mod = locs()->temp(2).reg(); |
| 3779 Range* right_range = InputAt(1)->definition()->range(); | 3779 Range* right_range = InputAt(1)->definition()->range(); |
| 3780 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3780 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 3781 // Handle divide by zero in runtime. | 3781 // Handle divide by zero in runtime. |
| 3782 __ beq(right, ZR, deopt); | 3782 __ beq(right, ZR, deopt); |
| 3783 } | 3783 } |
| 3784 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. | 3784 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. |
| 3785 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 3785 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3873 deopt, | 3873 deopt, |
| 3874 deopt_id(), | 3874 deopt_id(), |
| 3875 instance_call()->token_pos(), | 3875 instance_call()->token_pos(), |
| 3876 locs()); | 3876 locs()); |
| 3877 } | 3877 } |
| 3878 | 3878 |
| 3879 | 3879 |
| 3880 LocationSummary* BranchInstr::MakeLocationSummary(bool opt) const { | 3880 LocationSummary* BranchInstr::MakeLocationSummary(bool opt) const { |
| 3881 comparison()->InitializeLocationSummary(opt); | 3881 comparison()->InitializeLocationSummary(opt); |
| 3882 // Branches don't produce a result. | 3882 // Branches don't produce a result. |
| 3883 comparison()->locs()->set_out(Location::NoLocation()); | 3883 comparison()->locs()->set_out(0, Location::NoLocation()); |
| 3884 return comparison()->locs(); | 3884 return comparison()->locs(); |
| 3885 } | 3885 } |
| 3886 | 3886 |
| 3887 | 3887 |
| 3888 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3888 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3889 __ TraceSimMsg("BranchInstr"); | 3889 __ TraceSimMsg("BranchInstr"); |
| 3890 comparison()->EmitBranchCode(compiler, this); | 3890 comparison()->EmitBranchCode(compiler, this); |
| 3891 } | 3891 } |
| 3892 | 3892 |
| 3893 | 3893 |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4159 | 4159 |
| 4160 | 4160 |
| 4161 LocationSummary* CurrentContextInstr::MakeLocationSummary(bool opt) const { | 4161 LocationSummary* CurrentContextInstr::MakeLocationSummary(bool opt) const { |
| 4162 return LocationSummary::Make(0, | 4162 return LocationSummary::Make(0, |
| 4163 Location::RequiresRegister(), | 4163 Location::RequiresRegister(), |
| 4164 LocationSummary::kNoCall); | 4164 LocationSummary::kNoCall); |
| 4165 } | 4165 } |
| 4166 | 4166 |
| 4167 | 4167 |
| 4168 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4168 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4169 __ mov(locs()->out().reg(), CTX); | 4169 __ mov(locs()->out(0).reg(), CTX); |
| 4170 } | 4170 } |
| 4171 | 4171 |
| 4172 | 4172 |
| 4173 LocationSummary* StrictCompareInstr::MakeLocationSummary(bool opt) const { | 4173 LocationSummary* StrictCompareInstr::MakeLocationSummary(bool opt) const { |
| 4174 const intptr_t kNumInputs = 2; | 4174 const intptr_t kNumInputs = 2; |
| 4175 const intptr_t kNumTemps = 0; | 4175 const intptr_t kNumTemps = 0; |
| 4176 if (needs_number_check()) { | 4176 if (needs_number_check()) { |
| 4177 LocationSummary* locs = | 4177 LocationSummary* locs = |
| 4178 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4178 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4179 locs->set_in(0, Location::RegisterLocation(A0)); | 4179 locs->set_in(0, Location::RegisterLocation(A0)); |
| 4180 locs->set_in(1, Location::RegisterLocation(A1)); | 4180 locs->set_in(1, Location::RegisterLocation(A1)); |
| 4181 locs->set_out(Location::RegisterLocation(A0)); | 4181 locs->set_out(0, Location::RegisterLocation(A0)); |
| 4182 return locs; | 4182 return locs; |
| 4183 } | 4183 } |
| 4184 LocationSummary* locs = | 4184 LocationSummary* locs = |
| 4185 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4185 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4186 locs->set_in(0, Location::RegisterOrConstant(left())); | 4186 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 4187 // Only one of the inputs can be a constant. Choose register if the first one | 4187 // Only one of the inputs can be a constant. Choose register if the first one |
| 4188 // is a constant. | 4188 // is a constant. |
| 4189 locs->set_in(1, locs->in(0).IsConstant() | 4189 locs->set_in(1, locs->in(0).IsConstant() |
| 4190 ? Location::RequiresRegister() | 4190 ? Location::RequiresRegister() |
| 4191 : Location::RegisterOrConstant(right())); | 4191 : Location::RegisterOrConstant(right())); |
| 4192 locs->set_out(Location::RequiresRegister()); | 4192 locs->set_out(0, Location::RequiresRegister()); |
| 4193 return locs; | 4193 return locs; |
| 4194 } | 4194 } |
| 4195 | 4195 |
| 4196 | 4196 |
| 4197 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 4197 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 4198 BranchLabels labels) { | 4198 BranchLabels labels) { |
| 4199 Location left = locs()->in(0); | 4199 Location left = locs()->in(0); |
| 4200 Location right = locs()->in(1); | 4200 Location right = locs()->in(1); |
| 4201 ASSERT(!left.IsConstant() || !right.IsConstant()); | 4201 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 4202 if (left.IsConstant()) { | 4202 if (left.IsConstant()) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4223 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4223 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4224 __ TraceSimMsg("StrictCompareInstr"); | 4224 __ TraceSimMsg("StrictCompareInstr"); |
| 4225 __ Comment("StrictCompareInstr"); | 4225 __ Comment("StrictCompareInstr"); |
| 4226 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4226 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4227 | 4227 |
| 4228 Label is_true, is_false; | 4228 Label is_true, is_false; |
| 4229 BranchLabels labels = { &is_true, &is_false, &is_false }; | 4229 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 4230 Condition true_condition = EmitComparisonCode(compiler, labels); | 4230 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 4231 EmitBranchOnCondition(compiler, true_condition, labels); | 4231 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4232 | 4232 |
| 4233 Register result = locs()->out().reg(); | 4233 Register result = locs()->out(0).reg(); |
| 4234 Label done; | 4234 Label done; |
| 4235 __ Bind(&is_false); | 4235 __ Bind(&is_false); |
| 4236 __ LoadObject(result, Bool::False()); | 4236 __ LoadObject(result, Bool::False()); |
| 4237 __ b(&done); | 4237 __ b(&done); |
| 4238 __ Bind(&is_true); | 4238 __ Bind(&is_true); |
| 4239 __ LoadObject(result, Bool::True()); | 4239 __ LoadObject(result, Bool::True()); |
| 4240 __ Bind(&done); | 4240 __ Bind(&done); |
| 4241 } | 4241 } |
| 4242 | 4242 |
| 4243 | 4243 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4254 | 4254 |
| 4255 LocationSummary* BooleanNegateInstr::MakeLocationSummary(bool opt) const { | 4255 LocationSummary* BooleanNegateInstr::MakeLocationSummary(bool opt) const { |
| 4256 return LocationSummary::Make(1, | 4256 return LocationSummary::Make(1, |
| 4257 Location::RequiresRegister(), | 4257 Location::RequiresRegister(), |
| 4258 LocationSummary::kNoCall); | 4258 LocationSummary::kNoCall); |
| 4259 } | 4259 } |
| 4260 | 4260 |
| 4261 | 4261 |
| 4262 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4262 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4263 Register value = locs()->in(0).reg(); | 4263 Register value = locs()->in(0).reg(); |
| 4264 Register result = locs()->out().reg(); | 4264 Register result = locs()->out(0).reg(); |
| 4265 | 4265 |
| 4266 __ LoadObject(result, Bool::True()); | 4266 __ LoadObject(result, Bool::True()); |
| 4267 __ LoadObject(TMP, Bool::False()); | 4267 __ LoadObject(TMP, Bool::False()); |
| 4268 __ subu(CMPRES1, value, result); | 4268 __ subu(CMPRES1, value, result); |
| 4269 __ movz(result, TMP, CMPRES1); // If value is True, move False into result. | 4269 __ movz(result, TMP, CMPRES1); // If value is True, move False into result. |
| 4270 } | 4270 } |
| 4271 | 4271 |
| 4272 | 4272 |
| 4273 LocationSummary* AllocateObjectInstr::MakeLocationSummary(bool opt) const { | 4273 LocationSummary* AllocateObjectInstr::MakeLocationSummary(bool opt) const { |
| 4274 return MakeCallSummary(); | 4274 return MakeCallSummary(); |
| 4275 } | 4275 } |
| 4276 | 4276 |
| 4277 | 4277 |
| 4278 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4278 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4279 __ TraceSimMsg("AllocateObjectInstr"); | 4279 __ TraceSimMsg("AllocateObjectInstr"); |
| 4280 __ Comment("AllocateObjectInstr"); | 4280 __ Comment("AllocateObjectInstr"); |
| 4281 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls())); | 4281 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls())); |
| 4282 const ExternalLabel label(cls().ToCString(), stub.EntryPoint()); | 4282 const ExternalLabel label(cls().ToCString(), stub.EntryPoint()); |
| 4283 compiler->GenerateCall(token_pos(), | 4283 compiler->GenerateCall(token_pos(), |
| 4284 &label, | 4284 &label, |
| 4285 PcDescriptors::kOther, | 4285 PcDescriptors::kOther, |
| 4286 locs()); | 4286 locs()); |
| 4287 __ Drop(ArgumentCount()); // Discard arguments. | 4287 __ Drop(ArgumentCount()); // Discard arguments. |
| 4288 } | 4288 } |
| 4289 | 4289 |
| 4290 } // namespace dart | 4290 } // namespace dart |
| 4291 | 4291 |
| 4292 #endif // defined TARGET_ARCH_MIPS | 4292 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |