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 |