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

Side by Side Diff: runtime/vm/intermediate_language_ia32.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.cc ('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 526 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 537
538 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 538 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
539 const LocationSummary& locs, 539 const LocationSummary& locs,
540 Token::Kind kind, 540 Token::Kind kind,
541 BranchInstr* branch, 541 BranchInstr* branch,
542 intptr_t deopt_id, 542 intptr_t deopt_id,
543 intptr_t try_index) { 543 intptr_t try_index) {
544 Register left = locs.in(0).reg(); 544 Register left = locs.in(0).reg();
545 Register right = locs.in(1).reg(); 545 Register right = locs.in(1).reg();
546 const bool left_is_smi = (branch == NULL) ? 546 const bool left_is_smi = (branch == NULL) ?
547 false : (branch->left()->ResultCid() == kSmiCid); 547 false : (branch->computation()->left()->ResultCid() == kSmiCid);
548 const bool right_is_smi = (branch == NULL) ? 548 const bool right_is_smi = (branch == NULL) ?
549 false : (branch->right()->ResultCid() == kSmiCid); 549 false : (branch->computation()->right()->ResultCid() == kSmiCid);
550 // TODO(fschneider): Move smi smi checks outside this instruction.
550 if (!left_is_smi || !right_is_smi) { 551 if (!left_is_smi || !right_is_smi) {
551 Register temp = locs.temp(0).reg(); 552 Register temp = locs.temp(0).reg();
552 Label* deopt = compiler->AddDeoptStub(deopt_id, 553 Label* deopt = compiler->AddDeoptStub(deopt_id,
553 try_index, 554 try_index,
554 kDeoptSmiCompareSmi); 555 kDeoptSmiCompareSmi);
555 __ movl(temp, left); 556 __ movl(temp, left);
556 __ orl(temp, right); 557 __ orl(temp, right);
557 __ testl(temp, Immediate(kSmiTagMask)); 558 __ testl(temp, Immediate(kSmiTagMask));
558 __ j(NOT_ZERO, deopt); 559 __ j(NOT_ZERO, deopt);
559 } 560 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 compiler->EmitDoubleCompareBranch( 613 compiler->EmitDoubleCompareBranch(
613 true_condition, XMM0, XMM1, branch); 614 true_condition, XMM0, XMM1, branch);
614 } else { 615 } else {
615 compiler->EmitDoubleCompareBool( 616 compiler->EmitDoubleCompareBool(
616 true_condition, XMM0, XMM1, locs.out().reg()); 617 true_condition, XMM0, XMM1, locs.out().reg());
617 } 618 }
618 } 619 }
619 620
620 621
621 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 622 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
623 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
622 if (receiver_class_id() == kSmiCid) { 624 if (receiver_class_id() == kSmiCid) {
623 // Deoptimizes if both arguments not Smi. 625 // Deoptimizes if both arguments not Smi.
624 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 626 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch.
625 deopt_id(), try_index()); 627 deopt_id(), try_index());
626 return; 628 return;
627 } 629 }
628 if (receiver_class_id() == kDoubleCid) { 630 if (receiver_class_id() == kDoubleCid) {
629 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. 631 // Deoptimizes if both arguments are Smi, or if none is Double or Smi.
630 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 632 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch.
631 deopt_id(), try_index()); 633 deopt_id(), try_index());
632 return; 634 return;
633 } 635 }
634 const bool is_checked_strict_equal = 636 const bool is_checked_strict_equal =
635 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); 637 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
636 if (is_checked_strict_equal) { 638 if (is_checked_strict_equal) {
637 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, 639 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL,
638 deopt_id(), try_index()); 640 deopt_id(), try_index());
639 return; 641 return;
640 } 642 }
641 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 643 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
642 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(), 644 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(),
643 deopt_id(), token_pos(), try_index()); 645 deopt_id(), token_pos(), try_index());
644 } else { 646 return;
645 Register left = locs()->in(0).reg();
646 Register right = locs()->in(1).reg();
647 __ pushl(left);
648 __ pushl(right);
649 EmitEqualityAsInstanceCall(compiler,
650 deopt_id(),
651 token_pos(),
652 try_index(),
653 kind(),
654 locs());
655 ASSERT(locs()->out().reg() == EAX);
656 } 647 }
648 Register left = locs()->in(0).reg();
649 Register right = locs()->in(1).reg();
650 __ pushl(left);
651 __ pushl(right);
652 EmitEqualityAsInstanceCall(compiler,
653 deopt_id(),
654 token_pos(),
655 try_index(),
656 kind(),
657 locs());
658 ASSERT(locs()->out().reg() == EAX);
659 }
660
661
662 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler,
663 BranchInstr* branch) {
664 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
665 if (receiver_class_id() == kSmiCid) {
666 // Deoptimizes if both arguments not Smi.
667 EmitSmiComparisonOp(compiler, *locs(), kind(), branch,
668 deopt_id(), try_index());
669 return;
670 }
671 if (receiver_class_id() == kDoubleCid) {
672 // Deoptimizes if both arguments are Smi, or if none is Double or Smi.
673 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch,
674 deopt_id(), try_index());
675 return;
676 }
677 const bool is_checked_strict_equal =
678 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
679 if (is_checked_strict_equal) {
680 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
681 deopt_id(), try_index());
682 return;
683 }
684 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
685 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(),
686 deopt_id(), token_pos(), try_index());
687 return;
688 }
689 Register left = locs()->in(0).reg();
690 Register right = locs()->in(1).reg();
691 __ pushl(left);
692 __ pushl(right);
693 EmitEqualityAsInstanceCall(compiler,
694 deopt_id(),
695 token_pos(),
696 try_index(),
697 Token::kEQ, // kNE reverse occurs at branch.
698 locs());
699 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
700 __ CompareObject(EAX, compiler->bool_true());
701 branch->EmitBranchOnCondition(compiler, branch_condition);
657 } 702 }
658 703
659 704
660 LocationSummary* RelationalOpComp::MakeLocationSummary() const { 705 LocationSummary* RelationalOpComp::MakeLocationSummary() const {
661 const intptr_t kNumInputs = 2; 706 const intptr_t kNumInputs = 2;
662 if ((operands_class_id() == kSmiCid) || (operands_class_id() == kDoubleCid)) { 707 if ((operands_class_id() == kSmiCid) || (operands_class_id() == kDoubleCid)) {
663 const intptr_t kNumTemps = 1; 708 const intptr_t kNumTemps = 1;
664 LocationSummary* summary = 709 LocationSummary* summary =
665 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 710 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
666 summary->set_in(0, Location::RequiresRegister()); 711 summary->set_in(0, Location::RequiresRegister());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 __ Bind(&done); 760 __ Bind(&done);
716 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), 761 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
717 EDI, // Class id register. 762 EDI, // Class id register.
718 kNumArguments, 763 kNumArguments,
719 Array::Handle(), // No named arguments. 764 Array::Handle(), // No named arguments.
720 deopt, // Deoptimize target. 765 deopt, // Deoptimize target.
721 deopt_id(), 766 deopt_id(),
722 token_pos(), 767 token_pos(),
723 try_index(), 768 try_index(),
724 locs()); 769 locs());
725 ASSERT(locs()->out().reg() == EAX);
726 return; 770 return;
727 } 771 }
728 const String& function_name = 772 const String& function_name =
729 String::ZoneHandle(Symbols::New(Token::Str(kind()))); 773 String::ZoneHandle(Symbols::New(Token::Str(kind())));
730 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 774 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
731 deopt_id(), 775 deopt_id(),
732 token_pos(), 776 token_pos(),
733 try_index()); 777 try_index());
734 const intptr_t kNumArguments = 2; 778 const intptr_t kNumArguments = 2;
735 const intptr_t kNumArgsChecked = 2; // Type-feedback. 779 const intptr_t kNumArgsChecked = 2; // Type-feedback.
736 compiler->GenerateInstanceCall(deopt_id(), 780 compiler->GenerateInstanceCall(deopt_id(),
737 token_pos(), 781 token_pos(),
738 try_index(), 782 try_index(),
739 function_name, 783 function_name,
740 kNumArguments, 784 kNumArguments,
741 Array::ZoneHandle(), // No optional arguments. 785 Array::ZoneHandle(), // No optional arguments.
742 kNumArgsChecked, 786 kNumArgsChecked,
743 locs()); 787 locs());
744 ASSERT(locs()->out().reg() == EAX); 788 }
789
790
791 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler,
792 BranchInstr* branch) {
793 if (operands_class_id() == kSmiCid) {
794 EmitSmiComparisonOp(compiler, *locs(), kind(), branch,
795 deopt_id(), try_index());
796 return;
797 }
798 if (operands_class_id() == kDoubleCid) {
799 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch,
800 deopt_id(), try_index());
801 return;
802 }
803 EmitNativeCode(compiler);
804 __ CompareObject(EAX, compiler->bool_true());
805 branch->EmitBranchOnCondition(compiler, EQUAL);
745 } 806 }
746 807
747 808
748 LocationSummary* NativeCallComp::MakeLocationSummary() const { 809 LocationSummary* NativeCallComp::MakeLocationSummary() const {
749 const intptr_t kNumInputs = 0; 810 const intptr_t kNumInputs = 0;
750 const intptr_t kNumTemps = 3; 811 const intptr_t kNumTemps = 3;
751 LocationSummary* locs = 812 LocationSummary* locs =
752 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 813 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
753 locs->set_temp(0, Location::RegisterLocation(EAX)); 814 locs->set_temp(0, Location::RegisterLocation(EAX));
754 locs->set_temp(1, Location::RegisterLocation(ECX)); 815 locs->set_temp(1, Location::RegisterLocation(ECX));
(...skipping 1371 matching lines...) Expand 10 before | Expand all | Expand 10 after
2126 instance_call()->ArgumentCount(), 2187 instance_call()->ArgumentCount(),
2127 instance_call()->argument_names(), 2188 instance_call()->argument_names(),
2128 deopt, 2189 deopt,
2129 instance_call()->deopt_id(), 2190 instance_call()->deopt_id(),
2130 instance_call()->token_pos(), 2191 instance_call()->token_pos(),
2131 instance_call()->try_index(), 2192 instance_call()->try_index(),
2132 locs()); 2193 locs());
2133 } 2194 }
2134 2195
2135 2196
2136 // TODO(srdjan): Move to shared.
2137 static bool ICDataWithBothClassIds(const ICData& ic_data, intptr_t class_id) {
2138 if (ic_data.num_args_tested() != 2) return false;
2139 if (ic_data.NumberOfChecks() != 1) return false;
2140 Function& target = Function::Handle();
2141 GrowableArray<intptr_t> class_ids;
2142 ic_data.GetCheckAt(0, &class_ids, &target);
2143 return (class_ids[0] == class_id) && (class_ids[1] == class_id);
2144 }
2145
2146
2147 static bool IsCheckedStrictEquals(const ICData& ic_data, Token::Kind kind) {
2148 if ((kind == Token::kEQ) || (kind == Token::kNE)) {
2149 return ic_data.AllTargetsHaveSameOwner(kInstanceCid);
2150 }
2151 return false;
2152 }
2153
2154
2155 LocationSummary* BranchInstr::MakeLocationSummary() const {
2156 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2157 if (ICDataWithBothClassIds(*ic_data(), kSmiCid) ||
2158 ICDataWithBothClassIds(*ic_data(), kDoubleCid) ||
2159 IsCheckedStrictEquals(*ic_data(), kind())) {
2160 const intptr_t kNumInputs = 2;
2161 const intptr_t kNumTemps = 1;
2162 LocationSummary* summary =
2163 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2164 summary->set_in(0, Location::RequiresRegister());
2165 summary->set_in(1, Location::RequiresRegister());
2166 summary->set_temp(0, Location::RequiresRegister());
2167 return summary;
2168 }
2169 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) {
2170 const intptr_t kNumInputs = 2;
2171 const intptr_t kNumTemps = 1;
2172 LocationSummary* locs =
2173 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
2174 locs->set_in(0, Location::RegisterLocation(EAX));
2175 locs->set_in(1, Location::RegisterLocation(ECX));
2176 locs->set_temp(0, Location::RegisterLocation(EDX));
2177 return locs;
2178 }
2179 // Otherwise polymorphic dispatch.
2180 }
2181 // Call.
2182 const intptr_t kNumInputs = 2;
2183 const intptr_t kNumTemps = 0;
2184 LocationSummary* locs =
2185 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
2186 locs->set_in(0, Location::RegisterLocation(EAX));
2187 locs->set_in(1, Location::RegisterLocation(ECX));
2188 return locs;
2189 }
2190
2191
2192 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2197 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2193 // Relational or equality. 2198 computation()->EmitBranchCode(compiler, this);
2194 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2195 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) {
2196 EmitSmiComparisonOp(compiler, *locs(), kind(), this,
2197 deopt_id(), try_index());
2198 return;
2199 }
2200 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) {
2201 EmitDoubleComparisonOp(compiler, *locs(), kind(), this,
2202 deopt_id(), try_index());
2203 return;
2204 }
2205 if (IsCheckedStrictEquals(*ic_data(), kind())) {
2206 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this,
2207 deopt_id(), try_index());
2208 return;
2209 }
2210
2211 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons.
2212 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) {
2213 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(),
2214 deopt_id(), token_pos(), try_index());
2215 return;
2216 }
2217 // Otherwise polymorphic dispatch?
2218 }
2219 Register left = locs()->in(0).reg();
2220 Register right = locs()->in(1).reg();
2221 __ pushl(left);
2222 __ pushl(right);
2223 if ((kind() == Token::kNE) || (kind() == Token::kEQ)) {
2224 EmitEqualityAsInstanceCall(compiler,
2225 deopt_id(),
2226 token_pos(),
2227 try_index(),
2228 Token::kEQ, // kNE reverse occurs at branch.
2229 locs());
2230 } else {
2231 const String& function_name =
2232 String::ZoneHandle(Symbols::New(Token::Str(kind())));
2233 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
2234 deopt_id(),
2235 token_pos(),
2236 try_index());
2237 const intptr_t kNumArguments = 2;
2238 const intptr_t kNumArgsChecked = 2; // Type-feedback.
2239 compiler->GenerateInstanceCall(deopt_id(),
2240 token_pos(),
2241 try_index(),
2242 function_name,
2243 kNumArguments,
2244 Array::ZoneHandle(), // No optional args.
2245 kNumArgsChecked,
2246 locs());
2247 }
2248 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
2249 __ CompareObject(EAX, compiler->bool_true());
2250 EmitBranchOnCondition(compiler, branch_condition);
2251 }
2252
2253
2254 LocationSummary* StrictCompareAndBranchInstr::MakeLocationSummary() const {
2255 const int kNumInputs = 2;
2256 const int kNumTemps = 0;
2257 LocationSummary* locs =
2258 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2259 locs->set_in(0, Location::RequiresRegister());
2260 locs->set_in(1, Location::RequiresRegister());
2261 return locs;
2262 }
2263
2264
2265 void StrictCompareAndBranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2266 Register left = locs()->in(0).reg();
2267 Register right = locs()->in(1).reg();
2268 __ cmpl(left, right);
2269 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
2270 EmitBranchOnCondition(compiler, cond);
2271 } 2199 }
2272 2200
2273 2201
2274 LocationSummary* CheckClassComp::MakeLocationSummary() const { 2202 LocationSummary* CheckClassComp::MakeLocationSummary() const {
2275 const intptr_t kNumInputs = 1; 2203 const intptr_t kNumInputs = 1;
2276 const intptr_t kNumTemps = 1; 2204 const intptr_t kNumTemps = 1;
2277 LocationSummary* summary = 2205 LocationSummary* summary =
2278 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2206 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2279 summary->set_in(0, Location::RequiresRegister()); 2207 summary->set_in(0, Location::RequiresRegister());
2280 summary->set_temp(0, Location::RequiresRegister()); 2208 summary->set_temp(0, Location::RequiresRegister());
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2360 } 2288 }
2361 __ j(ABOVE_EQUAL, deopt); 2289 __ j(ABOVE_EQUAL, deopt);
2362 } 2290 }
2363 2291
2364 2292
2365 } // namespace dart 2293 } // namespace dart
2366 2294
2367 #undef __ 2295 #undef __
2368 2296
2369 #endif // defined TARGET_ARCH_X64 2297 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698