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 |