| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |