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

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

Issue 10867050: Separate branch on strict compare into a new IL instruction. (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
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 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 token_pos,
453 intptr_t try_index) { 452 intptr_t try_index) {
454 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 453 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
455 Register left = locs.in(0).reg(); 454 Register left = locs.in(0).reg();
456 Register right = locs.in(1).reg(); 455 Register right = locs.in(1).reg();
457 Register temp = locs.temp(0).reg(); 456 Register temp = locs.temp(0).reg();
458 Label* deopt = compiler->AddDeoptStub(deopt_id, 457 Label* deopt = compiler->AddDeoptStub(deopt_id,
459 try_index, 458 try_index,
460 kDeoptEquality); 459 kDeoptEquality);
461 __ testq(left, Immediate(kSmiTagMask)); 460 __ testq(left, Immediate(kSmiTagMask));
462 __ j(ZERO, deopt); 461 __ j(ZERO, deopt);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 deopt_id, token_pos, try_index); 543 deopt_id, token_pos, try_index);
545 __ Bind(&done); 544 __ Bind(&done);
546 } 545 }
547 546
548 547
549 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 548 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
550 const LocationSummary& locs, 549 const LocationSummary& locs,
551 Token::Kind kind, 550 Token::Kind kind,
552 BranchInstr* branch, 551 BranchInstr* branch,
553 intptr_t deopt_id, 552 intptr_t deopt_id,
554 intptr_t token_pos,
555 intptr_t try_index) { 553 intptr_t try_index) {
556 Register left = locs.in(0).reg(); 554 Register left = locs.in(0).reg();
557 Register right = locs.in(1).reg(); 555 Register right = locs.in(1).reg();
558 const bool left_is_smi = (branch == NULL) ? 556 const bool left_is_smi = (branch == NULL) ?
559 false : (branch->left()->ResultCid() == kSmiCid); 557 false : (branch->left()->ResultCid() == kSmiCid);
560 const bool right_is_smi = (branch == NULL) ? 558 const bool right_is_smi = (branch == NULL) ?
561 false : (branch->right()->ResultCid() == kSmiCid); 559 false : (branch->right()->ResultCid() == kSmiCid);
562 if (!left_is_smi || !right_is_smi) { 560 if (!left_is_smi || !right_is_smi) {
563 Register temp = locs.temp(0).reg(); 561 Register temp = locs.temp(0).reg();
564 Label* deopt = compiler->AddDeoptStub(deopt_id, 562 Label* deopt = compiler->AddDeoptStub(deopt_id,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 return OVERFLOW; 599 return OVERFLOW;
602 } 600 }
603 } 601 }
604 602
605 603
606 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 604 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
607 const LocationSummary& locs, 605 const LocationSummary& locs,
608 Token::Kind kind, 606 Token::Kind kind,
609 BranchInstr* branch, 607 BranchInstr* branch,
610 intptr_t deopt_id, 608 intptr_t deopt_id,
611 intptr_t token_pos,
612 intptr_t try_index) { 609 intptr_t try_index) {
613 Register left = locs.in(0).reg(); 610 Register left = locs.in(0).reg();
614 Register right = locs.in(1).reg(); 611 Register right = locs.in(1).reg();
615 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. 612 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs.
616 Register temp = locs.temp(0).reg(); 613 Register temp = locs.temp(0).reg();
617 Label* deopt = compiler->AddDeoptStub(deopt_id, 614 Label* deopt = compiler->AddDeoptStub(deopt_id,
618 try_index, 615 try_index,
619 kDeoptDoubleComparison); 616 kDeoptDoubleComparison);
620 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 617 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
621 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 618 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
622 619
623 Condition true_condition = TokenKindToDoubleCondition(kind); 620 Condition true_condition = TokenKindToDoubleCondition(kind);
624 if (branch != NULL) { 621 if (branch != NULL) {
625 compiler->EmitDoubleCompareBranch( 622 compiler->EmitDoubleCompareBranch(
626 true_condition, XMM0, XMM1, branch); 623 true_condition, XMM0, XMM1, branch);
627 } else { 624 } else {
628 compiler->EmitDoubleCompareBool( 625 compiler->EmitDoubleCompareBool(
629 true_condition, XMM0, XMM1, locs.out().reg()); 626 true_condition, XMM0, XMM1, locs.out().reg());
630 } 627 }
631 } 628 }
632 629
633 630
634 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 631 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
635 if (receiver_class_id() == kSmiCid) { 632 if (receiver_class_id() == kSmiCid) {
636 // Deoptimizes if both arguments not Smi. 633 // Deoptimizes if both arguments not Smi.
637 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 634 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch.
638 deopt_id(), token_pos(), try_index()); 635 deopt_id(), try_index());
639 return; 636 return;
640 } 637 }
641 if (receiver_class_id() == kDoubleCid) { 638 if (receiver_class_id() == kDoubleCid) {
642 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. 639 // Deoptimizes if both arguments are Smi, or if none is Double or Smi.
643 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 640 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch.
644 deopt_id(), token_pos(), try_index()); 641 deopt_id(), try_index());
645 return; 642 return;
646 } 643 }
647 const bool is_checked_strict_equal = 644 const bool is_checked_strict_equal =
648 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); 645 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
649 if (is_checked_strict_equal) { 646 if (is_checked_strict_equal) {
650 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, 647 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL,
651 deopt_id(), token_pos(), try_index()); 648 deopt_id(), try_index());
652 return; 649 return;
653 } 650 }
654 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 651 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
655 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(), 652 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(),
656 deopt_id(), token_pos(), try_index()); 653 deopt_id(), token_pos(), try_index());
657 } else { 654 } else {
658 Register left = locs()->in(0).reg(); 655 Register left = locs()->in(0).reg();
659 Register right = locs()->in(1).reg(); 656 Register right = locs()->in(1).reg();
660 __ pushq(left); 657 __ pushq(left);
661 __ pushq(right); 658 __ pushq(right);
(...skipping 27 matching lines...) Expand all
689 locs->set_in(0, Location::RegisterLocation(RAX)); 686 locs->set_in(0, Location::RegisterLocation(RAX));
690 locs->set_in(1, Location::RegisterLocation(RCX)); 687 locs->set_in(1, Location::RegisterLocation(RCX));
691 locs->set_out(Location::RegisterLocation(RAX)); 688 locs->set_out(Location::RegisterLocation(RAX));
692 return locs; 689 return locs;
693 } 690 }
694 691
695 692
696 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 693 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
697 if (operands_class_id() == kSmiCid) { 694 if (operands_class_id() == kSmiCid) {
698 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, 695 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL,
699 deopt_id(), token_pos(), try_index()); 696 deopt_id(), try_index());
700 return; 697 return;
701 } 698 }
702 if (operands_class_id() == kDoubleCid) { 699 if (operands_class_id() == kDoubleCid) {
703 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, 700 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL,
704 deopt_id(), token_pos(), try_index()); 701 deopt_id(), try_index());
705 return; 702 return;
706 } 703 }
707 704
708 // Push arguments for the call. 705 // Push arguments for the call.
709 // TODO(fschneider): Split this instruction into different types to avoid 706 // TODO(fschneider): Split this instruction into different types to avoid
710 // explicitly pushing arguments to the call here. 707 // explicitly pushing arguments to the call here.
711 Register left = locs()->in(0).reg(); 708 Register left = locs()->in(0).reg();
712 Register right = locs()->in(1).reg(); 709 Register right = locs()->in(1).reg();
713 __ pushq(left); 710 __ pushq(left);
714 __ pushq(right); 711 __ pushq(right);
(...skipping 1313 matching lines...) Expand 10 before | Expand all | Expand 10 after
2028 2025
2029 static bool IsCheckedStrictEquals(const ICData& ic_data, Token::Kind kind) { 2026 static bool IsCheckedStrictEquals(const ICData& ic_data, Token::Kind kind) {
2030 if ((kind == Token::kEQ) || (kind == Token::kNE)) { 2027 if ((kind == Token::kEQ) || (kind == Token::kNE)) {
2031 return ic_data.AllTargetsHaveSameOwner(kInstanceCid); 2028 return ic_data.AllTargetsHaveSameOwner(kInstanceCid);
2032 } 2029 }
2033 return false; 2030 return false;
2034 } 2031 }
2035 2032
2036 2033
2037 LocationSummary* BranchInstr::MakeLocationSummary() const { 2034 LocationSummary* BranchInstr::MakeLocationSummary() const {
2038 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) {
2039 const int kNumInputs = 2;
2040 const int kNumTemps = 0;
2041 LocationSummary* locs =
2042 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2043 locs->set_in(0, Location::RequiresRegister());
2044 locs->set_in(1, Location::RequiresRegister());
2045 return locs;
2046 }
2047 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 2035 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2048 if (ICDataWithBothClassIds(*ic_data(), kSmiCid) || 2036 if (ICDataWithBothClassIds(*ic_data(), kSmiCid) ||
2049 ICDataWithBothClassIds(*ic_data(), kDoubleCid) || 2037 ICDataWithBothClassIds(*ic_data(), kDoubleCid) ||
2050 IsCheckedStrictEquals(*ic_data(), kind())) { 2038 IsCheckedStrictEquals(*ic_data(), kind())) {
2051 const intptr_t kNumInputs = 2; 2039 const intptr_t kNumInputs = 2;
2052 const intptr_t kNumTemps = 1; 2040 const intptr_t kNumTemps = 1;
2053 LocationSummary* summary = 2041 LocationSummary* summary =
2054 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2042 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2055 summary->set_in(0, Location::RequiresRegister()); 2043 summary->set_in(0, Location::RequiresRegister());
2056 summary->set_in(1, Location::RequiresRegister()); 2044 summary->set_in(1, Location::RequiresRegister());
(...skipping 17 matching lines...) Expand all
2074 const intptr_t kNumTemps = 0; 2062 const intptr_t kNumTemps = 0;
2075 LocationSummary* locs = 2063 LocationSummary* locs =
2076 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 2064 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
2077 locs->set_in(0, Location::RegisterLocation(RAX)); 2065 locs->set_in(0, Location::RegisterLocation(RAX));
2078 locs->set_in(1, Location::RegisterLocation(RCX)); 2066 locs->set_in(1, Location::RegisterLocation(RCX));
2079 return locs; 2067 return locs;
2080 } 2068 }
2081 2069
2082 2070
2083 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2071 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2084 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) {
2085 Register left = locs()->in(0).reg();
2086 Register right = locs()->in(1).reg();
2087 __ cmpq(left, right);
2088 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
2089 EmitBranchOnCondition(compiler, cond);
2090 return;
2091 }
2092 // Relational or equality. 2072 // Relational or equality.
2093 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 2073 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2094 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) { 2074 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) {
2095 EmitSmiComparisonOp(compiler, *locs(), kind(), this, 2075 EmitSmiComparisonOp(compiler, *locs(), kind(), this,
2096 deopt_id(), token_pos(), try_index()); 2076 deopt_id(), try_index());
2097 return; 2077 return;
2098 } 2078 }
2099 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { 2079 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) {
2100 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, 2080 EmitDoubleComparisonOp(compiler, *locs(), kind(), this,
2101 deopt_id(), token_pos(), try_index()); 2081 deopt_id(), try_index());
2102 return; 2082 return;
2103 } 2083 }
2104 if (IsCheckedStrictEquals(*ic_data(), kind())) { 2084 if (IsCheckedStrictEquals(*ic_data(), kind())) {
2105 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, 2085 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this,
2106 deopt_id(), token_pos(), try_index()); 2086 deopt_id(), try_index());
2107 return; 2087 return;
2108 } 2088 }
2109 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. 2089 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons.
2110 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { 2090 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) {
2111 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(), 2091 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(),
2112 deopt_id(), token_pos(), try_index()); 2092 deopt_id(), token_pos(), try_index());
2113 return; 2093 return;
2114 } 2094 }
2115 // Otherwise polymorphic dispatch? 2095 // Otherwise polymorphic dispatch?
2116 } 2096 }
(...skipping 25 matching lines...) Expand all
2142 Array::ZoneHandle(), // No optional args. 2122 Array::ZoneHandle(), // No optional args.
2143 kNumArgsChecked, 2123 kNumArgsChecked,
2144 locs()); 2124 locs());
2145 } 2125 }
2146 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; 2126 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
2147 __ CompareObject(RAX, compiler->bool_true()); 2127 __ CompareObject(RAX, compiler->bool_true());
2148 EmitBranchOnCondition(compiler, branch_condition); 2128 EmitBranchOnCondition(compiler, branch_condition);
2149 } 2129 }
2150 2130
2151 2131
2132 LocationSummary* StrictCompareAndBranchInstr::MakeLocationSummary() const {
2133 const int kNumInputs = 2;
2134 const int kNumTemps = 0;
2135 LocationSummary* locs =
2136 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2137 locs->set_in(0, Location::RequiresRegister());
2138 locs->set_in(1, Location::RequiresRegister());
2139 return locs;
2140 }
2141
2142
2143 void StrictCompareAndBranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2144 Register left = locs()->in(0).reg();
2145 Register right = locs()->in(1).reg();
2146 __ cmpq(left, right);
2147 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
2148 EmitBranchOnCondition(compiler, cond);
2149 return;
2150 }
2151
2152
2152 LocationSummary* CheckClassComp::MakeLocationSummary() const { 2153 LocationSummary* CheckClassComp::MakeLocationSummary() const {
2153 const intptr_t kNumInputs = 1; 2154 const intptr_t kNumInputs = 1;
2154 const intptr_t kNumTemps = 1; 2155 const intptr_t kNumTemps = 1;
2155 LocationSummary* summary = 2156 LocationSummary* summary =
2156 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2157 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2157 summary->set_in(0, Location::RequiresRegister()); 2158 summary->set_in(0, Location::RequiresRegister());
2158 summary->set_temp(0, Location::RequiresRegister()); 2159 summary->set_temp(0, Location::RequiresRegister());
2159 return summary; 2160 return summary;
2160 } 2161 }
2161 2162
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2214 __ testq(value, Immediate(kSmiTagMask)); 2215 __ testq(value, Immediate(kSmiTagMask));
2215 __ j(NOT_ZERO, deopt); 2216 __ j(NOT_ZERO, deopt);
2216 } 2217 }
2217 2218
2218 2219
2219 } // namespace dart 2220 } // namespace dart
2220 2221
2221 #undef __ 2222 #undef __
2222 2223
2223 #endif // defined TARGET_ARCH_X64 2224 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698