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

Side by Side Diff: runtime/vm/intermediate_language_ia32.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/flow_graph_compiler_x64.h ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | 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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 LocationSummary* locs, 347 LocationSummary* locs,
348 BranchInstr* branch, 348 BranchInstr* branch,
349 Token::Kind kind, 349 Token::Kind kind,
350 intptr_t deopt_id, 350 intptr_t deopt_id,
351 intptr_t token_pos, 351 intptr_t token_pos,
352 intptr_t try_index) { 352 intptr_t try_index) {
353 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 353 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
354 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); 354 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
355 ASSERT(ic_data.NumberOfChecks() > 0); 355 ASSERT(ic_data.NumberOfChecks() > 0);
356 ASSERT(ic_data.num_args_tested() == 1); 356 ASSERT(ic_data.num_args_tested() == 1);
357 Label* deopt = compiler->AddDeoptStub(deopt_id, try_index, kDeoptEquality); 357 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
358 Register left = locs->in(0).reg(); 358 Register left = locs->in(0).reg();
359 Register right = locs->in(1).reg(); 359 Register right = locs->in(1).reg();
360 __ testl(left, Immediate(kSmiTagMask)); 360 __ testl(left, Immediate(kSmiTagMask));
361 Register temp = locs->temp(0).reg(); 361 Register temp = locs->temp(0).reg();
362 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { 362 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) {
363 Label done, load_class_id; 363 Label done, load_class_id;
364 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); 364 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump);
365 __ movl(temp, Immediate(kSmiCid)); 365 __ movl(temp, Immediate(kSmiCid));
366 __ jmp(&done, Assembler::kNearJump); 366 __ jmp(&done, Assembler::kNearJump);
367 __ Bind(&load_class_id); 367 __ Bind(&load_class_id);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 __ Bind(&done); 431 __ Bind(&done);
432 } 432 }
433 433
434 434
435 // Emit code when ICData's targets are all Object == (which is ===). 435 // Emit code when ICData's targets are all Object == (which is ===).
436 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, 436 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler,
437 const ICData& ic_data, 437 const ICData& ic_data,
438 const LocationSummary& locs, 438 const LocationSummary& locs,
439 Token::Kind kind, 439 Token::Kind kind,
440 BranchInstr* branch, 440 BranchInstr* branch,
441 intptr_t deopt_id, 441 intptr_t deopt_id) {
442 intptr_t try_index) {
443 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 442 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
444 Register left = locs.in(0).reg(); 443 Register left = locs.in(0).reg();
445 Register right = locs.in(1).reg(); 444 Register right = locs.in(1).reg();
446 Register temp = locs.temp(0).reg(); 445 Register temp = locs.temp(0).reg();
447 Label* deopt = compiler->AddDeoptStub(deopt_id, 446 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
448 try_index,
449 kDeoptEquality);
450 __ testl(left, Immediate(kSmiTagMask)); 447 __ testl(left, Immediate(kSmiTagMask));
451 __ j(ZERO, deopt); 448 __ j(ZERO, deopt);
452 // 'left' is not Smi. 449 // 'left' is not Smi.
453 const Immediate raw_null = 450 const Immediate raw_null =
454 Immediate(reinterpret_cast<intptr_t>(Object::null())); 451 Immediate(reinterpret_cast<intptr_t>(Object::null()));
455 Label identity_compare; 452 Label identity_compare;
456 __ cmpl(right, raw_null); 453 __ cmpl(right, raw_null);
457 __ j(EQUAL, &identity_compare); 454 __ j(EQUAL, &identity_compare);
458 __ cmpl(left, raw_null); 455 __ cmpl(left, raw_null);
459 __ j(EQUAL, &identity_compare); 456 __ j(EQUAL, &identity_compare);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, 529 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind,
533 deopt_id, token_pos, try_index); 530 deopt_id, token_pos, try_index);
534 __ Bind(&done); 531 __ Bind(&done);
535 } 532 }
536 533
537 534
538 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 535 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
539 const LocationSummary& locs, 536 const LocationSummary& locs,
540 Token::Kind kind, 537 Token::Kind kind,
541 BranchInstr* branch, 538 BranchInstr* branch,
542 intptr_t deopt_id, 539 intptr_t deopt_id) {
543 intptr_t try_index) {
544 Register left = locs.in(0).reg(); 540 Register left = locs.in(0).reg();
545 Register right = locs.in(1).reg(); 541 Register right = locs.in(1).reg();
546 const bool left_is_smi = (branch == NULL) ? 542 const bool left_is_smi = (branch == NULL) ?
547 false : (branch->left()->ResultCid() == kSmiCid); 543 false : (branch->left()->ResultCid() == kSmiCid);
548 const bool right_is_smi = (branch == NULL) ? 544 const bool right_is_smi = (branch == NULL) ?
549 false : (branch->right()->ResultCid() == kSmiCid); 545 false : (branch->right()->ResultCid() == kSmiCid);
550 if (!left_is_smi || !right_is_smi) { 546 if (!left_is_smi || !right_is_smi) {
551 Register temp = locs.temp(0).reg(); 547 Register temp = locs.temp(0).reg();
552 Label* deopt = compiler->AddDeoptStub(deopt_id, 548 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptSmiCompareSmi);
553 try_index,
554 kDeoptSmiCompareSmi);
555 __ movl(temp, left); 549 __ movl(temp, left);
556 __ orl(temp, right); 550 __ orl(temp, right);
557 __ testl(temp, Immediate(kSmiTagMask)); 551 __ testl(temp, Immediate(kSmiTagMask));
558 __ j(NOT_ZERO, deopt); 552 __ j(NOT_ZERO, deopt);
559 } 553 }
560 554
561 Condition true_condition = TokenKindToSmiCondition(kind); 555 Condition true_condition = TokenKindToSmiCondition(kind);
562 __ cmpl(left, right); 556 __ cmpl(left, right);
563 557
564 if (branch != NULL) { 558 if (branch != NULL) {
(...skipping 23 matching lines...) Expand all
588 UNREACHABLE(); 582 UNREACHABLE();
589 return OVERFLOW; 583 return OVERFLOW;
590 } 584 }
591 } 585 }
592 586
593 587
594 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 588 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
595 const LocationSummary& locs, 589 const LocationSummary& locs,
596 Token::Kind kind, 590 Token::Kind kind,
597 BranchInstr* branch, 591 BranchInstr* branch,
598 intptr_t deopt_id, 592 intptr_t deopt_id) {
599 intptr_t try_index) {
600 Register left = locs.in(0).reg(); 593 Register left = locs.in(0).reg();
601 Register right = locs.in(1).reg(); 594 Register right = locs.in(1).reg();
602 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. 595 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs.
603 Register temp = locs.temp(0).reg(); 596 Register temp = locs.temp(0).reg();
604 Label* deopt = compiler->AddDeoptStub(deopt_id, 597 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptDoubleComparison);
605 try_index,
606 kDeoptDoubleComparison);
607 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 598 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
608 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 599 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
609 600
610 Condition true_condition = TokenKindToDoubleCondition(kind); 601 Condition true_condition = TokenKindToDoubleCondition(kind);
611 if (branch != NULL) { 602 if (branch != NULL) {
612 compiler->EmitDoubleCompareBranch( 603 compiler->EmitDoubleCompareBranch(
613 true_condition, XMM0, XMM1, branch); 604 true_condition, XMM0, XMM1, branch);
614 } else { 605 } else {
615 compiler->EmitDoubleCompareBool( 606 compiler->EmitDoubleCompareBool(
616 true_condition, XMM0, XMM1, locs.out().reg()); 607 true_condition, XMM0, XMM1, locs.out().reg());
617 } 608 }
618 } 609 }
619 610
620 611
621 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 612 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
613 BranchInstr* kNoBranch = NULL;
622 if (receiver_class_id() == kSmiCid) { 614 if (receiver_class_id() == kSmiCid) {
623 // Deoptimizes if both arguments not Smi. 615 // Deoptimizes if both arguments not Smi.
624 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 616 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id());
625 deopt_id(), try_index());
626 return; 617 return;
627 } 618 }
628 if (receiver_class_id() == kDoubleCid) { 619 if (receiver_class_id() == kDoubleCid) {
629 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. 620 // Deoptimizes if both arguments are Smi, or if none is Double or Smi.
630 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 621 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id());
631 deopt_id(), try_index());
632 return; 622 return;
633 } 623 }
634 const bool is_checked_strict_equal = 624 const bool is_checked_strict_equal =
635 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); 625 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
636 if (is_checked_strict_equal) { 626 if (is_checked_strict_equal) {
637 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, 627 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
638 deopt_id(), try_index()); 628 deopt_id());
639 return; 629 return;
640 } 630 }
641 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 631 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
642 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(), 632 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(),
643 deopt_id(), token_pos(), try_index()); 633 deopt_id(), token_pos(), try_index());
644 } else { 634 } else {
645 Register left = locs()->in(0).reg(); 635 Register left = locs()->in(0).reg();
646 Register right = locs()->in(1).reg(); 636 Register right = locs()->in(1).reg();
647 __ pushl(left); 637 __ pushl(left);
648 __ pushl(right); 638 __ pushl(right);
649 EmitEqualityAsInstanceCall(compiler, 639 EmitEqualityAsInstanceCall(compiler,
650 deopt_id(), 640 deopt_id(),
651 token_pos(), 641 token_pos(),
652 try_index(), 642 try_index(),
(...skipping 22 matching lines...) Expand all
675 // Pick arbitrary fixed input registers because this is a call. 665 // Pick arbitrary fixed input registers because this is a call.
676 locs->set_in(0, Location::RegisterLocation(EAX)); 666 locs->set_in(0, Location::RegisterLocation(EAX));
677 locs->set_in(1, Location::RegisterLocation(ECX)); 667 locs->set_in(1, Location::RegisterLocation(ECX));
678 locs->set_out(Location::RegisterLocation(EAX)); 668 locs->set_out(Location::RegisterLocation(EAX));
679 return locs; 669 return locs;
680 } 670 }
681 671
682 672
683 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 673 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
684 if (operands_class_id() == kSmiCid) { 674 if (operands_class_id() == kSmiCid) {
685 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, 675 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, deopt_id());
686 deopt_id(), try_index());
687 return; 676 return;
688 } 677 }
689 if (operands_class_id() == kDoubleCid) { 678 if (operands_class_id() == kDoubleCid) {
690 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, 679 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, deopt_id());
691 deopt_id(), try_index());
692 return; 680 return;
693 } 681 }
694 682
695 // Push arguments for the call. 683 // Push arguments for the call.
696 // TODO(fschneider): Split this instruction into different types to avoid 684 // TODO(fschneider): Split this instruction into different types to avoid
697 // explicitly pushing arguments to the call here. 685 // explicitly pushing arguments to the call here.
698 Register left = locs()->in(0).reg(); 686 Register left = locs()->in(0).reg();
699 Register right = locs()->in(1).reg(); 687 Register right = locs()->in(1).reg();
700 __ pushl(left); 688 __ pushl(left);
701 __ pushl(right); 689 __ pushl(right);
702 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 690 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
703 Label* deopt = compiler->AddDeoptStub(deopt_id(), 691 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptRelationalOp);
704 try_index(),
705 kDeoptRelationalOp);
706 // Load class into EDI. Since this is a call, any register except 692 // Load class into EDI. Since this is a call, any register except
707 // the fixed input registers would be ok. 693 // the fixed input registers would be ok.
708 ASSERT((left != EDI) && (right != EDI)); 694 ASSERT((left != EDI) && (right != EDI));
709 Label done; 695 Label done;
710 const intptr_t kNumArguments = 2; 696 const intptr_t kNumArguments = 2;
711 __ movl(EDI, Immediate(kSmiCid)); 697 __ movl(EDI, Immediate(kSmiCid));
712 __ testl(left, Immediate(kSmiTagMask)); 698 __ testl(left, Immediate(kSmiTagMask));
713 __ j(ZERO, &done); 699 __ j(ZERO, &done);
714 __ LoadClassId(EDI, left); 700 __ LoadClassId(EDI, left);
715 __ Bind(&done); 701 __ Bind(&done);
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 LocationSummary::kNoCall); 1065 LocationSummary::kNoCall);
1080 } 1066 }
1081 1067
1082 1068
1083 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1069 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1084 Register instance_reg = locs()->in(0).reg(); 1070 Register instance_reg = locs()->in(0).reg();
1085 Register result_reg = locs()->out().reg(); 1071 Register result_reg = locs()->out().reg();
1086 if (HasICData()) { 1072 if (HasICData()) {
1087 ASSERT(original() != NULL); 1073 ASSERT(original() != NULL);
1088 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), 1074 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(),
1089 original()->try_index(),
1090 kDeoptInstanceGetterSameTarget); 1075 kDeoptInstanceGetterSameTarget);
1091 // Smis do not have instance fields (Smi class is always first). 1076 // Smis do not have instance fields (Smi class is always first).
1092 // Use 'result' as temporary register. 1077 // Use 'result' as temporary register.
1093 ASSERT(result_reg != instance_reg); 1078 ASSERT(result_reg != instance_reg);
1094 ASSERT(ic_data() != NULL); 1079 ASSERT(ic_data() != NULL);
1095 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); 1080 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt);
1096 } 1081 }
1097 1082
1098 __ movl(result_reg, FieldAddress(instance_reg, offset_in_bytes())); 1083 __ movl(result_reg, FieldAddress(instance_reg, offset_in_bytes()));
1099 } 1084 }
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
1464 ASSERT(left == result); 1449 ASSERT(left == result);
1465 Label* deopt = NULL; 1450 Label* deopt = NULL;
1466 switch (op_kind()) { 1451 switch (op_kind()) {
1467 case Token::kBIT_AND: 1452 case Token::kBIT_AND:
1468 case Token::kBIT_OR: 1453 case Token::kBIT_OR:
1469 case Token::kBIT_XOR: 1454 case Token::kBIT_XOR:
1470 // Can't deoptimize. Arguments are already checked for smi. 1455 // Can't deoptimize. Arguments are already checked for smi.
1471 break; 1456 break;
1472 default: 1457 default:
1473 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1458 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1474 instance_call()->try_index(),
1475 kDeoptBinarySmiOp); 1459 kDeoptBinarySmiOp);
1476 } 1460 }
1477 1461
1478 switch (op_kind()) { 1462 switch (op_kind()) {
1479 case Token::kADD: { 1463 case Token::kADD: {
1480 __ addl(left, right); 1464 __ addl(left, right);
1481 __ j(OVERFLOW, deopt); 1465 __ j(OVERFLOW, deopt);
1482 break; 1466 break;
1483 } 1467 }
1484 case Token::kSUB: { 1468 case Token::kSUB: {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1633 // receiver and a Mint or Smi argument. We fall back to the run time call if 1617 // receiver and a Mint or Smi argument. We fall back to the run time call if
1634 // both receiver and argument are Mint or if one of them is Mint and the other 1618 // both receiver and argument are Mint or if one of them is Mint and the other
1635 // is a negative Smi. 1619 // is a negative Smi.
1636 Register left = locs()->in(0).reg(); 1620 Register left = locs()->in(0).reg();
1637 Register right = locs()->in(1).reg(); 1621 Register right = locs()->in(1).reg();
1638 Register result = locs()->out().reg(); 1622 Register result = locs()->out().reg();
1639 Register temp = locs()->temp(0).reg(); 1623 Register temp = locs()->temp(0).reg();
1640 ASSERT(left == result); 1624 ASSERT(left == result);
1641 ASSERT(op_kind() == Token::kBIT_AND); 1625 ASSERT(op_kind() == Token::kBIT_AND);
1642 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1626 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1643 instance_call()->try_index(),
1644 kDeoptBinaryMintOp); 1627 kDeoptBinaryMintOp);
1645 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; 1628 Label mint_static_call, smi_static_call, non_smi, smi_smi, done;
1646 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? 1629 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi?
1647 __ j(NOT_ZERO, &non_smi); 1630 __ j(NOT_ZERO, &non_smi);
1648 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? 1631 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi?
1649 __ j(ZERO, &smi_smi); 1632 __ j(ZERO, &smi_smi);
1650 __ CompareClassId(right, kMintCid, temp); // Is argument Mint? 1633 __ CompareClassId(right, kMintCid, temp); // Is argument Mint?
1651 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. 1634 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint.
1652 __ cmpl(left, Immediate(0)); 1635 __ cmpl(left, Immediate(0));
1653 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. 1636 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument.
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1740 instance_call()->try_index(), 1723 instance_call()->try_index(),
1741 &label, 1724 &label,
1742 PcDescriptors::kOther, 1725 PcDescriptors::kOther,
1743 locs()); 1726 locs());
1744 // Newly allocated object is now in the result register (RAX). 1727 // Newly allocated object is now in the result register (RAX).
1745 ASSERT(result == EAX); 1728 ASSERT(result == EAX);
1746 __ movl(right, Address(ESP, 0)); 1729 __ movl(right, Address(ESP, 0));
1747 __ movl(left, Address(ESP, kWordSize)); 1730 __ movl(left, Address(ESP, kWordSize));
1748 1731
1749 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1732 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1750 instance_call()->try_index(),
1751 kDeoptBinaryDoubleOp); 1733 kDeoptBinaryDoubleOp);
1752 1734
1753 // Binary operation of two Smi's produces a Smi not a double. 1735 // Binary operation of two Smi's produces a Smi not a double.
1754 __ movl(temp, left); 1736 __ movl(temp, left);
1755 __ orl(temp, right); 1737 __ orl(temp, right);
1756 __ testl(temp, Immediate(kSmiTagMask)); 1738 __ testl(temp, Immediate(kSmiTagMask));
1757 __ j(ZERO, deopt); 1739 __ j(ZERO, deopt);
1758 1740
1759 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 1741 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
1760 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 1742 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
(...skipping 21 matching lines...) Expand all
1782 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1764 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1783 summary->set_in(0, Location::RequiresRegister()); 1765 summary->set_in(0, Location::RequiresRegister());
1784 summary->set_in(1, Location::RequiresRegister()); 1766 summary->set_in(1, Location::RequiresRegister());
1785 summary->set_temp(0, Location::RequiresRegister()); 1767 summary->set_temp(0, Location::RequiresRegister());
1786 return summary; 1768 return summary;
1787 } 1769 }
1788 1770
1789 1771
1790 void CheckEitherNonSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1772 void CheckEitherNonSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1791 Label* deopt = compiler->AddDeoptStub(instance_call_->deopt_id(), 1773 Label* deopt = compiler->AddDeoptStub(instance_call_->deopt_id(),
1792 instance_call_->try_index(),
1793 kDeoptBinaryDoubleOp); 1774 kDeoptBinaryDoubleOp);
1794 1775
1795 Register temp = locs()->temp(0).reg(); 1776 Register temp = locs()->temp(0).reg();
1796 __ movl(temp, locs()->in(0).reg()); 1777 __ movl(temp, locs()->in(0).reg());
1797 __ orl(temp, locs()->in(1).reg()); 1778 __ orl(temp, locs()->in(1).reg());
1798 __ testl(temp, Immediate(kSmiTagMask)); 1779 __ testl(temp, Immediate(kSmiTagMask));
1799 __ j(ZERO, deopt); 1780 __ j(ZERO, deopt);
1800 } 1781 }
1801 1782
1802 1783
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1878 } 1859 }
1879 1860
1880 1861
1881 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1862 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1882 const intptr_t v_cid = value()->ResultCid(); 1863 const intptr_t v_cid = value()->ResultCid();
1883 1864
1884 const Register value = locs()->in(0).reg(); 1865 const Register value = locs()->in(0).reg();
1885 const XmmRegister result = locs()->out().xmm_reg(); 1866 const XmmRegister result = locs()->out().xmm_reg();
1886 if (v_cid != kDoubleCid) { 1867 if (v_cid != kDoubleCid) {
1887 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1868 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1888 instance_call()->try_index(),
1889 kDeoptBinaryDoubleOp); 1869 kDeoptBinaryDoubleOp);
1890 compiler->LoadDoubleOrSmiToXmm(result, 1870 compiler->LoadDoubleOrSmiToXmm(result,
1891 value, 1871 value,
1892 locs()->temp(0).reg(), 1872 locs()->temp(0).reg(),
1893 deopt); 1873 deopt);
1894 } else { 1874 } else {
1895 __ movsd(result, FieldAddress(value, Double::value_offset())); 1875 __ movsd(result, FieldAddress(value, Double::value_offset()));
1896 } 1876 }
1897 } 1877 }
1898 1878
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1935 return summary; 1915 return summary;
1936 } 1916 }
1937 1917
1938 1918
1939 void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1919 void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1940 Register value = locs()->in(0).reg(); 1920 Register value = locs()->in(0).reg();
1941 ASSERT(value == locs()->out().reg()); 1921 ASSERT(value == locs()->out().reg());
1942 switch (op_kind()) { 1922 switch (op_kind()) {
1943 case Token::kNEGATE: { 1923 case Token::kNEGATE: {
1944 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1924 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1945 instance_call()->try_index(),
1946 kDeoptUnaryOp); 1925 kDeoptUnaryOp);
1947 __ negl(value); 1926 __ negl(value);
1948 __ j(OVERFLOW, deopt); 1927 __ j(OVERFLOW, deopt);
1949 break; 1928 break;
1950 } 1929 }
1951 case Token::kBIT_NOT: 1930 case Token::kBIT_NOT:
1952 __ notl(value); 1931 __ notl(value);
1953 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. 1932 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
1954 break; 1933 break;
1955 default: 1934 default:
(...skipping 22 matching lines...) Expand all
1978 // TODO(srdjan): Implement for more checks. 1957 // TODO(srdjan): Implement for more checks.
1979 ASSERT(ic_data.NumberOfChecks() == 1); 1958 ASSERT(ic_data.NumberOfChecks() == 1);
1980 intptr_t test_class_id; 1959 intptr_t test_class_id;
1981 Function& target = Function::Handle(); 1960 Function& target = Function::Handle();
1982 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); 1961 ic_data.GetOneClassCheckAt(0, &test_class_id, &target);
1983 1962
1984 Register value = locs()->in(0).reg(); 1963 Register value = locs()->in(0).reg();
1985 Register result = locs()->out().reg(); 1964 Register result = locs()->out().reg();
1986 ASSERT(value == result); 1965 ASSERT(value == result);
1987 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1966 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1988 instance_call()->try_index(),
1989 kDeoptUnaryOp); 1967 kDeoptUnaryOp);
1990 if (test_class_id == kDoubleCid) { 1968 if (test_class_id == kDoubleCid) {
1991 Register temp = locs()->temp(0).reg(); 1969 Register temp = locs()->temp(0).reg();
1992 __ testl(value, Immediate(kSmiTagMask)); 1970 __ testl(value, Immediate(kSmiTagMask));
1993 __ j(ZERO, deopt); // Smi. 1971 __ j(ZERO, deopt); // Smi.
1994 __ CompareClassId(value, kDoubleCid, temp); 1972 __ CompareClassId(value, kDoubleCid, temp);
1995 __ j(NOT_EQUAL, deopt); 1973 __ j(NOT_EQUAL, deopt);
1996 // Allocate result object. 1974 // Allocate result object.
1997 const Class& double_class = compiler->double_class(); 1975 const Class& double_class = compiler->double_class();
1998 const Code& stub = 1976 const Code& stub =
(...skipping 29 matching lines...) Expand all
2028 locs->set_out(Location::SameAsFirstInput()); 2006 locs->set_out(Location::SameAsFirstInput());
2029 return locs; 2007 return locs;
2030 } 2008 }
2031 2009
2032 2010
2033 void DoubleToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2011 void DoubleToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2034 Register value = locs()->in(0).reg(); 2012 Register value = locs()->in(0).reg();
2035 Register result = locs()->out().reg(); 2013 Register result = locs()->out().reg();
2036 2014
2037 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 2015 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
2038 instance_call()->try_index(),
2039 kDeoptDoubleToDouble); 2016 kDeoptDoubleToDouble);
2040 Register temp = locs()->temp(0).reg(); 2017 Register temp = locs()->temp(0).reg();
2041 __ testl(value, Immediate(kSmiTagMask)); 2018 __ testl(value, Immediate(kSmiTagMask));
2042 __ j(ZERO, deopt); // Deoptimize if Smi. 2019 __ j(ZERO, deopt); // Deoptimize if Smi.
2043 __ CompareClassId(value, kDoubleCid, temp); 2020 __ CompareClassId(value, kDoubleCid, temp);
2044 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. 2021 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double.
2045 ASSERT(value == result); 2022 ASSERT(value == result);
2046 } 2023 }
2047 2024
2048 2025
2049 LocationSummary* SmiToDoubleComp::MakeLocationSummary() const { 2026 LocationSummary* SmiToDoubleComp::MakeLocationSummary() const {
2050 return MakeCallSummary(); // Calls a stub to allocate result. 2027 return MakeCallSummary(); // Calls a stub to allocate result.
2051 } 2028 }
2052 2029
2053 2030
2054 void SmiToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2031 void SmiToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2055 Register result = locs()->out().reg(); 2032 Register result = locs()->out().reg();
2056 2033
2057 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 2034 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
2058 instance_call()->try_index(),
2059 kDeoptIntegerToDouble); 2035 kDeoptIntegerToDouble);
2060 2036
2061 const Class& double_class = compiler->double_class(); 2037 const Class& double_class = compiler->double_class();
2062 const Code& stub = 2038 const Code& stub =
2063 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); 2039 Code::Handle(StubCode::GetAllocationStubForClass(double_class));
2064 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); 2040 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
2065 2041
2066 // TODO(vegorov): allocate box in the driver loop to avoid spilling. 2042 // TODO(vegorov): allocate box in the driver loop to avoid spilling.
2067 compiler->GenerateCall(instance_call()->token_pos(), 2043 compiler->GenerateCall(instance_call()->token_pos(),
2068 instance_call()->try_index(), 2044 instance_call()->try_index(),
(...skipping 14 matching lines...) Expand all
2083 } 2059 }
2084 2060
2085 2061
2086 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { 2062 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const {
2087 return MakeCallSummary(); 2063 return MakeCallSummary();
2088 } 2064 }
2089 2065
2090 2066
2091 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2067 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2092 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 2068 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
2093 instance_call()->try_index(),
2094 kDeoptPolymorphicInstanceCallTestFail); 2069 kDeoptPolymorphicInstanceCallTestFail);
2095 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { 2070 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) {
2096 __ jmp(deopt); 2071 __ jmp(deopt);
2097 return; 2072 return;
2098 } 2073 }
2099 ASSERT(HasICData()); 2074 ASSERT(HasICData());
2100 ASSERT(ic_data()->num_args_tested() == 1); 2075 ASSERT(ic_data()->num_args_tested() == 1);
2101 if (!with_checks()) { 2076 if (!with_checks()) {
2102 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); 2077 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0));
2103 compiler->GenerateStaticCall(instance_call()->deopt_id(), 2078 compiler->GenerateStaticCall(instance_call()->deopt_id(),
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2186 locs->set_in(0, Location::RegisterLocation(EAX)); 2161 locs->set_in(0, Location::RegisterLocation(EAX));
2187 locs->set_in(1, Location::RegisterLocation(ECX)); 2162 locs->set_in(1, Location::RegisterLocation(ECX));
2188 return locs; 2163 return locs;
2189 } 2164 }
2190 2165
2191 2166
2192 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2167 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2193 // Relational or equality. 2168 // Relational or equality.
2194 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 2169 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2195 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) { 2170 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) {
2196 EmitSmiComparisonOp(compiler, *locs(), kind(), this, 2171 EmitSmiComparisonOp(compiler, *locs(), kind(), this, deopt_id());
2197 deopt_id(), try_index());
2198 return; 2172 return;
2199 } 2173 }
2200 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { 2174 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) {
2201 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, 2175 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, deopt_id());
2202 deopt_id(), try_index());
2203 return; 2176 return;
2204 } 2177 }
2205 if (IsCheckedStrictEquals(*ic_data(), kind())) { 2178 if (IsCheckedStrictEquals(*ic_data(), kind())) {
2206 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, 2179 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this,
2207 deopt_id(), try_index()); 2180 deopt_id());
2208 return; 2181 return;
2209 } 2182 }
2210 2183
2211 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. 2184 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons.
2212 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { 2185 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) {
2213 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(), 2186 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(),
2214 deopt_id(), token_pos(), try_index()); 2187 deopt_id(), token_pos(), try_index());
2215 return; 2188 return;
2216 } 2189 }
2217 // Otherwise polymorphic dispatch? 2190 // Otherwise polymorphic dispatch?
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2279 summary->set_in(0, Location::RequiresRegister()); 2252 summary->set_in(0, Location::RequiresRegister());
2280 summary->set_temp(0, Location::RequiresRegister()); 2253 summary->set_temp(0, Location::RequiresRegister());
2281 return summary; 2254 return summary;
2282 } 2255 }
2283 2256
2284 2257
2285 void CheckClassComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2258 void CheckClassComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2286 Register value = locs()->in(0).reg(); 2259 Register value = locs()->in(0).reg();
2287 Register temp = locs()->temp(0).reg(); 2260 Register temp = locs()->temp(0).reg();
2288 Label* deopt = compiler->AddDeoptStub(deopt_id(), 2261 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2289 try_index(),
2290 kDeoptCheckClass); 2262 kDeoptCheckClass);
2291 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmiCid); 2263 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmiCid);
2292 __ testl(value, Immediate(kSmiTagMask)); 2264 __ testl(value, Immediate(kSmiTagMask));
2293 __ j(ZERO, deopt); 2265 __ j(ZERO, deopt);
2294 __ LoadClassId(temp, value); 2266 __ LoadClassId(temp, value);
2295 Label is_ok; 2267 Label is_ok;
2296 const intptr_t num_checks = ic_data()->NumberOfChecks(); 2268 const intptr_t num_checks = ic_data()->NumberOfChecks();
2297 const bool use_near_jump = num_checks < 5; 2269 const bool use_near_jump = num_checks < 5;
2298 for (intptr_t i = 0; i < num_checks; i++) { 2270 for (intptr_t i = 0; i < num_checks; i++) {
2299 __ cmpl(temp, Immediate(ic_data()->GetReceiverClassIdAt(i))); 2271 __ cmpl(temp, Immediate(ic_data()->GetReceiverClassIdAt(i)));
(...skipping 17 matching lines...) Expand all
2317 LocationSummary* summary = 2289 LocationSummary* summary =
2318 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2290 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2319 summary->set_in(0, Location::RequiresRegister()); 2291 summary->set_in(0, Location::RequiresRegister());
2320 return summary; 2292 return summary;
2321 } 2293 }
2322 2294
2323 2295
2324 void CheckSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2296 void CheckSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2325 Register value = locs()->in(0).reg(); 2297 Register value = locs()->in(0).reg();
2326 Label* deopt = compiler->AddDeoptStub(deopt_id(), 2298 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2327 try_index(),
2328 kDeoptCheckSmi); 2299 kDeoptCheckSmi);
2329 __ testl(value, Immediate(kSmiTagMask)); 2300 __ testl(value, Immediate(kSmiTagMask));
2330 __ j(NOT_ZERO, deopt); 2301 __ j(NOT_ZERO, deopt);
2331 } 2302 }
2332 2303
2333 2304
2334 LocationSummary* CheckArrayBoundComp::MakeLocationSummary() const { 2305 LocationSummary* CheckArrayBoundComp::MakeLocationSummary() const {
2335 return LocationSummary::Make(2, 2306 return LocationSummary::Make(2,
2336 Location::NoLocation(), 2307 Location::NoLocation(),
2337 LocationSummary::kNoCall); 2308 LocationSummary::kNoCall);
2338 } 2309 }
2339 2310
2340 2311
2341 void CheckArrayBoundComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2312 void CheckArrayBoundComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2342 Register receiver = locs()->in(0).reg(); 2313 Register receiver = locs()->in(0).reg();
2343 Register index = locs()->in(1).reg(); 2314 Register index = locs()->in(1).reg();
2344 2315
2345 const DeoptReasonId deopt_reason = 2316 const DeoptReasonId deopt_reason =
2346 (array_type() == kGrowableObjectArrayCid) ? 2317 (array_type() == kGrowableObjectArrayCid) ?
2347 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; 2318 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray;
2348 Label* deopt = compiler->AddDeoptStub(deopt_id(), 2319 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2349 try_index(),
2350 deopt_reason); 2320 deopt_reason);
2351 switch (array_type()) { 2321 switch (array_type()) {
2352 case kArrayCid: 2322 case kArrayCid:
2353 case kImmutableArrayCid: 2323 case kImmutableArrayCid:
2354 __ cmpl(index, FieldAddress(receiver, Array::length_offset())); 2324 __ cmpl(index, FieldAddress(receiver, Array::length_offset()));
2355 break; 2325 break;
2356 case kGrowableObjectArrayCid: 2326 case kGrowableObjectArrayCid:
2357 __ cmpl(index, 2327 __ cmpl(index,
2358 FieldAddress(receiver, GrowableObjectArray::length_offset())); 2328 FieldAddress(receiver, GrowableObjectArray::length_offset()));
2359 break; 2329 break;
2360 } 2330 }
2361 __ j(ABOVE_EQUAL, deopt); 2331 __ j(ABOVE_EQUAL, deopt);
2362 } 2332 }
2363 2333
2364 2334
2365 } // namespace dart 2335 } // namespace dart
2366 2336
2367 #undef __ 2337 #undef __
2368 2338
2369 #endif // defined TARGET_ARCH_X64 2339 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.h ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698