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

Side by Side Diff: runtime/vm/intermediate_language_ia32.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, 4 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_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 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 token_pos,
443 intptr_t try_index) { 442 intptr_t try_index) {
444 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 443 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
445 Register left = locs.in(0).reg(); 444 Register left = locs.in(0).reg();
446 Register right = locs.in(1).reg(); 445 Register right = locs.in(1).reg();
447 Register temp = locs.temp(0).reg(); 446 Register temp = locs.temp(0).reg();
448 Label* deopt = compiler->AddDeoptStub(deopt_id, 447 Label* deopt = compiler->AddDeoptStub(deopt_id,
449 try_index, 448 try_index,
450 kDeoptEquality); 449 kDeoptEquality);
451 __ testl(left, Immediate(kSmiTagMask)); 450 __ testl(left, Immediate(kSmiTagMask));
452 __ j(ZERO, deopt); 451 __ j(ZERO, deopt);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 deopt_id, token_pos, try_index); 533 deopt_id, token_pos, try_index);
535 __ Bind(&done); 534 __ Bind(&done);
536 } 535 }
537 536
538 537
539 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 538 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
540 const LocationSummary& locs, 539 const LocationSummary& locs,
541 Token::Kind kind, 540 Token::Kind kind,
542 BranchInstr* branch, 541 BranchInstr* branch,
543 intptr_t deopt_id, 542 intptr_t deopt_id,
544 intptr_t token_pos,
545 intptr_t try_index) { 543 intptr_t try_index) {
546 Register left = locs.in(0).reg(); 544 Register left = locs.in(0).reg();
547 Register right = locs.in(1).reg(); 545 Register right = locs.in(1).reg();
548 const bool left_is_smi = (branch == NULL) ? 546 const bool left_is_smi = (branch == NULL) ?
549 false : (branch->left()->ResultCid() == kSmiCid); 547 false : (branch->left()->ResultCid() == kSmiCid);
550 const bool right_is_smi = (branch == NULL) ? 548 const bool right_is_smi = (branch == NULL) ?
551 false : (branch->right()->ResultCid() == kSmiCid); 549 false : (branch->right()->ResultCid() == kSmiCid);
552 if (!left_is_smi || !right_is_smi) { 550 if (!left_is_smi || !right_is_smi) {
553 Register temp = locs.temp(0).reg(); 551 Register temp = locs.temp(0).reg();
554 Label* deopt = compiler->AddDeoptStub(deopt_id, 552 Label* deopt = compiler->AddDeoptStub(deopt_id,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 return OVERFLOW; 589 return OVERFLOW;
592 } 590 }
593 } 591 }
594 592
595 593
596 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 594 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
597 const LocationSummary& locs, 595 const LocationSummary& locs,
598 Token::Kind kind, 596 Token::Kind kind,
599 BranchInstr* branch, 597 BranchInstr* branch,
600 intptr_t deopt_id, 598 intptr_t deopt_id,
601 intptr_t token_pos,
602 intptr_t try_index) { 599 intptr_t try_index) {
603 Register left = locs.in(0).reg(); 600 Register left = locs.in(0).reg();
604 Register right = locs.in(1).reg(); 601 Register right = locs.in(1).reg();
605 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. 602 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs.
606 Register temp = locs.temp(0).reg(); 603 Register temp = locs.temp(0).reg();
607 Label* deopt = compiler->AddDeoptStub(deopt_id, 604 Label* deopt = compiler->AddDeoptStub(deopt_id,
608 try_index, 605 try_index,
609 kDeoptDoubleComparison); 606 kDeoptDoubleComparison);
610 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 607 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
611 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 608 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
612 609
613 Condition true_condition = TokenKindToDoubleCondition(kind); 610 Condition true_condition = TokenKindToDoubleCondition(kind);
614 if (branch != NULL) { 611 if (branch != NULL) {
615 compiler->EmitDoubleCompareBranch( 612 compiler->EmitDoubleCompareBranch(
616 true_condition, XMM0, XMM1, branch); 613 true_condition, XMM0, XMM1, branch);
617 } else { 614 } else {
618 compiler->EmitDoubleCompareBool( 615 compiler->EmitDoubleCompareBool(
619 true_condition, XMM0, XMM1, locs.out().reg()); 616 true_condition, XMM0, XMM1, locs.out().reg());
620 } 617 }
621 } 618 }
622 619
623 620
624 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 621 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
625 if (receiver_class_id() == kSmiCid) { 622 if (receiver_class_id() == kSmiCid) {
626 // Deoptimizes if both arguments not Smi. 623 // Deoptimizes if both arguments not Smi.
627 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 624 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch.
628 deopt_id(), token_pos(), try_index()); 625 deopt_id(), try_index());
629 return; 626 return;
630 } 627 }
631 if (receiver_class_id() == kDoubleCid) { 628 if (receiver_class_id() == kDoubleCid) {
632 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. 629 // Deoptimizes if both arguments are Smi, or if none is Double or Smi.
633 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. 630 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch.
634 deopt_id(), token_pos(), try_index()); 631 deopt_id(), try_index());
635 return; 632 return;
636 } 633 }
637 const bool is_checked_strict_equal = 634 const bool is_checked_strict_equal =
638 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); 635 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
639 if (is_checked_strict_equal) { 636 if (is_checked_strict_equal) {
640 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, 637 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL,
641 deopt_id(), token_pos(), try_index()); 638 deopt_id(), try_index());
642 return; 639 return;
643 } 640 }
644 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 641 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
645 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(), 642 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(),
646 deopt_id(), token_pos(), try_index()); 643 deopt_id(), token_pos(), try_index());
647 } else { 644 } else {
648 Register left = locs()->in(0).reg(); 645 Register left = locs()->in(0).reg();
649 Register right = locs()->in(1).reg(); 646 Register right = locs()->in(1).reg();
650 __ pushl(left); 647 __ pushl(left);
651 __ pushl(right); 648 __ pushl(right);
(...skipping 27 matching lines...) Expand all
679 locs->set_in(0, Location::RegisterLocation(EAX)); 676 locs->set_in(0, Location::RegisterLocation(EAX));
680 locs->set_in(1, Location::RegisterLocation(ECX)); 677 locs->set_in(1, Location::RegisterLocation(ECX));
681 locs->set_out(Location::RegisterLocation(EAX)); 678 locs->set_out(Location::RegisterLocation(EAX));
682 return locs; 679 return locs;
683 } 680 }
684 681
685 682
686 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 683 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
687 if (operands_class_id() == kSmiCid) { 684 if (operands_class_id() == kSmiCid) {
688 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, 685 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL,
689 deopt_id(), token_pos(), try_index()); 686 deopt_id(), try_index());
690 return; 687 return;
691 } 688 }
692 if (operands_class_id() == kDoubleCid) { 689 if (operands_class_id() == kDoubleCid) {
693 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, 690 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL,
694 deopt_id(), token_pos(), try_index()); 691 deopt_id(), try_index());
695 return; 692 return;
696 } 693 }
697 694
698 // Push arguments for the call. 695 // Push arguments for the call.
699 // TODO(fschneider): Split this instruction into different types to avoid 696 // TODO(fschneider): Split this instruction into different types to avoid
700 // explicitly pushing arguments to the call here. 697 // explicitly pushing arguments to the call here.
701 Register left = locs()->in(0).reg(); 698 Register left = locs()->in(0).reg();
702 Register right = locs()->in(1).reg(); 699 Register right = locs()->in(1).reg();
703 __ pushl(left); 700 __ pushl(left);
704 __ pushl(right); 701 __ pushl(right);
(...skipping 1310 matching lines...) Expand 10 before | Expand all | Expand 10 after
2015 2012
2016 static bool IsCheckedStrictEquals(const ICData& ic_data, Token::Kind kind) { 2013 static bool IsCheckedStrictEquals(const ICData& ic_data, Token::Kind kind) {
2017 if ((kind == Token::kEQ) || (kind == Token::kNE)) { 2014 if ((kind == Token::kEQ) || (kind == Token::kNE)) {
2018 return ic_data.AllTargetsHaveSameOwner(kInstanceCid); 2015 return ic_data.AllTargetsHaveSameOwner(kInstanceCid);
2019 } 2016 }
2020 return false; 2017 return false;
2021 } 2018 }
2022 2019
2023 2020
2024 LocationSummary* BranchInstr::MakeLocationSummary() const { 2021 LocationSummary* BranchInstr::MakeLocationSummary() const {
2025 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) {
2026 const int kNumInputs = 2;
2027 const int kNumTemps = 0;
2028 LocationSummary* locs =
2029 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2030 locs->set_in(0, Location::RequiresRegister());
2031 locs->set_in(1, Location::RequiresRegister());
2032 return locs;
2033 }
2034 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 2022 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2035 if (ICDataWithBothClassIds(*ic_data(), kSmiCid) || 2023 if (ICDataWithBothClassIds(*ic_data(), kSmiCid) ||
2036 ICDataWithBothClassIds(*ic_data(), kDoubleCid) || 2024 ICDataWithBothClassIds(*ic_data(), kDoubleCid) ||
2037 IsCheckedStrictEquals(*ic_data(), kind())) { 2025 IsCheckedStrictEquals(*ic_data(), kind())) {
2038 const intptr_t kNumInputs = 2; 2026 const intptr_t kNumInputs = 2;
2039 const intptr_t kNumTemps = 1; 2027 const intptr_t kNumTemps = 1;
2040 LocationSummary* summary = 2028 LocationSummary* summary =
2041 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2029 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2042 summary->set_in(0, Location::RequiresRegister()); 2030 summary->set_in(0, Location::RequiresRegister());
2043 summary->set_in(1, Location::RequiresRegister()); 2031 summary->set_in(1, Location::RequiresRegister());
(...skipping 17 matching lines...) Expand all
2061 const intptr_t kNumTemps = 0; 2049 const intptr_t kNumTemps = 0;
2062 LocationSummary* locs = 2050 LocationSummary* locs =
2063 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 2051 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
2064 locs->set_in(0, Location::RegisterLocation(EAX)); 2052 locs->set_in(0, Location::RegisterLocation(EAX));
2065 locs->set_in(1, Location::RegisterLocation(ECX)); 2053 locs->set_in(1, Location::RegisterLocation(ECX));
2066 return locs; 2054 return locs;
2067 } 2055 }
2068 2056
2069 2057
2070 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2058 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2071 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) {
2072 Register left = locs()->in(0).reg();
2073 Register right = locs()->in(1).reg();
2074 __ cmpl(left, right);
2075 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
2076 EmitBranchOnCondition(compiler, cond);
2077 return;
2078 }
2079 // Relational or equality. 2059 // Relational or equality.
2080 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 2060 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2081 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) { 2061 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) {
2082 EmitSmiComparisonOp(compiler, *locs(), kind(), this, 2062 EmitSmiComparisonOp(compiler, *locs(), kind(), this,
2083 deopt_id(), token_pos(), try_index()); 2063 deopt_id(), try_index());
2084 return; 2064 return;
2085 } 2065 }
2086 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { 2066 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) {
2087 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, 2067 EmitDoubleComparisonOp(compiler, *locs(), kind(), this,
2088 deopt_id(), token_pos(), try_index()); 2068 deopt_id(), try_index());
2089 return; 2069 return;
2090 } 2070 }
2091 if (IsCheckedStrictEquals(*ic_data(), kind())) { 2071 if (IsCheckedStrictEquals(*ic_data(), kind())) {
2092 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, 2072 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this,
2093 deopt_id(), token_pos(), try_index()); 2073 deopt_id(), try_index());
2094 return; 2074 return;
2095 } 2075 }
2096 2076
2097 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. 2077 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons.
2098 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { 2078 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) {
2099 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(), 2079 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(),
2100 deopt_id(), token_pos(), try_index()); 2080 deopt_id(), token_pos(), try_index());
2101 return; 2081 return;
2102 } 2082 }
2103 // Otherwise polymorphic dispatch? 2083 // Otherwise polymorphic dispatch?
(...skipping 26 matching lines...) Expand all
2130 Array::ZoneHandle(), // No optional args. 2110 Array::ZoneHandle(), // No optional args.
2131 kNumArgsChecked, 2111 kNumArgsChecked,
2132 locs()); 2112 locs());
2133 } 2113 }
2134 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; 2114 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
2135 __ CompareObject(EAX, compiler->bool_true()); 2115 __ CompareObject(EAX, compiler->bool_true());
2136 EmitBranchOnCondition(compiler, branch_condition); 2116 EmitBranchOnCondition(compiler, branch_condition);
2137 } 2117 }
2138 2118
2139 2119
2120 LocationSummary* StrictCompareAndBranchInstr::MakeLocationSummary() const {
2121 const int kNumInputs = 2;
2122 const int kNumTemps = 0;
2123 LocationSummary* locs =
2124 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2125 locs->set_in(0, Location::RequiresRegister());
2126 locs->set_in(1, Location::RequiresRegister());
2127 return locs;
2128 }
2129
2130
2131 void StrictCompareAndBranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2132 Register left = locs()->in(0).reg();
2133 Register right = locs()->in(1).reg();
2134 __ cmpl(left, right);
2135 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
2136 EmitBranchOnCondition(compiler, cond);
2137 return;
2138 }
2139
2140
2140 LocationSummary* CheckClassComp::MakeLocationSummary() const { 2141 LocationSummary* CheckClassComp::MakeLocationSummary() const {
2141 const intptr_t kNumInputs = 1; 2142 const intptr_t kNumInputs = 1;
2142 const intptr_t kNumTemps = 1; 2143 const intptr_t kNumTemps = 1;
2143 LocationSummary* summary = 2144 LocationSummary* summary =
2144 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2145 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2145 summary->set_in(0, Location::RequiresRegister()); 2146 summary->set_in(0, Location::RequiresRegister());
2146 summary->set_temp(0, Location::RequiresRegister()); 2147 summary->set_temp(0, Location::RequiresRegister());
2147 return summary; 2148 return summary;
2148 } 2149 }
2149 2150
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2202 __ testl(value, Immediate(kSmiTagMask)); 2203 __ testl(value, Immediate(kSmiTagMask));
2203 __ j(NOT_ZERO, deopt); 2204 __ j(NOT_ZERO, deopt);
2204 } 2205 }
2205 2206
2206 2207
2207 } // namespace dart 2208 } // namespace dart
2208 2209
2209 #undef __ 2210 #undef __
2210 2211
2211 #endif // defined TARGET_ARCH_X64 2212 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698