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