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