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

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

Issue 10887009: Refactor branch instructions to enable further optimizations. (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') | runtime/vm/locations.h » ('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_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 536 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 547
548 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 548 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
549 const LocationSummary& locs, 549 const LocationSummary& locs,
550 Token::Kind kind, 550 Token::Kind kind,
551 BranchInstr* branch, 551 BranchInstr* branch,
552 intptr_t deopt_id, 552 intptr_t deopt_id,
553 intptr_t try_index) { 553 intptr_t try_index) {
554 Register left = locs.in(0).reg(); 554 Register left = locs.in(0).reg();
555 Register right = locs.in(1).reg(); 555 Register right = locs.in(1).reg();
556 const bool left_is_smi = (branch == NULL) ? 556 const bool left_is_smi = (branch == NULL) ?
557 false : (branch->left()->ResultCid() == kSmiCid); 557 false : (branch->computation()->left()->ResultCid() == kSmiCid);
558 const bool right_is_smi = (branch == NULL) ? 558 const bool right_is_smi = (branch == NULL) ?
559 false : (branch->right()->ResultCid() == kSmiCid); 559 false : (branch->computation()->right()->ResultCid() == kSmiCid);
560 // TODO(fschneider): Move smi smi checks outside this instruction.
560 if (!left_is_smi || !right_is_smi) { 561 if (!left_is_smi || !right_is_smi) {
561 Register temp = locs.temp(0).reg(); 562 Register temp = locs.temp(0).reg();
562 Label* deopt = compiler->AddDeoptStub(deopt_id, 563 Label* deopt = compiler->AddDeoptStub(deopt_id,
563 try_index, 564 try_index,
564 kDeoptSmiCompareSmi); 565 kDeoptSmiCompareSmi);
565 __ movq(temp, left); 566 __ movq(temp, left);
566 __ orq(temp, right); 567 __ orq(temp, right);
567 __ testq(temp, Immediate(kSmiTagMask)); 568 __ testq(temp, Immediate(kSmiTagMask));
568 __ j(NOT_ZERO, deopt); 569 __ j(NOT_ZERO, deopt);
569 } 570 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 compiler->EmitDoubleCompareBranch( 623 compiler->EmitDoubleCompareBranch(
623 true_condition, XMM0, XMM1, branch); 624 true_condition, XMM0, XMM1, branch);
624 } else { 625 } else {
625 compiler->EmitDoubleCompareBool( 626 compiler->EmitDoubleCompareBool(
626 true_condition, XMM0, XMM1, locs.out().reg()); 627 true_condition, XMM0, XMM1, locs.out().reg());
627 } 628 }
628 } 629 }
629 630
630 631
631 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 632 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
633 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
632 if (receiver_class_id() == kSmiCid) { 634 if (receiver_class_id() == kSmiCid) {
633 // Deoptimizes if both arguments not Smi. 635 // Deoptimizes if both arguments not Smi.
634 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 636 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch.
635 deopt_id(), try_index()); 637 deopt_id(), try_index());
636 return; 638 return;
637 } 639 }
638 if (receiver_class_id() == kDoubleCid) { 640 if (receiver_class_id() == kDoubleCid) {
639 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. 641 // Deoptimizes if both arguments are Smi, or if none is Double or Smi.
640 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 642 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch.
641 deopt_id(), try_index()); 643 deopt_id(), try_index());
642 return; 644 return;
643 } 645 }
644 const bool is_checked_strict_equal = 646 const bool is_checked_strict_equal =
645 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); 647 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
646 if (is_checked_strict_equal) { 648 if (is_checked_strict_equal) {
647 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, 649 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL,
648 deopt_id(), try_index()); 650 deopt_id(), try_index());
649 return; 651 return;
650 } 652 }
651 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 653 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
652 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(), 654 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(),
653 deopt_id(), token_pos(), try_index()); 655 deopt_id(), token_pos(), try_index());
654 } else { 656 return;
655 Register left = locs()->in(0).reg();
656 Register right = locs()->in(1).reg();
657 __ pushq(left);
658 __ pushq(right);
659 EmitEqualityAsInstanceCall(compiler,
660 deopt_id(),
661 token_pos(),
662 try_index(),
663 kind(),
664 locs());
665 ASSERT(locs()->out().reg() == RAX);
666 } 657 }
658 Register left = locs()->in(0).reg();
659 Register right = locs()->in(1).reg();
660 __ pushq(left);
661 __ pushq(right);
662 EmitEqualityAsInstanceCall(compiler,
663 deopt_id(),
664 token_pos(),
665 try_index(),
666 kind(),
667 locs());
668 ASSERT(locs()->out().reg() == RAX);
669 }
670
671
672 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler,
673 BranchInstr* branch) {
674 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
675 if (receiver_class_id() == kSmiCid) {
676 // Deoptimizes if both arguments not Smi.
677 EmitSmiComparisonOp(compiler, *locs(), kind(), branch,
678 deopt_id(), try_index());
679 return;
680 }
681 if (receiver_class_id() == kDoubleCid) {
682 // Deoptimizes if both arguments are Smi, or if none is Double or Smi.
683 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch,
684 deopt_id(), try_index());
685 return;
686 }
687 const bool is_checked_strict_equal =
688 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
689 if (is_checked_strict_equal) {
690 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
691 deopt_id(), try_index());
692 return;
693 }
694 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
695 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(),
696 deopt_id(), token_pos(), try_index());
697 return;
698 }
699 Register left = locs()->in(0).reg();
700 Register right = locs()->in(1).reg();
701 __ pushq(left);
702 __ pushq(right);
703 EmitEqualityAsInstanceCall(compiler,
704 deopt_id(),
705 token_pos(),
706 try_index(),
707 Token::kEQ, // kNE reverse occurs at branch.
708 locs());
709 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
710 __ CompareObject(RAX, compiler->bool_true());
711 branch->EmitBranchOnCondition(compiler, branch_condition);
667 } 712 }
668 713
669 714
670 LocationSummary* RelationalOpComp::MakeLocationSummary() const { 715 LocationSummary* RelationalOpComp::MakeLocationSummary() const {
671 const intptr_t kNumInputs = 2; 716 const intptr_t kNumInputs = 2;
672 if (operands_class_id() == kSmiCid || operands_class_id() == kDoubleCid) { 717 if (operands_class_id() == kSmiCid || operands_class_id() == kDoubleCid) {
673 const intptr_t kNumTemps = 1; 718 const intptr_t kNumTemps = 1;
674 LocationSummary* summary = 719 LocationSummary* summary =
675 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 720 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
676 summary->set_in(0, Location::RequiresRegister()); 721 summary->set_in(0, Location::RequiresRegister());
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 const intptr_t kNumArguments = 2; 771 const intptr_t kNumArguments = 2;
727 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), 772 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
728 RDI, // Class id register. 773 RDI, // Class id register.
729 kNumArguments, 774 kNumArguments,
730 Array::Handle(), // No named arguments. 775 Array::Handle(), // No named arguments.
731 deopt, // Deoptimize target. 776 deopt, // Deoptimize target.
732 deopt_id(), 777 deopt_id(),
733 token_pos(), 778 token_pos(),
734 try_index(), 779 try_index(),
735 locs()); 780 locs());
736 ASSERT(locs()->out().reg() == RAX);
737 return; 781 return;
738 } 782 }
739 const String& function_name = 783 const String& function_name =
740 String::ZoneHandle(Symbols::New(Token::Str(kind()))); 784 String::ZoneHandle(Symbols::New(Token::Str(kind())));
741 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 785 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
742 deopt_id(), 786 deopt_id(),
743 token_pos(), 787 token_pos(),
744 try_index()); 788 try_index());
745 const intptr_t kNumArguments = 2; 789 const intptr_t kNumArguments = 2;
746 const intptr_t kNumArgsChecked = 2; // Type-feedback. 790 const intptr_t kNumArgsChecked = 2; // Type-feedback.
747 compiler->GenerateInstanceCall(deopt_id(), 791 compiler->GenerateInstanceCall(deopt_id(),
748 token_pos(), 792 token_pos(),
749 try_index(), 793 try_index(),
750 function_name, 794 function_name,
751 kNumArguments, 795 kNumArguments,
752 Array::ZoneHandle(), // No optional arguments. 796 Array::ZoneHandle(), // No optional arguments.
753 kNumArgsChecked, 797 kNumArgsChecked,
754 locs()); 798 locs());
755 ASSERT(locs()->out().reg() == RAX); 799 }
800
801
802 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler,
803 BranchInstr* branch) {
804 if (operands_class_id() == kSmiCid) {
805 EmitSmiComparisonOp(compiler, *locs(), kind(), branch,
806 deopt_id(), try_index());
807 return;
808 }
809 if (operands_class_id() == kDoubleCid) {
810 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch,
811 deopt_id(), try_index());
812 return;
813 }
814 EmitNativeCode(compiler);
815 __ CompareObject(RAX, compiler->bool_true());
816 branch->EmitBranchOnCondition(compiler, EQUAL);
756 } 817 }
757 818
758 819
759 LocationSummary* NativeCallComp::MakeLocationSummary() const { 820 LocationSummary* NativeCallComp::MakeLocationSummary() const {
760 const intptr_t kNumInputs = 0; 821 const intptr_t kNumInputs = 0;
761 const intptr_t kNumTemps = 3; 822 const intptr_t kNumTemps = 3;
762 LocationSummary* locs = 823 LocationSummary* locs =
763 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 824 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
764 locs->set_temp(0, Location::RegisterLocation(RAX)); 825 locs->set_temp(0, Location::RegisterLocation(RAX));
765 locs->set_temp(1, Location::RegisterLocation(RBX)); 826 locs->set_temp(1, Location::RegisterLocation(RBX));
(...skipping 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 instance_call()->ArgumentCount(), 2195 instance_call()->ArgumentCount(),
2135 instance_call()->argument_names(), 2196 instance_call()->argument_names(),
2136 deopt, 2197 deopt,
2137 instance_call()->deopt_id(), 2198 instance_call()->deopt_id(),
2138 instance_call()->token_pos(), 2199 instance_call()->token_pos(),
2139 instance_call()->try_index(), 2200 instance_call()->try_index(),
2140 locs()); 2201 locs());
2141 } 2202 }
2142 2203
2143 2204
2144 // TODO(srdjan): Move to shared.
2145 static bool ICDataWithBothClassIds(const ICData& ic_data, intptr_t class_id) {
2146 if (ic_data.num_args_tested() != 2) return false;
2147 if (ic_data.NumberOfChecks() != 1) return false;
2148 Function& target = Function::Handle();
2149 GrowableArray<intptr_t> class_ids;
2150 ic_data.GetCheckAt(0, &class_ids, &target);
2151 return (class_ids[0] == class_id) && (class_ids[1] == class_id);
2152 }
2153
2154
2155 static bool IsCheckedStrictEquals(const ICData& ic_data, Token::Kind kind) {
2156 if ((kind == Token::kEQ) || (kind == Token::kNE)) {
2157 return ic_data.AllTargetsHaveSameOwner(kInstanceCid);
2158 }
2159 return false;
2160 }
2161
2162
2163 LocationSummary* BranchInstr::MakeLocationSummary() const {
2164 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2165 if (ICDataWithBothClassIds(*ic_data(), kSmiCid) ||
2166 ICDataWithBothClassIds(*ic_data(), kDoubleCid) ||
2167 IsCheckedStrictEquals(*ic_data(), kind())) {
2168 const intptr_t kNumInputs = 2;
2169 const intptr_t kNumTemps = 1;
2170 LocationSummary* summary =
2171 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2172 summary->set_in(0, Location::RequiresRegister());
2173 summary->set_in(1, Location::RequiresRegister());
2174 summary->set_temp(0, Location::RequiresRegister());
2175 return summary;
2176 }
2177 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) {
2178 const intptr_t kNumInputs = 2;
2179 const intptr_t kNumTemps = 1;
2180 LocationSummary* locs =
2181 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
2182 locs->set_in(0, Location::RegisterLocation(RAX));
2183 locs->set_in(1, Location::RegisterLocation(RCX));
2184 locs->set_temp(0, Location::RegisterLocation(RDX));
2185 return locs;
2186 }
2187 // Otherwise polymorphic dispatch.
2188 }
2189 // Call.
2190 const intptr_t kNumInputs = 2;
2191 const intptr_t kNumTemps = 0;
2192 LocationSummary* locs =
2193 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
2194 locs->set_in(0, Location::RegisterLocation(RAX));
2195 locs->set_in(1, Location::RegisterLocation(RCX));
2196 return locs;
2197 }
2198
2199
2200 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2205 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2201 // Relational or equality. 2206 computation()->EmitBranchCode(compiler, this);
2202 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2203 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) {
2204 EmitSmiComparisonOp(compiler, *locs(), kind(), this,
2205 deopt_id(), try_index());
2206 return;
2207 }
2208 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) {
2209 EmitDoubleComparisonOp(compiler, *locs(), kind(), this,
2210 deopt_id(), try_index());
2211 return;
2212 }
2213 if (IsCheckedStrictEquals(*ic_data(), kind())) {
2214 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this,
2215 deopt_id(), try_index());
2216 return;
2217 }
2218 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons.
2219 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) {
2220 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(),
2221 deopt_id(), token_pos(), try_index());
2222 return;
2223 }
2224 // Otherwise polymorphic dispatch?
2225 }
2226 Register left = locs()->in(0).reg();
2227 Register right = locs()->in(1).reg();
2228 __ pushq(left);
2229 __ pushq(right);
2230 if ((kind() == Token::kNE) || (kind() == Token::kEQ)) {
2231 EmitEqualityAsInstanceCall(compiler,
2232 deopt_id(),
2233 token_pos(),
2234 try_index(),
2235 Token::kEQ, // kNE reverse occurs at branch.
2236 locs());
2237 } else {
2238 const String& function_name =
2239 String::ZoneHandle(Symbols::New(Token::Str(kind())));
2240 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
2241 deopt_id(),
2242 token_pos(),
2243 try_index());
2244 const intptr_t kNumArguments = 2;
2245 const intptr_t kNumArgsChecked = 2; // Type-feedback.
2246 compiler->GenerateInstanceCall(deopt_id(),
2247 token_pos(),
2248 try_index(),
2249 function_name,
2250 kNumArguments,
2251 Array::ZoneHandle(), // No optional args.
2252 kNumArgsChecked,
2253 locs());
2254 }
2255 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
2256 __ CompareObject(RAX, compiler->bool_true());
2257 EmitBranchOnCondition(compiler, branch_condition);
2258 }
2259
2260
2261 LocationSummary* StrictCompareAndBranchInstr::MakeLocationSummary() const {
2262 const int kNumInputs = 2;
2263 const int kNumTemps = 0;
2264 LocationSummary* locs =
2265 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2266 locs->set_in(0, Location::RequiresRegister());
2267 locs->set_in(1, Location::RequiresRegister());
2268 return locs;
2269 }
2270
2271
2272 void StrictCompareAndBranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2273 Register left = locs()->in(0).reg();
2274 Register right = locs()->in(1).reg();
2275 __ cmpq(left, right);
2276 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
2277 EmitBranchOnCondition(compiler, cond);
2278 } 2207 }
2279 2208
2280 2209
2281 LocationSummary* CheckClassComp::MakeLocationSummary() const { 2210 LocationSummary* CheckClassComp::MakeLocationSummary() const {
2282 const intptr_t kNumInputs = 1; 2211 const intptr_t kNumInputs = 1;
2283 const intptr_t kNumTemps = 1; 2212 const intptr_t kNumTemps = 1;
2284 LocationSummary* summary = 2213 LocationSummary* summary =
2285 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2214 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2286 summary->set_in(0, Location::RequiresRegister()); 2215 summary->set_in(0, Location::RequiresRegister());
2287 summary->set_temp(0, Location::RequiresRegister()); 2216 summary->set_temp(0, Location::RequiresRegister());
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2367 } 2296 }
2368 __ j(ABOVE_EQUAL, deopt); 2297 __ j(ABOVE_EQUAL, deopt);
2369 } 2298 }
2370 2299
2371 2300
2372 } // namespace dart 2301 } // namespace dart
2373 2302
2374 #undef __ 2303 #undef __
2375 2304
2376 #endif // defined TARGET_ARCH_X64 2305 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/locations.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698