Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Side by Side Diff: runtime/vm/intermediate_language_x64.cc

Issue 10886015: Eliminate try-index for deopt stubs. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 "lib/error.h" 10 #include "lib/error.h"
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 LocationSummary* locs, 356 LocationSummary* locs,
357 BranchInstr* branch, 357 BranchInstr* branch,
358 Token::Kind kind, 358 Token::Kind kind,
359 intptr_t deopt_id, 359 intptr_t deopt_id,
360 intptr_t token_pos, 360 intptr_t token_pos,
361 intptr_t try_index) { 361 intptr_t try_index) {
362 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 362 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
363 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); 363 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
364 ASSERT(ic_data.NumberOfChecks() > 0); 364 ASSERT(ic_data.NumberOfChecks() > 0);
365 ASSERT(ic_data.num_args_tested() == 1); 365 ASSERT(ic_data.num_args_tested() == 1);
366 Label* deopt = compiler->AddDeoptStub(deopt_id, try_index, kDeoptEquality); 366 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
367 Register left = locs->in(0).reg(); 367 Register left = locs->in(0).reg();
368 Register right = locs->in(1).reg(); 368 Register right = locs->in(1).reg();
369 __ testq(left, Immediate(kSmiTagMask)); 369 __ testq(left, Immediate(kSmiTagMask));
370 Register temp = locs->temp(0).reg(); 370 Register temp = locs->temp(0).reg();
371 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { 371 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) {
372 Label done, load_class_id; 372 Label done, load_class_id;
373 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); 373 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump);
374 __ movq(temp, Immediate(kSmiCid)); 374 __ movq(temp, Immediate(kSmiCid));
375 __ jmp(&done, Assembler::kNearJump); 375 __ jmp(&done, Assembler::kNearJump);
376 __ Bind(&load_class_id); 376 __ Bind(&load_class_id);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 __ Bind(&done); 441 __ Bind(&done);
442 } 442 }
443 443
444 444
445 // Emit code when ICData's targets are all Object == (which is ===). 445 // Emit code when ICData's targets are all Object == (which is ===).
446 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, 446 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler,
447 const ICData& ic_data, 447 const ICData& ic_data,
448 const LocationSummary& locs, 448 const LocationSummary& locs,
449 Token::Kind kind, 449 Token::Kind kind,
450 BranchInstr* branch, 450 BranchInstr* branch,
451 intptr_t deopt_id, 451 intptr_t deopt_id) {
452 intptr_t try_index) {
453 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 452 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
454 Register left = locs.in(0).reg(); 453 Register left = locs.in(0).reg();
455 Register right = locs.in(1).reg(); 454 Register right = locs.in(1).reg();
456 Register temp = locs.temp(0).reg(); 455 Register temp = locs.temp(0).reg();
457 Label* deopt = compiler->AddDeoptStub(deopt_id, 456 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
458 try_index,
459 kDeoptEquality);
460 __ testq(left, Immediate(kSmiTagMask)); 457 __ testq(left, Immediate(kSmiTagMask));
461 __ j(ZERO, deopt); 458 __ j(ZERO, deopt);
462 // 'left' is not Smi. 459 // 'left' is not Smi.
463 const Immediate raw_null = 460 const Immediate raw_null =
464 Immediate(reinterpret_cast<intptr_t>(Object::null())); 461 Immediate(reinterpret_cast<intptr_t>(Object::null()));
465 Label identity_compare; 462 Label identity_compare;
466 __ cmpq(right, raw_null); 463 __ cmpq(right, raw_null);
467 __ j(EQUAL, &identity_compare); 464 __ j(EQUAL, &identity_compare);
468 __ cmpq(left, raw_null); 465 __ cmpq(left, raw_null);
469 __ j(EQUAL, &identity_compare); 466 __ j(EQUAL, &identity_compare);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, 539 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind,
543 deopt_id, token_pos, try_index); 540 deopt_id, token_pos, try_index);
544 __ Bind(&done); 541 __ Bind(&done);
545 } 542 }
546 543
547 544
548 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 545 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
549 const LocationSummary& locs, 546 const LocationSummary& locs,
550 Token::Kind kind, 547 Token::Kind kind,
551 BranchInstr* branch, 548 BranchInstr* branch,
552 intptr_t deopt_id, 549 intptr_t deopt_id) {
553 intptr_t try_index) {
554 Register left = locs.in(0).reg(); 550 Register left = locs.in(0).reg();
555 Register right = locs.in(1).reg(); 551 Register right = locs.in(1).reg();
556 const bool left_is_smi = (branch == NULL) ? 552 const bool left_is_smi = (branch == NULL) ?
557 false : (branch->left()->ResultCid() == kSmiCid); 553 false : (branch->left()->ResultCid() == kSmiCid);
558 const bool right_is_smi = (branch == NULL) ? 554 const bool right_is_smi = (branch == NULL) ?
559 false : (branch->right()->ResultCid() == kSmiCid); 555 false : (branch->right()->ResultCid() == kSmiCid);
560 if (!left_is_smi || !right_is_smi) { 556 if (!left_is_smi || !right_is_smi) {
561 Register temp = locs.temp(0).reg(); 557 Register temp = locs.temp(0).reg();
562 Label* deopt = compiler->AddDeoptStub(deopt_id, 558 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptSmiCompareSmi);
563 try_index,
564 kDeoptSmiCompareSmi);
565 __ movq(temp, left); 559 __ movq(temp, left);
566 __ orq(temp, right); 560 __ orq(temp, right);
567 __ testq(temp, Immediate(kSmiTagMask)); 561 __ testq(temp, Immediate(kSmiTagMask));
568 __ j(NOT_ZERO, deopt); 562 __ j(NOT_ZERO, deopt);
569 } 563 }
570 564
571 Condition true_condition = TokenKindToSmiCondition(kind); 565 Condition true_condition = TokenKindToSmiCondition(kind);
572 __ cmpq(left, right); 566 __ cmpq(left, right);
573 567
574 if (branch != NULL) { 568 if (branch != NULL) {
(...skipping 23 matching lines...) Expand all
598 UNREACHABLE(); 592 UNREACHABLE();
599 return OVERFLOW; 593 return OVERFLOW;
600 } 594 }
601 } 595 }
602 596
603 597
604 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 598 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
605 const LocationSummary& locs, 599 const LocationSummary& locs,
606 Token::Kind kind, 600 Token::Kind kind,
607 BranchInstr* branch, 601 BranchInstr* branch,
608 intptr_t deopt_id, 602 intptr_t deopt_id) {
609 intptr_t try_index) {
610 Register left = locs.in(0).reg(); 603 Register left = locs.in(0).reg();
611 Register right = locs.in(1).reg(); 604 Register right = locs.in(1).reg();
612 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. 605 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs.
613 Register temp = locs.temp(0).reg(); 606 Register temp = locs.temp(0).reg();
614 Label* deopt = compiler->AddDeoptStub(deopt_id, 607 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptDoubleComparison);
615 try_index,
616 kDeoptDoubleComparison);
617 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 608 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
618 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 609 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
619 610
620 Condition true_condition = TokenKindToDoubleCondition(kind); 611 Condition true_condition = TokenKindToDoubleCondition(kind);
621 if (branch != NULL) { 612 if (branch != NULL) {
622 compiler->EmitDoubleCompareBranch( 613 compiler->EmitDoubleCompareBranch(
623 true_condition, XMM0, XMM1, branch); 614 true_condition, XMM0, XMM1, branch);
624 } else { 615 } else {
625 compiler->EmitDoubleCompareBool( 616 compiler->EmitDoubleCompareBool(
626 true_condition, XMM0, XMM1, locs.out().reg()); 617 true_condition, XMM0, XMM1, locs.out().reg());
627 } 618 }
628 } 619 }
629 620
630 621
631 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 622 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
623 BranchInstr* kNoBranch = NULL;
632 if (receiver_class_id() == kSmiCid) { 624 if (receiver_class_id() == kSmiCid) {
633 // Deoptimizes if both arguments not Smi. 625 // Deoptimizes if both arguments not Smi.
634 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 626 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id());
635 deopt_id(), try_index());
636 return; 627 return;
637 } 628 }
638 if (receiver_class_id() == kDoubleCid) { 629 if (receiver_class_id() == kDoubleCid) {
639 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. 630 // Deoptimizes if both arguments are Smi, or if none is Double or Smi.
640 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 631 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id());
641 deopt_id(), try_index());
642 return; 632 return;
643 } 633 }
644 const bool is_checked_strict_equal = 634 const bool is_checked_strict_equal =
645 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); 635 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
646 if (is_checked_strict_equal) { 636 if (is_checked_strict_equal) {
647 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, 637 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
648 deopt_id(), try_index()); 638 deopt_id());
649 return; 639 return;
650 } 640 }
651 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 641 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
652 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(), 642 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(),
653 deopt_id(), token_pos(), try_index()); 643 deopt_id(), token_pos(), try_index());
654 } else { 644 } else {
655 Register left = locs()->in(0).reg(); 645 Register left = locs()->in(0).reg();
656 Register right = locs()->in(1).reg(); 646 Register right = locs()->in(1).reg();
657 __ pushq(left); 647 __ pushq(left);
658 __ pushq(right); 648 __ pushq(right);
659 EmitEqualityAsInstanceCall(compiler, 649 EmitEqualityAsInstanceCall(compiler,
660 deopt_id(), 650 deopt_id(),
661 token_pos(), 651 token_pos(),
662 try_index(), 652 try_index(),
(...skipping 22 matching lines...) Expand all
685 // Pick arbitrary fixed input registers because this is a call. 675 // Pick arbitrary fixed input registers because this is a call.
686 locs->set_in(0, Location::RegisterLocation(RAX)); 676 locs->set_in(0, Location::RegisterLocation(RAX));
687 locs->set_in(1, Location::RegisterLocation(RCX)); 677 locs->set_in(1, Location::RegisterLocation(RCX));
688 locs->set_out(Location::RegisterLocation(RAX)); 678 locs->set_out(Location::RegisterLocation(RAX));
689 return locs; 679 return locs;
690 } 680 }
691 681
692 682
693 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 683 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
694 if (operands_class_id() == kSmiCid) { 684 if (operands_class_id() == kSmiCid) {
695 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, 685 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, deopt_id());
696 deopt_id(), try_index());
697 return; 686 return;
698 } 687 }
699 if (operands_class_id() == kDoubleCid) { 688 if (operands_class_id() == kDoubleCid) {
700 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, 689 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, deopt_id());
701 deopt_id(), try_index());
702 return; 690 return;
703 } 691 }
704 692
705 // Push arguments for the call. 693 // Push arguments for the call.
706 // TODO(fschneider): Split this instruction into different types to avoid 694 // TODO(fschneider): Split this instruction into different types to avoid
707 // explicitly pushing arguments to the call here. 695 // explicitly pushing arguments to the call here.
708 Register left = locs()->in(0).reg(); 696 Register left = locs()->in(0).reg();
709 Register right = locs()->in(1).reg(); 697 Register right = locs()->in(1).reg();
710 __ pushq(left); 698 __ pushq(left);
711 __ pushq(right); 699 __ pushq(right);
712 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 700 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
713 Label* deopt = compiler->AddDeoptStub(deopt_id(), 701 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptRelationalOp);
714 try_index(),
715 kDeoptRelationalOp);
716 702
717 // Load class into RDI. Since this is a call, any register except 703 // Load class into RDI. Since this is a call, any register except
718 // the fixed input registers would be ok. 704 // the fixed input registers would be ok.
719 ASSERT((left != RDI) && (right != RDI)); 705 ASSERT((left != RDI) && (right != RDI));
720 Label done; 706 Label done;
721 __ movq(RDI, Immediate(kSmiCid)); 707 __ movq(RDI, Immediate(kSmiCid));
722 __ testq(left, Immediate(kSmiTagMask)); 708 __ testq(left, Immediate(kSmiTagMask));
723 __ j(ZERO, &done); 709 __ j(ZERO, &done);
724 __ LoadClassId(RDI, left); 710 __ LoadClassId(RDI, left);
725 __ Bind(&done); 711 __ Bind(&done);
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 LocationSummary::kNoCall); 1081 LocationSummary::kNoCall);
1096 } 1082 }
1097 1083
1098 1084
1099 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1085 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1100 Register instance_reg = locs()->in(0).reg(); 1086 Register instance_reg = locs()->in(0).reg();
1101 Register result_reg = locs()->out().reg(); 1087 Register result_reg = locs()->out().reg();
1102 if (HasICData()) { 1088 if (HasICData()) {
1103 ASSERT(original() != NULL); 1089 ASSERT(original() != NULL);
1104 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), 1090 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(),
1105 original()->try_index(),
1106 kDeoptInstanceGetterSameTarget); 1091 kDeoptInstanceGetterSameTarget);
1107 // Smis do not have instance fields (Smi class is always first). 1092 // Smis do not have instance fields (Smi class is always first).
1108 // Use 'result' as temporary register. 1093 // Use 'result' as temporary register.
1109 ASSERT(result_reg != instance_reg); 1094 ASSERT(result_reg != instance_reg);
1110 ASSERT(ic_data() != NULL); 1095 ASSERT(ic_data() != NULL);
1111 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); 1096 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt);
1112 } 1097 }
1113 1098
1114 __ movq(result_reg, FieldAddress(instance_reg, offset_in_bytes())); 1099 __ movq(result_reg, FieldAddress(instance_reg, offset_in_bytes()));
1115 } 1100 }
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 ASSERT(left == result); 1462 ASSERT(left == result);
1478 Label* deopt = NULL; 1463 Label* deopt = NULL;
1479 switch (op_kind()) { 1464 switch (op_kind()) {
1480 case Token::kBIT_AND: 1465 case Token::kBIT_AND:
1481 case Token::kBIT_OR: 1466 case Token::kBIT_OR:
1482 case Token::kBIT_XOR: 1467 case Token::kBIT_XOR:
1483 // Can't deoptimize. Arguments are already checked for smi. 1468 // Can't deoptimize. Arguments are already checked for smi.
1484 break; 1469 break;
1485 default: 1470 default:
1486 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1471 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1487 instance_call()->try_index(),
1488 kDeoptBinarySmiOp); 1472 kDeoptBinarySmiOp);
1489 } 1473 }
1490 switch (op_kind()) { 1474 switch (op_kind()) {
1491 case Token::kADD: { 1475 case Token::kADD: {
1492 __ addq(left, right); 1476 __ addq(left, right);
1493 __ j(OVERFLOW, deopt); 1477 __ j(OVERFLOW, deopt);
1494 break; 1478 break;
1495 } 1479 }
1496 case Token::kSUB: { 1480 case Token::kSUB: {
1497 __ subq(left, right); 1481 __ subq(left, right);
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1643 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi 1627 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi
1644 // receiver and a Mint or Smi argument. We fall back to the run time call if 1628 // receiver and a Mint or Smi argument. We fall back to the run time call if
1645 // both receiver and argument are Mint or if one of them is Mint and the other 1629 // both receiver and argument are Mint or if one of them is Mint and the other
1646 // is a negative Smi. 1630 // is a negative Smi.
1647 Register left = locs()->in(0).reg(); 1631 Register left = locs()->in(0).reg();
1648 Register right = locs()->in(1).reg(); 1632 Register right = locs()->in(1).reg();
1649 Register result = locs()->out().reg(); 1633 Register result = locs()->out().reg();
1650 ASSERT(left == result); 1634 ASSERT(left == result);
1651 ASSERT(op_kind() == Token::kBIT_AND); 1635 ASSERT(op_kind() == Token::kBIT_AND);
1652 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1636 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1653 instance_call()->try_index(),
1654 kDeoptBinaryMintOp); 1637 kDeoptBinaryMintOp);
1655 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; 1638 Label mint_static_call, smi_static_call, non_smi, smi_smi, done;
1656 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? 1639 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi?
1657 __ j(NOT_ZERO, &non_smi); 1640 __ j(NOT_ZERO, &non_smi);
1658 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? 1641 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi?
1659 __ j(ZERO, &smi_smi); 1642 __ j(ZERO, &smi_smi);
1660 __ CompareClassId(right, kMintCid); // Is argument Mint? 1643 __ CompareClassId(right, kMintCid); // Is argument Mint?
1661 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. 1644 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint.
1662 __ cmpq(left, Immediate(0)); 1645 __ cmpq(left, Immediate(0));
1663 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. 1646 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument.
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1750 instance_call()->try_index(), 1733 instance_call()->try_index(),
1751 &label, 1734 &label,
1752 PcDescriptors::kOther, 1735 PcDescriptors::kOther,
1753 locs()); 1736 locs());
1754 // Newly allocated object is now in the result register (RAX). 1737 // Newly allocated object is now in the result register (RAX).
1755 ASSERT(result == RAX); 1738 ASSERT(result == RAX);
1756 __ movq(right, Address(RSP, 0)); 1739 __ movq(right, Address(RSP, 0));
1757 __ movq(left, Address(RSP, kWordSize)); 1740 __ movq(left, Address(RSP, kWordSize));
1758 1741
1759 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1742 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1760 instance_call()->try_index(),
1761 kDeoptBinaryDoubleOp); 1743 kDeoptBinaryDoubleOp);
1762 1744
1763 // Binary operation of two Smi's produces a Smi not a double. 1745 // Binary operation of two Smi's produces a Smi not a double.
1764 __ movq(temp, left); 1746 __ movq(temp, left);
1765 __ orq(temp, right); 1747 __ orq(temp, right);
1766 __ testq(temp, Immediate(kSmiTagMask)); 1748 __ testq(temp, Immediate(kSmiTagMask));
1767 __ j(ZERO, deopt); 1749 __ j(ZERO, deopt);
1768 1750
1769 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 1751 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
1770 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 1752 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
(...skipping 21 matching lines...) Expand all
1792 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1774 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1793 summary->set_in(0, Location::RequiresRegister()); 1775 summary->set_in(0, Location::RequiresRegister());
1794 summary->set_in(1, Location::RequiresRegister()); 1776 summary->set_in(1, Location::RequiresRegister());
1795 summary->set_temp(0, Location::RequiresRegister()); 1777 summary->set_temp(0, Location::RequiresRegister());
1796 return summary; 1778 return summary;
1797 } 1779 }
1798 1780
1799 1781
1800 void CheckEitherNonSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1782 void CheckEitherNonSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1801 Label* deopt = compiler->AddDeoptStub(instance_call_->deopt_id(), 1783 Label* deopt = compiler->AddDeoptStub(instance_call_->deopt_id(),
1802 instance_call_->try_index(),
1803 kDeoptBinaryDoubleOp); 1784 kDeoptBinaryDoubleOp);
1804 1785
1805 Register temp = locs()->temp(0).reg(); 1786 Register temp = locs()->temp(0).reg();
1806 __ movq(temp, locs()->in(0).reg()); 1787 __ movq(temp, locs()->in(0).reg());
1807 __ orq(temp, locs()->in(1).reg()); 1788 __ orq(temp, locs()->in(1).reg());
1808 __ testl(temp, Immediate(kSmiTagMask)); 1789 __ testl(temp, Immediate(kSmiTagMask));
1809 __ j(ZERO, deopt); 1790 __ j(ZERO, deopt);
1810 } 1791 }
1811 1792
1812 1793
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1888 } 1869 }
1889 1870
1890 1871
1891 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1872 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1892 const intptr_t v_cid = value()->ResultCid(); 1873 const intptr_t v_cid = value()->ResultCid();
1893 1874
1894 const Register value = locs()->in(0).reg(); 1875 const Register value = locs()->in(0).reg();
1895 const XmmRegister result = locs()->out().xmm_reg(); 1876 const XmmRegister result = locs()->out().xmm_reg();
1896 if (v_cid != kDoubleCid) { 1877 if (v_cid != kDoubleCid) {
1897 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1878 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1898 instance_call()->try_index(),
1899 kDeoptBinaryDoubleOp); 1879 kDeoptBinaryDoubleOp);
1900 compiler->LoadDoubleOrSmiToXmm(result, 1880 compiler->LoadDoubleOrSmiToXmm(result,
1901 value, 1881 value,
1902 locs()->temp(0).reg(), 1882 locs()->temp(0).reg(),
1903 deopt); 1883 deopt);
1904 } else { 1884 } else {
1905 __ movsd(result, FieldAddress(value, Double::value_offset())); 1885 __ movsd(result, FieldAddress(value, Double::value_offset()));
1906 } 1886 }
1907 } 1887 }
1908 1888
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1945 return summary; 1925 return summary;
1946 } 1926 }
1947 1927
1948 1928
1949 void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1929 void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1950 Register value = locs()->in(0).reg(); 1930 Register value = locs()->in(0).reg();
1951 ASSERT(value == locs()->out().reg()); 1931 ASSERT(value == locs()->out().reg());
1952 switch (op_kind()) { 1932 switch (op_kind()) {
1953 case Token::kNEGATE: { 1933 case Token::kNEGATE: {
1954 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1934 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1955 instance_call()->try_index(),
1956 kDeoptUnaryOp); 1935 kDeoptUnaryOp);
1957 __ negq(value); 1936 __ negq(value);
1958 __ j(OVERFLOW, deopt); 1937 __ j(OVERFLOW, deopt);
1959 break; 1938 break;
1960 } 1939 }
1961 case Token::kBIT_NOT: 1940 case Token::kBIT_NOT:
1962 __ notq(value); 1941 __ notq(value);
1963 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. 1942 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
1964 break; 1943 break;
1965 default: 1944 default:
(...skipping 22 matching lines...) Expand all
1988 // TODO(srdjan): Implement for more checks. 1967 // TODO(srdjan): Implement for more checks.
1989 ASSERT(ic_data.NumberOfChecks() == 1); 1968 ASSERT(ic_data.NumberOfChecks() == 1);
1990 intptr_t test_class_id; 1969 intptr_t test_class_id;
1991 Function& target = Function::Handle(); 1970 Function& target = Function::Handle();
1992 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); 1971 ic_data.GetOneClassCheckAt(0, &test_class_id, &target);
1993 1972
1994 Register value = locs()->in(0).reg(); 1973 Register value = locs()->in(0).reg();
1995 Register result = locs()->out().reg(); 1974 Register result = locs()->out().reg();
1996 ASSERT(value == result); 1975 ASSERT(value == result);
1997 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1976 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1998 instance_call()->try_index(),
1999 kDeoptUnaryOp); 1977 kDeoptUnaryOp);
2000 if (test_class_id == kDoubleCid) { 1978 if (test_class_id == kDoubleCid) {
2001 Register temp = locs()->temp(0).reg(); 1979 Register temp = locs()->temp(0).reg();
2002 __ testq(value, Immediate(kSmiTagMask)); 1980 __ testq(value, Immediate(kSmiTagMask));
2003 __ j(ZERO, deopt); // Smi. 1981 __ j(ZERO, deopt); // Smi.
2004 __ CompareClassId(value, kDoubleCid); 1982 __ CompareClassId(value, kDoubleCid);
2005 __ j(NOT_EQUAL, deopt); 1983 __ j(NOT_EQUAL, deopt);
2006 // Allocate result object. 1984 // Allocate result object.
2007 const Class& double_class = compiler->double_class(); 1985 const Class& double_class = compiler->double_class();
2008 const Code& stub = 1986 const Code& stub =
(...skipping 28 matching lines...) Expand all
2037 locs->set_out(Location::SameAsFirstInput()); 2015 locs->set_out(Location::SameAsFirstInput());
2038 return locs; 2016 return locs;
2039 } 2017 }
2040 2018
2041 2019
2042 void DoubleToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2020 void DoubleToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2043 Register value = locs()->in(0).reg(); 2021 Register value = locs()->in(0).reg();
2044 Register result = locs()->out().reg(); 2022 Register result = locs()->out().reg();
2045 2023
2046 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 2024 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
2047 instance_call()->try_index(),
2048 kDeoptDoubleToDouble); 2025 kDeoptDoubleToDouble);
2049 2026
2050 __ testq(value, Immediate(kSmiTagMask)); 2027 __ testq(value, Immediate(kSmiTagMask));
2051 __ j(ZERO, deopt); // Deoptimize if Smi. 2028 __ j(ZERO, deopt); // Deoptimize if Smi.
2052 __ CompareClassId(value, kDoubleCid); 2029 __ CompareClassId(value, kDoubleCid);
2053 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. 2030 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double.
2054 ASSERT(value == result); 2031 ASSERT(value == result);
2055 } 2032 }
2056 2033
2057 2034
2058 LocationSummary* SmiToDoubleComp::MakeLocationSummary() const { 2035 LocationSummary* SmiToDoubleComp::MakeLocationSummary() const {
2059 return MakeCallSummary(); // Calls a stub to allocate result. 2036 return MakeCallSummary(); // Calls a stub to allocate result.
2060 } 2037 }
2061 2038
2062 2039
2063 void SmiToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2040 void SmiToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2064 Register result = locs()->out().reg(); 2041 Register result = locs()->out().reg();
2065 2042
2066 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 2043 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
2067 instance_call()->try_index(),
2068 kDeoptIntegerToDouble); 2044 kDeoptIntegerToDouble);
2069 2045
2070 const Class& double_class = compiler->double_class(); 2046 const Class& double_class = compiler->double_class();
2071 const Code& stub = 2047 const Code& stub =
2072 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); 2048 Code::Handle(StubCode::GetAllocationStubForClass(double_class));
2073 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); 2049 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
2074 2050
2075 // TODO(fschneider): Inline new-space allocation and move the call into 2051 // TODO(fschneider): Inline new-space allocation and move the call into
2076 // deferred code. 2052 // deferred code.
2077 compiler->GenerateCall(instance_call()->token_pos(), 2053 compiler->GenerateCall(instance_call()->token_pos(),
(...skipping 15 matching lines...) Expand all
2093 } 2069 }
2094 2070
2095 2071
2096 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { 2072 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const {
2097 return MakeCallSummary(); 2073 return MakeCallSummary();
2098 } 2074 }
2099 2075
2100 2076
2101 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2077 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2102 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 2078 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
2103 instance_call()->try_index(),
2104 kDeoptPolymorphicInstanceCallTestFail); 2079 kDeoptPolymorphicInstanceCallTestFail);
2105 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { 2080 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) {
2106 __ jmp(deopt); 2081 __ jmp(deopt);
2107 return; 2082 return;
2108 } 2083 }
2109 ASSERT(HasICData()); 2084 ASSERT(HasICData());
2110 ASSERT(ic_data()->num_args_tested() == 1); 2085 ASSERT(ic_data()->num_args_tested() == 1);
2111 if (!with_checks()) { 2086 if (!with_checks()) {
2112 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); 2087 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0));
2113 compiler->GenerateStaticCall(instance_call()->deopt_id(), 2088 compiler->GenerateStaticCall(instance_call()->deopt_id(),
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2194 locs->set_in(0, Location::RegisterLocation(RAX)); 2169 locs->set_in(0, Location::RegisterLocation(RAX));
2195 locs->set_in(1, Location::RegisterLocation(RCX)); 2170 locs->set_in(1, Location::RegisterLocation(RCX));
2196 return locs; 2171 return locs;
2197 } 2172 }
2198 2173
2199 2174
2200 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2175 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2201 // Relational or equality. 2176 // Relational or equality.
2202 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 2177 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2203 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) { 2178 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) {
2204 EmitSmiComparisonOp(compiler, *locs(), kind(), this, 2179 EmitSmiComparisonOp(compiler, *locs(), kind(), this, deopt_id());
2205 deopt_id(), try_index());
2206 return; 2180 return;
2207 } 2181 }
2208 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { 2182 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) {
2209 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, 2183 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, deopt_id());
2210 deopt_id(), try_index());
2211 return; 2184 return;
2212 } 2185 }
2213 if (IsCheckedStrictEquals(*ic_data(), kind())) { 2186 if (IsCheckedStrictEquals(*ic_data(), kind())) {
2214 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, 2187 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this,
2215 deopt_id(), try_index()); 2188 deopt_id());
2216 return; 2189 return;
2217 } 2190 }
2218 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. 2191 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons.
2219 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { 2192 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) {
2220 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(), 2193 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(),
2221 deopt_id(), token_pos(), try_index()); 2194 deopt_id(), token_pos(), try_index());
2222 return; 2195 return;
2223 } 2196 }
2224 // Otherwise polymorphic dispatch? 2197 // Otherwise polymorphic dispatch?
2225 } 2198 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2286 summary->set_in(0, Location::RequiresRegister()); 2259 summary->set_in(0, Location::RequiresRegister());
2287 summary->set_temp(0, Location::RequiresRegister()); 2260 summary->set_temp(0, Location::RequiresRegister());
2288 return summary; 2261 return summary;
2289 } 2262 }
2290 2263
2291 2264
2292 void CheckClassComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2265 void CheckClassComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2293 Register value = locs()->in(0).reg(); 2266 Register value = locs()->in(0).reg();
2294 Register temp = locs()->temp(0).reg(); 2267 Register temp = locs()->temp(0).reg();
2295 Label* deopt = compiler->AddDeoptStub(deopt_id(), 2268 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2296 try_index(),
2297 kDeoptCheckClass); 2269 kDeoptCheckClass);
2298 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmiCid); 2270 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmiCid);
2299 __ testq(value, Immediate(kSmiTagMask)); 2271 __ testq(value, Immediate(kSmiTagMask));
2300 __ j(ZERO, deopt); 2272 __ j(ZERO, deopt);
2301 __ LoadClassId(temp, value); 2273 __ LoadClassId(temp, value);
2302 Label is_ok; 2274 Label is_ok;
2303 const intptr_t num_checks = ic_data()->NumberOfChecks(); 2275 const intptr_t num_checks = ic_data()->NumberOfChecks();
2304 const bool use_near_jump = num_checks < 5; 2276 const bool use_near_jump = num_checks < 5;
2305 for (intptr_t i = 0; i < num_checks; i++) { 2277 for (intptr_t i = 0; i < num_checks; i++) {
2306 __ cmpl(temp, Immediate(ic_data()->GetReceiverClassIdAt(i))); 2278 __ cmpl(temp, Immediate(ic_data()->GetReceiverClassIdAt(i)));
(...skipping 17 matching lines...) Expand all
2324 LocationSummary* summary = 2296 LocationSummary* summary =
2325 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2297 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2326 summary->set_in(0, Location::RequiresRegister()); 2298 summary->set_in(0, Location::RequiresRegister());
2327 return summary; 2299 return summary;
2328 } 2300 }
2329 2301
2330 2302
2331 void CheckSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2303 void CheckSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2332 Register value = locs()->in(0).reg(); 2304 Register value = locs()->in(0).reg();
2333 Label* deopt = compiler->AddDeoptStub(deopt_id(), 2305 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2334 try_index(),
2335 kDeoptCheckSmi); 2306 kDeoptCheckSmi);
2336 __ testq(value, Immediate(kSmiTagMask)); 2307 __ testq(value, Immediate(kSmiTagMask));
2337 __ j(NOT_ZERO, deopt); 2308 __ j(NOT_ZERO, deopt);
2338 } 2309 }
2339 2310
2340 2311
2341 LocationSummary* CheckArrayBoundComp::MakeLocationSummary() const { 2312 LocationSummary* CheckArrayBoundComp::MakeLocationSummary() const {
2342 return LocationSummary::Make(2, 2313 return LocationSummary::Make(2,
2343 Location::NoLocation(), 2314 Location::NoLocation(),
2344 LocationSummary::kNoCall); 2315 LocationSummary::kNoCall);
2345 } 2316 }
2346 2317
2347 2318
2348 void CheckArrayBoundComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2319 void CheckArrayBoundComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2349 Register receiver = locs()->in(0).reg(); 2320 Register receiver = locs()->in(0).reg();
2350 Register index = locs()->in(1).reg(); 2321 Register index = locs()->in(1).reg();
2351 2322
2352 const DeoptReasonId deopt_reason = 2323 const DeoptReasonId deopt_reason =
2353 (array_type() == kGrowableObjectArrayCid) ? 2324 (array_type() == kGrowableObjectArrayCid) ?
2354 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; 2325 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray;
2355 Label* deopt = compiler->AddDeoptStub(deopt_id(), 2326 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2356 try_index(),
2357 deopt_reason); 2327 deopt_reason);
2358 switch (array_type()) { 2328 switch (array_type()) {
2359 case kArrayCid: 2329 case kArrayCid:
2360 case kImmutableArrayCid: 2330 case kImmutableArrayCid:
2361 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); 2331 __ cmpq(index, FieldAddress(receiver, Array::length_offset()));
2362 break; 2332 break;
2363 case kGrowableObjectArrayCid: 2333 case kGrowableObjectArrayCid:
2364 __ cmpq(index, 2334 __ cmpq(index,
2365 FieldAddress(receiver, GrowableObjectArray::length_offset())); 2335 FieldAddress(receiver, GrowableObjectArray::length_offset()));
2366 break; 2336 break;
2367 } 2337 }
2368 __ j(ABOVE_EQUAL, deopt); 2338 __ j(ABOVE_EQUAL, deopt);
2369 } 2339 }
2370 2340
2371 2341
2372 } // namespace dart 2342 } // namespace dart
2373 2343
2374 #undef __ 2344 #undef __
2375 2345
2376 #endif // defined TARGET_ARCH_X64 2346 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698