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 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 EmitBranchOnCondition(FlowGraphCompiler* compiler, | 412 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
413 TargetEntryInstr* true_successor, | 413 Condition true_condition, |
414 TargetEntryInstr* false_successor, | 414 BranchLabels labels) { |
415 Condition true_condition) { | 415 if (labels.fall_through == labels.false_label) { |
416 if (compiler->CanFallThroughTo(false_successor)) { | |
417 // If the next block is the false successor, fall through to it. | 416 // If the next block is the false successor, fall through to it. |
418 __ j(true_condition, compiler->GetJumpLabel(true_successor)); | 417 __ j(true_condition, labels.true_label); |
419 } else { | 418 } else { |
420 // If the next block is not the false successor, branch to it. | 419 // If the next block is not the false successor, branch to it. |
421 Condition false_condition = NegateCondition(true_condition); | 420 Condition false_condition = NegateCondition(true_condition); |
422 __ j(false_condition, compiler->GetJumpLabel(false_successor)); | 421 __ j(false_condition, labels.false_label); |
423 | 422 |
424 // Fall through or jump to the true successor. | 423 // Fall through or jump to the true successor. |
425 if (!compiler->CanFallThroughTo(true_successor)) { | 424 if (labels.fall_through != labels.true_label) { |
426 __ jmp(compiler->GetJumpLabel(true_successor)); | 425 __ jmp(labels.true_label); |
427 } | 426 } |
428 } | 427 } |
429 } | 428 } |
430 | 429 |
431 | 430 |
432 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 431 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
433 const LocationSummary& locs, | 432 const LocationSummary& locs, |
434 Token::Kind kind, | 433 Token::Kind kind, |
435 BranchInstr* branch) { | 434 BranchLabels labels) { |
436 Location left = locs.in(0); | 435 Location left = locs.in(0); |
437 Location right = locs.in(1); | 436 Location right = locs.in(1); |
438 ASSERT(!left.IsConstant() || !right.IsConstant()); | 437 ASSERT(!left.IsConstant() || !right.IsConstant()); |
439 | 438 |
440 Condition true_condition = TokenKindToSmiCondition(kind); | 439 Condition true_condition = TokenKindToSmiCondition(kind); |
441 | 440 |
442 if (left.IsConstant()) { | 441 if (left.IsConstant()) { |
443 __ CompareObject(right.reg(), left.constant(), PP); | 442 __ CompareObject(right.reg(), left.constant(), PP); |
444 true_condition = FlipCondition(true_condition); | 443 true_condition = FlipCondition(true_condition); |
445 } else if (right.IsConstant()) { | 444 } else if (right.IsConstant()) { |
446 __ CompareObject(left.reg(), right.constant(), PP); | 445 __ CompareObject(left.reg(), right.constant(), PP); |
447 } else if (right.IsStackSlot()) { | 446 } else if (right.IsStackSlot()) { |
448 __ cmpq(left.reg(), right.ToStackSlotAddress()); | 447 __ cmpq(left.reg(), right.ToStackSlotAddress()); |
449 } else { | 448 } else { |
450 __ cmpq(left.reg(), right.reg()); | 449 __ cmpq(left.reg(), right.reg()); |
451 } | 450 } |
452 | 451 EmitBranchOnCondition(compiler, true_condition, labels); |
453 if (branch != NULL) { | |
454 EmitBranchOnCondition(compiler, | |
455 branch->true_successor(), | |
456 branch->false_successor(), | |
457 true_condition); | |
458 } else { | |
459 Register result = locs.out().reg(); | |
460 Label done, is_true; | |
461 __ j(true_condition, &is_true); | |
462 __ LoadObject(result, Bool::False(), PP); | |
463 __ jmp(&done); | |
464 __ Bind(&is_true); | |
465 __ LoadObject(result, Bool::True(), PP); | |
466 __ Bind(&done); | |
467 } | |
468 } | 452 } |
469 | 453 |
470 | 454 |
471 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 455 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
472 switch (kind) { | 456 switch (kind) { |
473 case Token::kEQ: return EQUAL; | 457 case Token::kEQ: return EQUAL; |
474 case Token::kNE: return NOT_EQUAL; | 458 case Token::kNE: return NOT_EQUAL; |
475 case Token::kLT: return BELOW; | 459 case Token::kLT: return BELOW; |
476 case Token::kGT: return ABOVE; | 460 case Token::kGT: return ABOVE; |
477 case Token::kLTE: return BELOW_EQUAL; | 461 case Token::kLTE: return BELOW_EQUAL; |
478 case Token::kGTE: return ABOVE_EQUAL; | 462 case Token::kGTE: return ABOVE_EQUAL; |
479 default: | 463 default: |
480 UNREACHABLE(); | 464 UNREACHABLE(); |
481 return OVERFLOW; | 465 return OVERFLOW; |
482 } | 466 } |
483 } | 467 } |
484 | 468 |
485 | 469 |
486 static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler, | 470 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
487 Condition true_condition, | 471 const LocationSummary& locs, |
488 FpuRegister left, | 472 Token::Kind kind, |
489 FpuRegister right, | 473 BranchLabels labels) { |
490 BranchInstr* branch) { | 474 XmmRegister left = locs.in(0).fpu_reg(); |
491 ASSERT(branch != NULL); | 475 XmmRegister right = locs.in(1).fpu_reg(); |
| 476 |
492 __ comisd(left, right); | 477 __ comisd(left, right); |
493 BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ? | 478 |
494 branch->true_successor() : branch->false_successor(); | 479 Condition true_condition = TokenKindToDoubleCondition(kind); |
495 __ j(PARITY_EVEN, compiler->GetJumpLabel(nan_result)); | 480 Label* nan_result = (true_condition == NOT_EQUAL) |
496 EmitBranchOnCondition(compiler, | 481 ? labels.true_label : labels.false_label; |
497 branch->true_successor(), | 482 __ j(PARITY_EVEN, nan_result); |
498 branch->false_successor(), | 483 EmitBranchOnCondition(compiler, true_condition, labels); |
499 true_condition); | |
500 } | 484 } |
501 | 485 |
502 | 486 |
503 static void EmitDoubleCompareBool(FlowGraphCompiler* compiler, | 487 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
504 Condition true_condition, | 488 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
505 FpuRegister left, | 489 |
506 FpuRegister right, | 490 Label is_true, is_false; |
507 Register result) { | 491 BranchLabels labels = { &is_true, &is_false, &is_false }; |
508 __ comisd(left, right); | 492 |
509 Label is_false, is_true, done; | 493 if (operation_cid() == kSmiCid) { |
510 // x == NaN -> false, x != NaN -> true. | 494 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
511 Label* nan_label = (true_condition == NOT_EQUAL) ? &is_true : &is_false; | 495 } else { |
512 __ j(PARITY_EVEN, nan_label, Assembler::kNearJump); | 496 ASSERT(operation_cid() == kDoubleCid); |
513 __ j(true_condition, &is_true, Assembler::kNearJump); | 497 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 498 } |
| 499 Register result = locs()->out().reg(); |
| 500 Label done; |
514 __ Bind(&is_false); | 501 __ Bind(&is_false); |
515 __ LoadObject(result, Bool::False(), PP); | 502 __ LoadObject(result, Bool::False(), PP); |
516 __ jmp(&done); | 503 __ jmp(&done); |
517 __ Bind(&is_true); | 504 __ Bind(&is_true); |
518 __ LoadObject(result, Bool::True(), PP); | 505 __ LoadObject(result, Bool::True(), PP); |
519 __ Bind(&done); | 506 __ Bind(&done); |
520 } | 507 } |
521 | 508 |
522 | 509 |
523 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 510 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
524 const LocationSummary& locs, | 511 BranchInstr* branch) { |
525 Token::Kind kind, | 512 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
526 BranchInstr* branch) { | |
527 XmmRegister left = locs.in(0).fpu_reg(); | |
528 XmmRegister right = locs.in(1).fpu_reg(); | |
529 | 513 |
530 Condition true_condition = TokenKindToDoubleCondition(kind); | 514 BranchLabels labels = compiler->CreateBranchLabels(branch); |
531 if (branch != NULL) { | 515 |
532 EmitDoubleCompareBranch(compiler, true_condition, left, right, branch); | 516 if (operation_cid() == kSmiCid) { |
533 } else { | 517 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
534 EmitDoubleCompareBool(compiler, true_condition, | 518 } else { |
535 left, right, locs.out().reg()); | 519 ASSERT(operation_cid() == kDoubleCid); |
| 520 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
536 } | 521 } |
537 } | 522 } |
538 | 523 |
539 | 524 |
540 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
541 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | |
542 BranchInstr* kNoBranch = NULL; | |
543 if (operation_cid() == kSmiCid) { | |
544 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); | |
545 return; | |
546 } | |
547 if (operation_cid() == kDoubleCid) { | |
548 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); | |
549 return; | |
550 } | |
551 UNREACHABLE(); | |
552 } | |
553 | |
554 | |
555 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | |
556 BranchInstr* branch) { | |
557 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | |
558 if (operation_cid() == kSmiCid) { | |
559 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | |
560 return; | |
561 } | |
562 if (operation_cid() == kDoubleCid) { | |
563 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | |
564 return; | |
565 } | |
566 UNREACHABLE(); | |
567 } | |
568 | |
569 | |
570 LocationSummary* TestSmiInstr::MakeLocationSummary() const { | 525 LocationSummary* TestSmiInstr::MakeLocationSummary() const { |
571 const intptr_t kNumInputs = 2; | 526 const intptr_t kNumInputs = 2; |
572 const intptr_t kNumTemps = 0; | 527 const intptr_t kNumTemps = 0; |
573 LocationSummary* locs = | 528 LocationSummary* locs = |
574 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 529 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
575 locs->set_in(0, Location::RequiresRegister()); | 530 locs->set_in(0, Location::RequiresRegister()); |
576 // Only one input can be a constant operand. The case of two constant | 531 // Only one input can be a constant operand. The case of two constant |
577 // operands should be handled by constant propagation. | 532 // operands should be handled by constant propagation. |
578 locs->set_in(1, Location::RegisterOrConstant(right())); | 533 locs->set_in(1, Location::RegisterOrConstant(right())); |
579 return locs; | 534 return locs; |
580 } | 535 } |
581 | 536 |
582 | 537 |
583 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 538 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
584 // Never emitted outside of the BranchInstr. | 539 // Never emitted outside of the BranchInstr. |
585 UNREACHABLE(); | 540 UNREACHABLE(); |
586 } | 541 } |
587 | 542 |
588 | 543 |
589 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 544 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
590 BranchInstr* branch) { | 545 BranchInstr* branch) { |
| 546 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 547 |
591 Condition branch_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | 548 Condition branch_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
592 Register left_reg = locs()->in(0).reg(); | 549 Register left_reg = locs()->in(0).reg(); |
593 Location right = locs()->in(1); | 550 Location right = locs()->in(1); |
594 if (right.IsConstant()) { | 551 if (right.IsConstant()) { |
595 ASSERT(right.constant().IsSmi()); | 552 ASSERT(right.constant().IsSmi()); |
596 const int64_t imm = | 553 const int64_t imm = |
597 reinterpret_cast<int64_t>(right.constant().raw()); | 554 reinterpret_cast<int64_t>(right.constant().raw()); |
598 __ TestImmediate(left_reg, Immediate(imm), PP); | 555 __ TestImmediate(left_reg, Immediate(imm), PP); |
599 } else { | 556 } else { |
600 __ testq(left_reg, right.reg()); | 557 __ testq(left_reg, right.reg()); |
601 } | 558 } |
602 EmitBranchOnCondition(compiler, | 559 EmitBranchOnCondition(compiler, branch_condition, labels); |
603 branch->true_successor(), | |
604 branch->false_successor(), | |
605 branch_condition); | |
606 } | 560 } |
607 | 561 |
608 | 562 |
609 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 563 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
610 const intptr_t kNumInputs = 2; | 564 const intptr_t kNumInputs = 2; |
611 const intptr_t kNumTemps = 0; | 565 const intptr_t kNumTemps = 0; |
612 if (operation_cid() == kDoubleCid) { | 566 if (operation_cid() == kDoubleCid) { |
613 LocationSummary* summary = | 567 LocationSummary* summary = |
614 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 568 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
615 summary->set_in(0, Location::RequiresFpuRegister()); | 569 summary->set_in(0, Location::RequiresFpuRegister()); |
616 summary->set_in(1, Location::RequiresFpuRegister()); | 570 summary->set_in(1, Location::RequiresFpuRegister()); |
617 summary->set_out(Location::RequiresRegister()); | 571 summary->set_out(Location::RequiresRegister()); |
618 return summary; | 572 return summary; |
619 } | 573 } |
620 ASSERT(operation_cid() == kSmiCid); | 574 ASSERT(operation_cid() == kSmiCid); |
621 LocationSummary* summary = | 575 LocationSummary* summary = |
622 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 576 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
623 summary->set_in(0, Location::RegisterOrConstant(left())); | 577 summary->set_in(0, Location::RegisterOrConstant(left())); |
624 // Only one input can be a constant operand. The case of two constant | 578 // Only one input can be a constant operand. The case of two constant |
625 // operands should be handled by constant propagation. | 579 // operands should be handled by constant propagation. |
626 summary->set_in(1, summary->in(0).IsConstant() | 580 summary->set_in(1, summary->in(0).IsConstant() |
627 ? Location::RequiresRegister() | 581 ? Location::RequiresRegister() |
628 : Location::RegisterOrConstant(right())); | 582 : Location::RegisterOrConstant(right())); |
629 summary->set_out(Location::RequiresRegister()); | 583 summary->set_out(Location::RequiresRegister()); |
630 return summary; | 584 return summary; |
631 } | 585 } |
632 | 586 |
633 | 587 |
634 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 588 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 589 Label is_true, is_false; |
| 590 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 591 |
635 if (operation_cid() == kSmiCid) { | 592 if (operation_cid() == kSmiCid) { |
636 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); | 593 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
637 return; | 594 } else { |
| 595 ASSERT(operation_cid() == kDoubleCid); |
| 596 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
638 } | 597 } |
639 ASSERT(operation_cid() == kDoubleCid); | 598 Register result = locs()->out().reg(); |
640 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); | 599 Label done; |
| 600 __ Bind(&is_false); |
| 601 __ LoadObject(result, Bool::False(), PP); |
| 602 __ jmp(&done); |
| 603 __ Bind(&is_true); |
| 604 __ LoadObject(result, Bool::True(), PP); |
| 605 __ Bind(&done); |
641 } | 606 } |
642 | 607 |
643 | 608 |
644 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 609 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
645 BranchInstr* branch) { | 610 BranchInstr* branch) { |
| 611 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 612 |
646 if (operation_cid() == kSmiCid) { | 613 if (operation_cid() == kSmiCid) { |
647 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 614 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
648 return; | 615 } else { |
| 616 ASSERT(operation_cid() == kDoubleCid); |
| 617 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
649 } | 618 } |
650 ASSERT(operation_cid() == kDoubleCid); | |
651 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | |
652 } | 619 } |
653 | 620 |
654 | 621 |
655 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 622 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
656 const intptr_t kNumInputs = 0; | 623 const intptr_t kNumInputs = 0; |
657 const intptr_t kNumTemps = 3; | 624 const intptr_t kNumTemps = 3; |
658 LocationSummary* locs = | 625 LocationSummary* locs = |
659 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 626 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
660 locs->set_temp(0, Location::RegisterLocation(RAX)); | 627 locs->set_temp(0, Location::RegisterLocation(RAX)); |
661 locs->set_temp(1, Location::RegisterLocation(RBX)); | 628 locs->set_temp(1, Location::RegisterLocation(RBX)); |
(...skipping 3774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4436 // Only one of the inputs can be a constant. Choose register if the first one | 4403 // Only one of the inputs can be a constant. Choose register if the first one |
4437 // is a constant. | 4404 // is a constant. |
4438 locs->set_in(1, locs->in(0).IsConstant() | 4405 locs->set_in(1, locs->in(0).IsConstant() |
4439 ? Location::RequiresRegister() | 4406 ? Location::RequiresRegister() |
4440 : Location::RegisterOrConstant(right())); | 4407 : Location::RegisterOrConstant(right())); |
4441 locs->set_out(Location::RequiresRegister()); | 4408 locs->set_out(Location::RequiresRegister()); |
4442 return locs; | 4409 return locs; |
4443 } | 4410 } |
4444 | 4411 |
4445 | 4412 |
| 4413 static void EmitStrictComparison(FlowGraphCompiler* compiler, |
| 4414 StrictCompareInstr* compare, |
| 4415 BranchLabels labels) { |
| 4416 LocationSummary* locs = compare->locs(); |
| 4417 bool needs_number_check = compare->needs_number_check(); |
| 4418 intptr_t token_pos = compare->token_pos(); |
| 4419 Token::Kind kind = compare->kind(); |
| 4420 Location left = locs->in(0); |
| 4421 Location right = locs->in(1); |
| 4422 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 4423 if (left.IsConstant()) { |
| 4424 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 4425 left.constant(), |
| 4426 needs_number_check, |
| 4427 token_pos); |
| 4428 } else if (right.IsConstant()) { |
| 4429 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 4430 right.constant(), |
| 4431 needs_number_check, |
| 4432 token_pos); |
| 4433 } else { |
| 4434 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 4435 right.reg(), |
| 4436 needs_number_check, |
| 4437 token_pos); |
| 4438 } |
| 4439 |
| 4440 Condition true_condition = (kind == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 4441 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4442 } |
| 4443 |
| 4444 |
4446 // Special code for numbers (compare values instead of references.) | 4445 // Special code for numbers (compare values instead of references.) |
4447 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4446 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4448 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4447 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
4449 Location left = locs()->in(0); | 4448 |
4450 Location right = locs()->in(1); | 4449 Label is_true, is_false; |
4451 ASSERT(!left.IsConstant() || !right.IsConstant()); | 4450 BranchLabels labels = { &is_true, &is_false, &is_false }; |
4452 if (left.IsConstant()) { | 4451 |
4453 compiler->EmitEqualityRegConstCompare(right.reg(), | 4452 EmitStrictComparison(compiler, this, labels); |
4454 left.constant(), | |
4455 needs_number_check(), | |
4456 token_pos()); | |
4457 } else if (right.IsConstant()) { | |
4458 compiler->EmitEqualityRegConstCompare(left.reg(), | |
4459 right.constant(), | |
4460 needs_number_check(), | |
4461 token_pos()); | |
4462 } else { | |
4463 compiler->EmitEqualityRegRegCompare(left.reg(), | |
4464 right.reg(), | |
4465 needs_number_check(), | |
4466 token_pos()); | |
4467 } | |
4468 | 4453 |
4469 Register result = locs()->out().reg(); | 4454 Register result = locs()->out().reg(); |
4470 Label load_true, done; | 4455 Label done; |
4471 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 4456 __ Bind(&is_false); |
4472 __ j(true_condition, &load_true, Assembler::kNearJump); | |
4473 __ LoadObject(result, Bool::False(), PP); | 4457 __ LoadObject(result, Bool::False(), PP); |
4474 __ jmp(&done, Assembler::kNearJump); | 4458 __ jmp(&done); |
4475 __ Bind(&load_true); | 4459 __ Bind(&is_true); |
4476 __ LoadObject(result, Bool::True(), PP); | 4460 __ LoadObject(result, Bool::True(), PP); |
4477 __ Bind(&done); | 4461 __ Bind(&done); |
4478 } | 4462 } |
4479 | 4463 |
4480 | 4464 |
4481 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 4465 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
4482 BranchInstr* branch) { | 4466 BranchInstr* branch) { |
4483 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4467 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
4484 Location left = locs()->in(0); | |
4485 Location right = locs()->in(1); | |
4486 ASSERT(!left.IsConstant() || !right.IsConstant()); | |
4487 if (left.IsConstant()) { | |
4488 compiler->EmitEqualityRegConstCompare(right.reg(), | |
4489 left.constant(), | |
4490 needs_number_check(), | |
4491 token_pos()); | |
4492 } else if (right.IsConstant()) { | |
4493 compiler->EmitEqualityRegConstCompare(left.reg(), | |
4494 right.constant(), | |
4495 needs_number_check(), | |
4496 token_pos()); | |
4497 } else { | |
4498 compiler->EmitEqualityRegRegCompare(left.reg(), | |
4499 right.reg(), | |
4500 needs_number_check(), | |
4501 token_pos()); | |
4502 } | |
4503 | 4468 |
4504 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 4469 BranchLabels labels = compiler->CreateBranchLabels(branch); |
4505 EmitBranchOnCondition(compiler, | 4470 |
4506 branch->true_successor(), | 4471 EmitStrictComparison(compiler, this, labels); |
4507 branch->false_successor(), | |
4508 true_condition); | |
4509 } | 4472 } |
4510 | 4473 |
4511 | 4474 |
4512 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { | 4475 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { |
4513 const intptr_t kNumInputs = 0; | 4476 const intptr_t kNumInputs = 0; |
4514 const intptr_t kNumTemps = 1; | 4477 const intptr_t kNumTemps = 1; |
4515 LocationSummary* result = | 4478 LocationSummary* result = |
4516 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4479 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
4517 result->set_out(Location::RegisterLocation(RAX)); | 4480 result->set_out(Location::RegisterLocation(RAX)); |
4518 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. | 4481 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4617 PcDescriptors::kOther, | 4580 PcDescriptors::kOther, |
4618 locs()); | 4581 locs()); |
4619 __ Drop(2); // Discard type arguments and receiver. | 4582 __ Drop(2); // Discard type arguments and receiver. |
4620 } | 4583 } |
4621 | 4584 |
4622 } // namespace dart | 4585 } // namespace dart |
4623 | 4586 |
4624 #undef __ | 4587 #undef __ |
4625 | 4588 |
4626 #endif // defined TARGET_ARCH_X64 | 4589 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |