| 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 case BELOW_EQUAL: return ABOVE_EQUAL; | 402 case BELOW_EQUAL: return ABOVE_EQUAL; |
| 403 case ABOVE: return BELOW; | 403 case ABOVE: return BELOW; |
| 404 case ABOVE_EQUAL: return BELOW_EQUAL; | 404 case ABOVE_EQUAL: return BELOW_EQUAL; |
| 405 default: | 405 default: |
| 406 UNIMPLEMENTED(); | 406 UNIMPLEMENTED(); |
| 407 return EQUAL; | 407 return EQUAL; |
| 408 } | 408 } |
| 409 } | 409 } |
| 410 | 410 |
| 411 | 411 |
| 412 static void EmitBranchOnValue(FlowGraphCompiler* compiler, | |
| 413 TargetEntryInstr* true_successor, | |
| 414 TargetEntryInstr* false_successor, | |
| 415 bool value) { | |
| 416 if (value && !compiler->CanFallThroughTo(true_successor)) { | |
| 417 __ jmp(compiler->GetJumpLabel(true_successor)); | |
| 418 } else if (!value && !compiler->CanFallThroughTo(false_successor)) { | |
| 419 __ jmp(compiler->GetJumpLabel(false_successor)); | |
| 420 } | |
| 421 } | |
| 422 | |
| 423 | |
| 424 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 412 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 425 TargetEntryInstr* true_successor, | 413 TargetEntryInstr* true_successor, |
| 426 TargetEntryInstr* false_successor, | 414 TargetEntryInstr* false_successor, |
| 427 Condition true_condition) { | 415 Condition true_condition) { |
| 428 if (compiler->CanFallThroughTo(false_successor)) { | 416 if (compiler->CanFallThroughTo(false_successor)) { |
| 429 // If the next block is the false successor, fall through to it. | 417 // If the next block is the false successor, fall through to it. |
| 430 __ j(true_condition, compiler->GetJumpLabel(true_successor)); | 418 __ j(true_condition, compiler->GetJumpLabel(true_successor)); |
| 431 } else { | 419 } else { |
| 432 // If the next block is not the false successor, branch to it. | 420 // If the next block is not the false successor, branch to it. |
| 433 Condition false_condition = NegateCondition(true_condition); | 421 Condition false_condition = NegateCondition(true_condition); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 EmitDoubleCompareBool(compiler, true_condition, | 534 EmitDoubleCompareBool(compiler, true_condition, |
| 547 left, right, locs.out().reg()); | 535 left, right, locs.out().reg()); |
| 548 } | 536 } |
| 549 } | 537 } |
| 550 | 538 |
| 551 | 539 |
| 552 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 540 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 553 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 541 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 554 BranchInstr* kNoBranch = NULL; | 542 BranchInstr* kNoBranch = NULL; |
| 555 if (operation_cid() == kSmiCid) { | 543 if (operation_cid() == kSmiCid) { |
| 556 // Deoptimizes if both arguments not Smi. | |
| 557 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); | 544 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 558 return; | 545 return; |
| 559 } | 546 } |
| 560 if (operation_cid() == kDoubleCid) { | 547 if (operation_cid() == kDoubleCid) { |
| 561 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | |
| 562 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); | 548 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 563 return; | 549 return; |
| 564 } | 550 } |
| 565 UNREACHABLE(); | 551 UNREACHABLE(); |
| 566 } | 552 } |
| 567 | 553 |
| 568 | 554 |
| 569 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 555 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 570 BranchInstr* branch) { | 556 BranchInstr* branch) { |
| 571 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 557 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 572 if (operation_cid() == kSmiCid) { | 558 if (operation_cid() == kSmiCid) { |
| 573 // Deoptimizes if both arguments not Smi. | |
| 574 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 559 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 575 return; | 560 return; |
| 576 } | 561 } |
| 577 if (operation_cid() == kDoubleCid) { | 562 if (operation_cid() == kDoubleCid) { |
| 578 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | |
| 579 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 563 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 580 return; | 564 return; |
| 581 } | 565 } |
| 582 UNREACHABLE(); | 566 UNREACHABLE(); |
| 583 } | 567 } |
| 584 | 568 |
| 585 | 569 |
| 586 LocationSummary* TestSmiInstr::MakeLocationSummary() const { | 570 LocationSummary* TestSmiInstr::MakeLocationSummary() const { |
| 587 const intptr_t kNumInputs = 2; | 571 const intptr_t kNumInputs = 2; |
| 588 const intptr_t kNumTemps = 0; | 572 const intptr_t kNumTemps = 0; |
| (...skipping 3785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4374 LocationSummary* locs = | 4358 LocationSummary* locs = |
| 4375 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4359 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4376 locs->set_in(0, Location::RegisterLocation(RAX)); | 4360 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 4377 locs->set_in(1, Location::RegisterLocation(RCX)); | 4361 locs->set_in(1, Location::RegisterLocation(RCX)); |
| 4378 locs->set_out(Location::RegisterLocation(RAX)); | 4362 locs->set_out(Location::RegisterLocation(RAX)); |
| 4379 return locs; | 4363 return locs; |
| 4380 } | 4364 } |
| 4381 LocationSummary* locs = | 4365 LocationSummary* locs = |
| 4382 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4366 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4383 locs->set_in(0, Location::RegisterOrConstant(left())); | 4367 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 4384 locs->set_in(1, Location::RegisterOrConstant(right())); | 4368 // Only one of the inputs can be a constant. Choose register if the first one |
| 4369 // is a constant. |
| 4370 locs->set_in(1, locs->in(0).IsConstant() |
| 4371 ? Location::RequiresRegister() |
| 4372 : Location::RegisterOrConstant(right())); |
| 4385 locs->set_out(Location::RequiresRegister()); | 4373 locs->set_out(Location::RequiresRegister()); |
| 4386 return locs; | 4374 return locs; |
| 4387 } | 4375 } |
| 4388 | 4376 |
| 4389 | 4377 |
| 4390 // Special code for numbers (compare values instead of references.) | 4378 // Special code for numbers (compare values instead of references.) |
| 4391 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4379 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4392 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4380 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4393 Location left = locs()->in(0); | 4381 Location left = locs()->in(0); |
| 4394 Location right = locs()->in(1); | 4382 Location right = locs()->in(1); |
| 4395 if (left.IsConstant() && right.IsConstant()) { | 4383 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 4396 // TODO(vegorov): should be eliminated earlier by constant propagation. | |
| 4397 const bool result = (kind() == Token::kEQ_STRICT) ? | |
| 4398 left.constant().raw() == right.constant().raw() : | |
| 4399 left.constant().raw() != right.constant().raw(); | |
| 4400 __ LoadObject(locs()->out().reg(), Bool::Get(result), PP); | |
| 4401 return; | |
| 4402 } | |
| 4403 if (left.IsConstant()) { | 4384 if (left.IsConstant()) { |
| 4404 compiler->EmitEqualityRegConstCompare(right.reg(), | 4385 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 4405 left.constant(), | 4386 left.constant(), |
| 4406 needs_number_check(), | 4387 needs_number_check(), |
| 4407 token_pos()); | 4388 token_pos()); |
| 4408 } else if (right.IsConstant()) { | 4389 } else if (right.IsConstant()) { |
| 4409 compiler->EmitEqualityRegConstCompare(left.reg(), | 4390 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 4410 right.constant(), | 4391 right.constant(), |
| 4411 needs_number_check(), | 4392 needs_number_check(), |
| 4412 token_pos()); | 4393 token_pos()); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4427 __ LoadObject(result, Bool::True(), PP); | 4408 __ LoadObject(result, Bool::True(), PP); |
| 4428 __ Bind(&done); | 4409 __ Bind(&done); |
| 4429 } | 4410 } |
| 4430 | 4411 |
| 4431 | 4412 |
| 4432 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 4413 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 4433 BranchInstr* branch) { | 4414 BranchInstr* branch) { |
| 4434 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4415 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4435 Location left = locs()->in(0); | 4416 Location left = locs()->in(0); |
| 4436 Location right = locs()->in(1); | 4417 Location right = locs()->in(1); |
| 4437 if (left.IsConstant() && right.IsConstant()) { | 4418 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 4438 // TODO(vegorov): should be eliminated earlier by constant propagation. | |
| 4439 const bool result = (kind() == Token::kEQ_STRICT) ? | |
| 4440 left.constant().raw() == right.constant().raw() : | |
| 4441 left.constant().raw() != right.constant().raw(); | |
| 4442 EmitBranchOnValue(compiler, | |
| 4443 branch->true_successor(), | |
| 4444 branch->false_successor(), | |
| 4445 result); | |
| 4446 return; | |
| 4447 } | |
| 4448 if (left.IsConstant()) { | 4419 if (left.IsConstant()) { |
| 4449 compiler->EmitEqualityRegConstCompare(right.reg(), | 4420 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 4450 left.constant(), | 4421 left.constant(), |
| 4451 needs_number_check(), | 4422 needs_number_check(), |
| 4452 token_pos()); | 4423 token_pos()); |
| 4453 } else if (right.IsConstant()) { | 4424 } else if (right.IsConstant()) { |
| 4454 compiler->EmitEqualityRegConstCompare(left.reg(), | 4425 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 4455 right.constant(), | 4426 right.constant(), |
| 4456 needs_number_check(), | 4427 needs_number_check(), |
| 4457 token_pos()); | 4428 token_pos()); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4578 PcDescriptors::kOther, | 4549 PcDescriptors::kOther, |
| 4579 locs()); | 4550 locs()); |
| 4580 __ Drop(2); // Discard type arguments and receiver. | 4551 __ Drop(2); // Discard type arguments and receiver. |
| 4581 } | 4552 } |
| 4582 | 4553 |
| 4583 } // namespace dart | 4554 } // namespace dart |
| 4584 | 4555 |
| 4585 #undef __ | 4556 #undef __ |
| 4586 | 4557 |
| 4587 #endif // defined TARGET_ARCH_X64 | 4558 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |