Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 5595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5606 } | 5606 } |
| 5607 | 5607 |
| 5608 | 5608 |
| 5609 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(Isolate* isolate, | 5609 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(Isolate* isolate, |
| 5610 bool opt) const { | 5610 bool opt) const { |
| 5611 const intptr_t kNumInputs = 1; | 5611 const intptr_t kNumInputs = 1; |
| 5612 const intptr_t kNumTemps = 0; | 5612 const intptr_t kNumTemps = 0; |
| 5613 LocationSummary* summary = new(isolate) LocationSummary( | 5613 LocationSummary* summary = new(isolate) LocationSummary( |
| 5614 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5614 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5615 summary->set_in(0, Location::RequiresRegister()); | 5615 summary->set_in(0, Location::RequiresRegister()); |
| 5616 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | 5616 if (is_32_bit()) { |
| 5617 Location::RegisterLocation(EDX))); | 5617 summary->set_out(0, Location::RequiresRegister()); |
| 5618 } else { | |
| 5619 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | |
| 5620 Location::RegisterLocation(EDX))); | |
| 5621 } | |
| 5618 return summary; | 5622 return summary; |
| 5619 } | 5623 } |
| 5620 | 5624 |
| 5621 | 5625 |
| 5622 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5626 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5623 const intptr_t value_cid = value()->Type()->ToCid(); | 5627 const intptr_t value_cid = value()->Type()->ToCid(); |
| 5624 const Register value = locs()->in(0).reg(); | 5628 const Register value = locs()->in(0).reg(); |
| 5629 | |
| 5630 if (is_32_bit()) { | |
| 5631 const Register out = locs()->out(0).reg(); | |
| 5632 if (value_cid == kMintCid) { | |
| 5633 __ movl(out, FieldAddress(value, Mint::value_offset())); | |
|
Vyacheslav Egorov (Google)
2014/06/23 20:02:06
for constants here it is beneficial to emit immedi
| |
| 5634 } else if (value_cid == kSmiCid) { | |
| 5635 __ movl(out, value); | |
| 5636 __ SmiUntag(out); | |
| 5637 } else { | |
| 5638 Label* deopt = compiler->AddDeoptStub(deopt_id_, | |
| 5639 ICData::kDeoptUnboxInteger); | |
| 5640 Label is_smi, done; | |
| 5641 __ testl(value, Immediate(kSmiTagMask)); | |
| 5642 __ j(ZERO, &is_smi); | |
| 5643 __ CompareClassId(value, kMintCid, out); | |
| 5644 __ j(NOT_EQUAL, deopt); | |
| 5645 __ movl(out, FieldAddress(value, Mint::value_offset())); | |
| 5646 __ jmp(&done); | |
| 5647 __ Bind(&is_smi); | |
| 5648 __ movl(out, value); | |
| 5649 __ SmiUntag(out); | |
| 5650 __ Bind(&done); | |
| 5651 } | |
| 5652 return; | |
| 5653 } | |
| 5654 | |
| 5655 ASSERT(!is_32_bit()); | |
| 5625 PairLocation* result_pair = locs()->out(0).AsPairLocation(); | 5656 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
| 5626 Register result_lo = result_pair->At(0).reg(); | 5657 Register result_lo = result_pair->At(0).reg(); |
| 5627 Register result_hi = result_pair->At(1).reg(); | 5658 Register result_hi = result_pair->At(1).reg(); |
| 5628 | 5659 |
| 5629 ASSERT(value != result_lo); | 5660 ASSERT(value != result_lo); |
| 5630 ASSERT(value != result_hi); | 5661 ASSERT(value != result_hi); |
| 5631 ASSERT(result_lo == EAX); | 5662 ASSERT(result_lo == EAX); |
| 5632 ASSERT(result_hi == EDX); | 5663 ASSERT(result_hi == EDX); |
| 5633 | 5664 |
| 5634 if (value_cid == kMintCid) { | 5665 if (value_cid == kMintCid) { |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5747 kNoRegister); | 5778 kNoRegister); |
| 5748 __ Bind(slow_path->exit_label()); | 5779 __ Bind(slow_path->exit_label()); |
| 5749 // 3. Restore lower half of input before using it. | 5780 // 3. Restore lower half of input before using it. |
| 5750 __ subl(value_lo, Immediate(0x40000000)); | 5781 __ subl(value_lo, Immediate(0x40000000)); |
| 5751 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo); | 5782 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo); |
| 5752 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi); | 5783 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi); |
| 5753 __ Bind(&done); | 5784 __ Bind(&done); |
| 5754 } | 5785 } |
| 5755 | 5786 |
| 5756 | 5787 |
| 5788 LocationSummary* MintConverterInstr::MakeLocationSummary(Isolate* isolate, | |
| 5789 bool opt) const { | |
| 5790 // We should only see this in optimized code. | |
| 5791 ASSERT(opt); | |
| 5792 const intptr_t kNumInputs = 1; | |
| 5793 const intptr_t kNumTemps = 0; | |
| 5794 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5795 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5796 if (conversion_kind() == kMint32ToMint) { | |
| 5797 summary->set_in(0, Location::RequiresRegister()); | |
| 5798 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | |
| 5799 Location::RequiresRegister())); | |
| 5800 } else if (conversion_kind() == kMintToMint32) { | |
| 5801 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | |
| 5802 Location::RequiresRegister())); | |
| 5803 summary->set_out(0, Location::RequiresRegister()); | |
| 5804 } else { | |
| 5805 UNREACHABLE(); | |
| 5806 } | |
| 5807 return summary; | |
| 5808 } | |
| 5809 | |
| 5810 | |
| 5811 void MintConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 5812 if (conversion_kind() == kMint32ToMint) { | |
| 5813 Register in = locs()->in(0).reg(); | |
| 5814 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
| 5815 Register out_lo = out_pair->At(0).reg(); | |
| 5816 Register out_hi = out_pair->At(1).reg(); | |
| 5817 // Copy lo. | |
| 5818 __ movl(out_lo, in); | |
| 5819 // Zero hi. | |
| 5820 __ xorl(out_hi, out_hi); | |
| 5821 } else if (conversion_kind() == kMintToMint32) { | |
| 5822 PairLocation* in_pair = locs()->in(0).AsPairLocation(); | |
| 5823 Register in_lo = in_pair->At(0).reg(); | |
| 5824 Register out = locs()->out(0).reg(); | |
| 5825 // Copy lo. | |
| 5826 __ movl(out, in_lo); | |
| 5827 } else { | |
| 5828 UNREACHABLE(); | |
| 5829 } | |
| 5830 } | |
| 5831 | |
| 5832 | |
| 5833 static bool BinaryMintOutputSameAsInput(const BinaryMintOpInstr* instr) { | |
| 5834 return instr->is_32_bit() == instr->IsInput32Bit(0); | |
| 5835 } | |
| 5836 | |
| 5757 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5837 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
|
Vyacheslav Egorov (Google)
2014/06/23 20:02:06
This instruction became way too complex. We need t
| |
| 5758 bool opt) const { | 5838 bool opt) const { |
| 5759 const intptr_t kNumInputs = 2; | 5839 const intptr_t kNumInputs = 2; |
| 5840 // Need a temporary right high word if we are computing a 64-bit value | |
| 5841 // and the right operand is 32-bits. | |
| 5842 const intptr_t kNumTemps = (!is_32_bit() && IsInput32Bit(1)) ? 1 : 0; | |
| 5760 switch (op_kind()) { | 5843 switch (op_kind()) { |
| 5761 case Token::kBIT_AND: | 5844 case Token::kBIT_AND: |
| 5762 case Token::kBIT_OR: | 5845 case Token::kBIT_OR: |
| 5763 case Token::kBIT_XOR: { | 5846 case Token::kBIT_XOR: { |
| 5764 const intptr_t kNumTemps = 0; | |
| 5765 LocationSummary* summary = new(isolate) LocationSummary( | 5847 LocationSummary* summary = new(isolate) LocationSummary( |
| 5766 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5848 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5767 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5849 |
| 5768 Location::RequiresRegister())); | 5850 if (kNumTemps > 0) { |
| 5769 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | 5851 ASSERT(kNumTemps == 1); |
| 5770 Location::RequiresRegister())); | 5852 summary->set_temp(0, Location::RequiresRegister()); |
| 5771 summary->set_out(0, Location::SameAsFirstInput()); | 5853 } |
| 5854 | |
| 5855 if (IsInput32Bit(0)) { | |
| 5856 summary->set_in(0, Location::RequiresRegister()); | |
| 5857 } else { | |
| 5858 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | |
| 5859 Location::RequiresRegister())); | |
| 5860 } | |
| 5861 | |
| 5862 if (IsInput32Bit(1)) { | |
| 5863 summary->set_in(1, Location::RequiresRegister()); | |
| 5864 } else { | |
| 5865 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | |
| 5866 Location::RequiresRegister())); | |
| 5867 } | |
| 5868 | |
| 5869 if (BinaryMintOutputSameAsInput(this)) { | |
| 5870 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5871 } else if (is_32_bit()) { | |
| 5872 summary->set_out(0, Location::RequiresRegister()); | |
| 5873 } else { | |
| 5874 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | |
| 5875 Location::RequiresRegister())); | |
| 5876 } | |
| 5772 return summary; | 5877 return summary; |
| 5773 } | 5878 } |
| 5774 case Token::kADD: | 5879 case Token::kADD: |
| 5775 case Token::kSUB: { | 5880 case Token::kSUB: { |
| 5776 const intptr_t kNumTemps = 0; | |
| 5777 LocationSummary* summary = new(isolate) LocationSummary( | 5881 LocationSummary* summary = new(isolate) LocationSummary( |
| 5778 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5882 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5779 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5883 |
| 5780 Location::RequiresRegister())); | 5884 if (kNumTemps > 0) { |
| 5781 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | 5885 ASSERT(kNumTemps == 1); |
| 5782 Location::RequiresRegister())); | 5886 summary->set_temp(0, Location::RequiresRegister()); |
| 5783 summary->set_out(0, Location::SameAsFirstInput()); | 5887 } |
| 5888 if (IsInput32Bit(0)) { | |
| 5889 summary->set_in(0, Location::RequiresRegister()); | |
| 5890 } else { | |
| 5891 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | |
| 5892 Location::RequiresRegister())); | |
| 5893 } | |
| 5894 | |
| 5895 if (IsInput32Bit(1)) { | |
| 5896 summary->set_in(1, Location::RequiresRegister()); | |
| 5897 } else { | |
| 5898 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | |
| 5899 Location::RequiresRegister())); | |
| 5900 } | |
| 5901 | |
| 5902 if (BinaryMintOutputSameAsInput(this)) { | |
| 5903 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5904 } else if (is_32_bit()) { | |
| 5905 summary->set_out(0, Location::RequiresRegister()); | |
| 5906 } else { | |
| 5907 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | |
| 5908 Location::RequiresRegister())); | |
| 5909 } | |
| 5784 return summary; | 5910 return summary; |
| 5785 } | 5911 } |
| 5786 default: | 5912 default: |
| 5787 UNREACHABLE(); | 5913 UNREACHABLE(); |
| 5788 return NULL; | 5914 return NULL; |
| 5789 } | 5915 } |
| 5790 } | 5916 } |
| 5791 | 5917 |
| 5792 | 5918 |
| 5793 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5919 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5794 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 5920 Register left_lo = kNoRegister; |
| 5795 Register left_lo = left_pair->At(0).reg(); | 5921 Register left_hi = kNoRegister; |
| 5796 Register left_hi = left_pair->At(1).reg(); | 5922 Register right_lo = kNoRegister; |
| 5797 PairLocation* right_pair = locs()->in(1).AsPairLocation(); | 5923 Register right_hi = kNoRegister; |
| 5798 Register right_lo = right_pair->At(0).reg(); | 5924 Register out_lo = kNoRegister; |
| 5799 Register right_hi = right_pair->At(1).reg(); | 5925 Register out_hi = kNoRegister; |
| 5926 | |
| 5927 if (IsInput32Bit(0)) { | |
| 5928 left_lo = locs()->in(0).reg(); | |
| 5929 } else { | |
| 5930 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | |
| 5931 left_lo = left_pair->At(0).reg(); | |
| 5932 left_hi = left_pair->At(1).reg(); | |
| 5933 } | |
| 5934 | |
| 5935 if (IsInput32Bit(1)) { | |
| 5936 right_lo = locs()->in(1).reg(); | |
| 5937 } else { | |
| 5938 PairLocation* right_pair = locs()->in(1).AsPairLocation(); | |
| 5939 right_lo = right_pair->At(0).reg(); | |
| 5940 right_hi = right_pair->At(1).reg(); | |
| 5941 } | |
| 5942 | |
| 5943 if (is_32_bit()) { | |
| 5944 out_lo = locs()->out(0).reg(); | |
| 5945 if (!BinaryMintOutputSameAsInput(this)) { | |
| 5946 // Copy lo part of left. | |
| 5947 __ movl(out_lo, left_lo); | |
| 5948 } else { | |
| 5949 ASSERT(out_lo == left_lo); | |
| 5950 } | |
| 5951 switch (op_kind()) { | |
| 5952 case Token::kBIT_AND: | |
| 5953 __ andl(out_lo, right_lo); | |
| 5954 break; | |
| 5955 case Token::kBIT_OR: | |
| 5956 __ orl(out_lo, right_lo); | |
| 5957 break; | |
| 5958 case Token::kBIT_XOR: | |
| 5959 __ xorl(out_lo, right_lo); | |
| 5960 break; | |
| 5961 case Token::kADD: | |
| 5962 case Token::kSUB: { | |
| 5963 if (op_kind() == Token::kADD) { | |
| 5964 __ addl(out_lo, right_lo); | |
| 5965 } else { | |
| 5966 __ subl(out_lo, right_lo); | |
| 5967 } | |
| 5968 break; | |
| 5969 } | |
| 5970 default: UNREACHABLE(); | |
| 5971 } | |
| 5972 return; | |
| 5973 } | |
| 5974 | |
| 5975 ASSERT(!is_32_bit()); | |
| 5976 | |
| 5800 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 5977 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 5801 Register out_lo = out_pair->At(0).reg(); | 5978 out_lo = out_pair->At(0).reg(); |
| 5802 Register out_hi = out_pair->At(1).reg(); | 5979 out_hi = out_pair->At(1).reg(); |
| 5803 ASSERT(out_lo == left_lo); | 5980 if (BinaryMintOutputSameAsInput(this)) { |
| 5804 ASSERT(out_hi == left_hi); | 5981 ASSERT(out_lo == left_lo); |
| 5982 ASSERT(out_hi == left_hi); | |
| 5983 } else { | |
| 5984 // Left input is 32-bits. | |
| 5985 ASSERT(IsInput32Bit(0)); | |
| 5986 // Copy lo input. | |
| 5987 __ movl(out_lo, left_lo); | |
| 5988 // Zero output. | |
| 5989 __ xorl(out_hi, out_hi); | |
| 5990 } | |
| 5991 | |
| 5992 if (IsInput32Bit(1)) { | |
| 5993 // Zero temporary right high word. | |
| 5994 right_hi = locs()->temp(0).reg(); | |
| 5995 __ xorl(right_hi, right_hi); | |
| 5996 } | |
| 5805 | 5997 |
| 5806 Label* deopt = NULL; | 5998 Label* deopt = NULL; |
| 5807 if (FLAG_throw_on_javascript_int_overflow) { | 5999 if (FLAG_throw_on_javascript_int_overflow) { |
| 5808 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6000 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 5809 } | 6001 } |
| 5810 switch (op_kind()) { | 6002 switch (op_kind()) { |
| 5811 case Token::kBIT_AND: | 6003 case Token::kBIT_AND: |
| 5812 __ andl(left_lo, right_lo); | 6004 __ andl(out_lo, right_lo); |
| 5813 __ andl(left_hi, right_hi); | 6005 __ andl(out_hi, right_hi); |
| 5814 break; | 6006 break; |
| 5815 case Token::kBIT_OR: | 6007 case Token::kBIT_OR: |
| 5816 __ orl(left_lo, right_lo); | 6008 __ orl(out_lo, right_lo); |
| 5817 __ orl(left_hi, right_hi); | 6009 __ orl(out_hi, right_hi); |
| 5818 break; | 6010 break; |
| 5819 case Token::kBIT_XOR: | 6011 case Token::kBIT_XOR: |
| 5820 __ xorl(left_lo, right_lo); | 6012 __ xorl(out_lo, right_lo); |
| 5821 __ xorl(left_hi, right_hi); | 6013 __ xorl(out_hi, right_hi); |
| 5822 break; | 6014 break; |
| 5823 case Token::kADD: | 6015 case Token::kADD: |
| 5824 case Token::kSUB: { | 6016 case Token::kSUB: { |
| 5825 if (!FLAG_throw_on_javascript_int_overflow) { | 6017 if (!FLAG_throw_on_javascript_int_overflow) { |
| 5826 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6018 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 5827 } | 6019 } |
| 5828 if (op_kind() == Token::kADD) { | 6020 if (op_kind() == Token::kADD) { |
| 5829 __ addl(left_lo, right_lo); | 6021 __ addl(out_lo, right_lo); |
| 5830 __ adcl(left_hi, right_hi); | 6022 __ adcl(out_hi, right_hi); |
| 5831 } else { | 6023 } else { |
| 5832 __ subl(left_lo, right_lo); | 6024 __ subl(out_lo, right_lo); |
| 5833 __ sbbl(left_hi, right_hi); | 6025 __ sbbl(out_hi, right_hi); |
| 5834 } | 6026 } |
| 5835 __ j(OVERFLOW, deopt); | 6027 __ j(OVERFLOW, deopt); |
| 5836 break; | 6028 break; |
| 5837 } | 6029 } |
| 5838 default: UNREACHABLE(); | 6030 default: UNREACHABLE(); |
| 5839 } | 6031 } |
| 5840 if (FLAG_throw_on_javascript_int_overflow) { | 6032 if (FLAG_throw_on_javascript_int_overflow) { |
| 5841 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); | 6033 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); |
| 5842 } | 6034 } |
| 5843 } | 6035 } |
| 5844 | 6036 |
| 5845 | 6037 |
| 6038 static bool ShiftMintOpInstrOutputSameAsInput(const ShiftMintOpInstr* instr) { | |
| 6039 return instr->is_32_bit() == instr->IsInput32Bit(0); | |
| 6040 } | |
| 6041 | |
| 6042 | |
| 5846 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, | 6043 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5847 bool opt) const { | 6044 bool opt) const { |
| 6045 const bool need_temps = (op_kind() == Token::kSHL) && CanShiftLeftOverflow(); | |
| 5848 const intptr_t kNumInputs = 2; | 6046 const intptr_t kNumInputs = 2; |
| 5849 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 0; | 6047 const intptr_t kNumTemps = need_temps ? 2 : 0; |
| 5850 LocationSummary* summary = new(isolate) LocationSummary( | 6048 LocationSummary* summary = new(isolate) LocationSummary( |
| 5851 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6049 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5852 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6050 |
| 5853 Location::RequiresRegister())); | 6051 |
| 6052 if (IsInput32Bit(0)) { | |
| 6053 summary->set_in(0, Location::RequiresRegister()); | |
| 6054 } else { | |
| 6055 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | |
| 6056 Location::RequiresRegister())); | |
| 6057 } | |
| 6058 | |
| 5854 summary->set_in(1, Location::RegisterLocation(ECX)); | 6059 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 5855 if (op_kind() == Token::kSHL) { | 6060 |
| 6061 if (need_temps) { | |
| 5856 summary->set_temp(0, Location::RequiresRegister()); | 6062 summary->set_temp(0, Location::RequiresRegister()); |
| 5857 summary->set_temp(1, Location::RequiresRegister()); | 6063 summary->set_temp(1, Location::RequiresRegister()); |
| 5858 } | 6064 } |
| 5859 summary->set_out(0, Location::SameAsFirstInput()); | 6065 |
| 6066 if (ShiftMintOpInstrOutputSameAsInput(this)) { | |
| 6067 summary->set_out(0, Location::SameAsFirstInput()); | |
| 6068 } else if (is_32_bit()) { | |
| 6069 summary->set_out(0, Location::RequiresRegister()); | |
| 6070 } else { | |
| 6071 ASSERT(IsInput32Bit(0)); | |
| 6072 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | |
| 6073 Location::RequiresRegister())); | |
| 6074 } | |
| 6075 | |
| 5860 return summary; | 6076 return summary; |
| 5861 } | 6077 } |
| 5862 | 6078 |
| 5863 | 6079 |
| 5864 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6080 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5865 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 6081 // Shift count is in ECX. |
| 5866 Register left_lo = left_pair->At(0).reg(); | 6082 ASSERT(locs()->in(1).reg() == ECX); |
| 5867 Register left_hi = left_pair->At(1).reg(); | 6083 Register left_lo; |
| 5868 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6084 Register left_hi; |
| 5869 Register out_lo = out_pair->At(0).reg(); | 6085 Register out_lo; |
| 5870 Register out_hi = out_pair->At(1).reg(); | 6086 Register out_hi; |
| 5871 ASSERT(out_lo == left_lo); | |
| 5872 ASSERT(out_hi == left_hi); | |
| 5873 | 6087 |
| 5874 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | 6088 if (IsInput32Bit(0)) { |
| 6089 left_lo = locs()->in(0).reg(); | |
| 6090 left_hi = kNoRegister; | |
| 6091 } else { | |
| 6092 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | |
| 6093 left_lo = left_pair->At(0).reg(); | |
| 6094 left_hi = left_pair->At(1).reg(); | |
| 6095 } | |
| 6096 | |
| 6097 if (is_32_bit()) { | |
| 6098 out_lo = locs()->out(0).reg(); | |
| 6099 out_hi = kNoRegister; | |
| 6100 } else { | |
| 6101 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
| 6102 out_lo = out_pair->At(0).reg(); | |
| 6103 out_hi = out_pair->At(1).reg(); | |
| 6104 } | |
| 6105 | |
| 6106 if (ShiftMintOpInstrOutputSameAsInput(this)) { | |
| 6107 ASSERT(out_lo == left_lo); | |
| 6108 ASSERT(out_hi == left_hi); | |
| 6109 } else if (is_32_bit()) { | |
| 6110 ASSERT(!IsInput32Bit(0)); | |
| 6111 // Copy lo. | |
| 6112 __ movl(out_lo, left_lo); | |
| 6113 } else if (IsInput32Bit(0)) { | |
| 6114 ASSERT(!is_32_bit()); | |
| 6115 // Copy lo. | |
| 6116 __ movl(out_lo, left_lo); | |
| 6117 // Zero hi. | |
| 6118 __ xorl(out_hi, out_hi); | |
| 6119 } | |
| 6120 | |
| 6121 | |
| 5875 Label done; | 6122 Label done; |
| 5876 __ testl(ECX, ECX); | 6123 __ testl(ECX, ECX); |
| 5877 __ j(ZERO, &done); // Shift by 0 is a nop. | 6124 __ j(ZERO, &done); // Shift by 0 is a nop. |
| 6125 __ SmiUntag(ECX); | |
| 6126 | |
| 5878 // Deoptimize if shift count is > 31. | 6127 // Deoptimize if shift count is > 31. |
| 5879 // sarl operation masks the count to 5 bits and | 6128 // sarl operation masks the count to 5 bits and |
| 5880 // shrd is undefined with count > operand size (32) | 6129 // shrd is undefined with count > operand size (32) |
| 5881 // TODO(fschneider): Support shift counts > 31 without deoptimization. | 6130 // TODO(fschneider): Support shift counts > 31 without deoptimization. |
| 5882 __ SmiUntag(ECX); | 6131 |
| 6132 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | |
| 5883 const Immediate& kCountLimit = Immediate(31); | 6133 const Immediate& kCountLimit = Immediate(31); |
| 5884 __ cmpl(ECX, kCountLimit); | 6134 __ cmpl(ECX, kCountLimit); |
| 5885 __ j(ABOVE, deopt); | 6135 __ j(ABOVE, deopt); |
| 6136 | |
| 5886 switch (op_kind()) { | 6137 switch (op_kind()) { |
| 5887 case Token::kSHR: { | 6138 case Token::kSHR: { |
| 5888 __ shrd(left_lo, left_hi); // Shift count in CL. | 6139 if (IsInput32Bit(0)) { |
| 5889 __ sarl(left_hi, ECX); // Shift count in CL. | 6140 // 32-bit input. |
| 6141 // Upper word is 0, use logical shift. | |
| 6142 __ shrl(out_lo, ECX); | |
| 6143 // If needed, out_hi is already zero. | |
| 6144 } else { | |
| 6145 // 64-bit input, | |
| 6146 if (is_32_bit()) { | |
| 6147 // 32-bit output | |
| 6148 __ shrd(out_lo, left_hi); // Shift count in CL. | |
| 6149 } else { | |
| 6150 // 64-bit output. | |
| 6151 __ shrd(out_lo, left_hi); // Shift count in CL. | |
| 6152 __ sarl(out_hi, ECX); // Shift count in CL. | |
| 6153 } | |
| 6154 } | |
| 5890 break; | 6155 break; |
| 5891 } | 6156 } |
| 5892 case Token::kSHL: { | 6157 case Token::kSHL: { |
| 5893 Register temp1 = locs()->temp(0).reg(); | 6158 if (CanShiftLeftOverflow()) { |
| 5894 Register temp2 = locs()->temp(1).reg(); | 6159 // 64-bit input and 64-bit output. |
| 5895 __ movl(temp1, left_lo); // Low 32 bits. | 6160 Register temp1 = locs()->temp(0).reg(); |
| 5896 __ movl(temp2, left_hi); // High 32 bits. | 6161 Register temp2 = locs()->temp(1).reg(); |
| 5897 __ shll(left_lo, ECX); // Shift count in CL. | 6162 __ movl(temp1, out_lo); // Low 32 bits. |
| 5898 __ shld(left_hi, temp1); // Shift count in CL. | 6163 __ movl(temp2, out_hi); // High 32 bits. |
| 5899 // Check for overflow by shifting back the high 32 bits | 6164 __ shll(out_lo, ECX); // Shift count in CL. |
| 5900 // and comparing with the input. | 6165 __ shld(out_hi, temp1); // Shift count in CL. |
| 5901 __ movl(temp1, temp2); | 6166 // Check for overflow by shifting back the high 32 bits |
| 5902 __ movl(temp2, left_hi); | 6167 // and comparing with the input. |
| 5903 __ sarl(temp2, ECX); | 6168 __ movl(temp1, temp2); |
| 5904 __ cmpl(temp1, temp2); | 6169 __ movl(temp2, out_hi); |
| 5905 __ j(NOT_EQUAL, deopt); | 6170 __ sarl(temp2, ECX); |
| 6171 __ cmpl(temp1, temp2); | |
| 6172 __ j(NOT_EQUAL, deopt); | |
| 6173 } else { | |
| 6174 if (is_32_bit()) { | |
| 6175 // 32-bit output (can be 64-bit or 32-bit input). | |
| 6176 __ shll(out_lo, ECX); | |
| 6177 } else { | |
| 6178 // 64-bit output and 32-bit input. | |
| 6179 ASSERT(out_lo != left_lo); | |
| 6180 __ shll(out_lo, ECX); | |
| 6181 __ shld(out_hi, left_lo); | |
| 6182 } | |
| 6183 } | |
| 5906 break; | 6184 break; |
| 5907 } | 6185 } |
| 5908 default: | 6186 default: |
| 5909 UNREACHABLE(); | 6187 UNREACHABLE(); |
| 5910 break; | 6188 break; |
| 5911 } | 6189 } |
| 5912 __ Bind(&done); | 6190 __ Bind(&done); |
| 5913 if (FLAG_throw_on_javascript_int_overflow) { | 6191 if (FLAG_throw_on_javascript_int_overflow && !is_32_bit()) { |
| 5914 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); | 6192 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); |
| 5915 } | 6193 } |
| 5916 } | 6194 } |
| 5917 | 6195 |
| 5918 | 6196 |
| 6197 static bool UnaryMintOutputSameAsInput(const UnaryMintOpInstr* instr) { | |
| 6198 return instr->is_32_bit() == instr->IsInput32Bit(0); | |
| 6199 } | |
| 6200 | |
| 6201 | |
| 5919 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 6202 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5920 bool opt) const { | 6203 bool opt) const { |
| 5921 const intptr_t kNumInputs = 1; | 6204 const intptr_t kNumInputs = 1; |
| 5922 const intptr_t kNumTemps = 0; | 6205 const intptr_t kNumTemps = 0; |
| 5923 LocationSummary* summary = new(isolate) LocationSummary( | 6206 LocationSummary* summary = new(isolate) LocationSummary( |
| 5924 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6207 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5925 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6208 |
| 5926 Location::RequiresRegister())); | 6209 if (IsInput32Bit(0)) { |
| 5927 summary->set_out(0, Location::SameAsFirstInput()); | 6210 summary->set_in(0, Location::RequiresRegister()); |
| 5928 if (FLAG_throw_on_javascript_int_overflow) { | 6211 } else { |
| 5929 summary->set_temp(0, Location::RequiresRegister()); | 6212 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6213 Location::RequiresRegister())); | |
| 6214 } | |
| 6215 | |
| 6216 if (UnaryMintOutputSameAsInput(this)) { | |
| 6217 summary->set_out(0, Location::SameAsFirstInput()); | |
| 6218 } else if (IsInput32Bit(0)) { | |
| 6219 ASSERT(!is_32_bit()); | |
| 6220 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | |
| 6221 Location::RequiresRegister())); | |
| 6222 } else { | |
| 6223 ASSERT(is_32_bit()); | |
| 6224 summary->set_out(0, Location::RequiresRegister()); | |
| 5930 } | 6225 } |
| 5931 return summary; | 6226 return summary; |
| 5932 } | 6227 } |
| 5933 | 6228 |
| 5934 | 6229 |
| 5935 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6230 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5936 ASSERT(op_kind() == Token::kBIT_NOT); | 6231 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5937 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 6232 |
| 5938 Register left_lo = left_pair->At(0).reg(); | 6233 // Extract registers. |
| 5939 Register left_hi = left_pair->At(1).reg(); | 6234 Register out_lo; |
| 5940 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6235 Register out_hi = kNoRegister; |
| 5941 Register out_lo = out_pair->At(0).reg(); | 6236 Register left_lo; |
| 5942 Register out_hi = out_pair->At(1).reg(); | 6237 Register left_hi = kNoRegister; |
| 5943 ASSERT(out_lo == left_lo); | 6238 |
| 5944 ASSERT(out_hi == left_hi); | 6239 if (IsInput32Bit(0)) { |
| 6240 left_lo = locs()->in(0).reg(); | |
| 6241 } else { | |
| 6242 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | |
| 6243 left_lo = left_pair->At(0).reg(); | |
| 6244 left_hi = left_pair->At(1).reg(); | |
| 6245 } | |
| 6246 | |
| 6247 if (is_32_bit()) { | |
| 6248 out_lo = locs()->out(0).reg(); | |
| 6249 } else { | |
| 6250 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
| 6251 out_lo = out_pair->At(0).reg(); | |
| 6252 out_hi = out_pair->At(1).reg(); | |
| 6253 } | |
| 6254 | |
| 6255 if (UnaryMintOutputSameAsInput(this)) { | |
| 6256 ASSERT(out_lo == left_lo); | |
| 6257 ASSERT(out_hi == left_hi); | |
| 6258 } else { | |
| 6259 __ movl(out_lo, left_lo); | |
| 6260 if (!is_32_bit() && IsInput32Bit(0)) { | |
| 6261 // Zero high word. | |
| 6262 __ xorl(out_hi, out_hi); | |
| 6263 } | |
| 6264 } | |
| 5945 | 6265 |
| 5946 Label* deopt = NULL; | 6266 Label* deopt = NULL; |
| 5947 if (FLAG_throw_on_javascript_int_overflow) { | 6267 if (FLAG_throw_on_javascript_int_overflow && !is_32_bit()) { |
| 5948 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | 6268 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); |
| 5949 } | 6269 } |
| 5950 | 6270 |
| 5951 __ notl(left_lo); | 6271 __ notl(out_lo); |
| 5952 __ notl(left_hi); | 6272 if (!is_32_bit()) { |
| 6273 __ notl(out_hi); | |
| 6274 } | |
| 5953 | 6275 |
| 5954 if (FLAG_throw_on_javascript_int_overflow) { | 6276 if (FLAG_throw_on_javascript_int_overflow && !is_32_bit()) { |
| 5955 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); | 6277 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); |
| 5956 } | 6278 } |
| 5957 } | 6279 } |
| 5958 | 6280 |
| 5959 | 6281 |
| 5960 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6282 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
| 5961 bool opt) const { | 6283 bool opt) const { |
| 5962 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6284 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
| 5963 } | 6285 } |
| 5964 | 6286 |
| 5965 | 6287 |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6307 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6629 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
| 6308 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6630 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
| 6309 #endif | 6631 #endif |
| 6310 } | 6632 } |
| 6311 | 6633 |
| 6312 } // namespace dart | 6634 } // namespace dart |
| 6313 | 6635 |
| 6314 #undef __ | 6636 #undef __ |
| 6315 | 6637 |
| 6316 #endif // defined TARGET_ARCH_IA32 | 6638 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |