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 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 } | 644 } |
645 | 645 |
646 | 646 |
647 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 647 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
648 BranchLabels labels) { | 648 BranchLabels labels) { |
649 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 649 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
650 Register val_reg = locs()->in(0).reg(); | 650 Register val_reg = locs()->in(0).reg(); |
651 Register cid_reg = locs()->temp(0).reg(); | 651 Register cid_reg = locs()->temp(0).reg(); |
652 | 652 |
653 Label* deopt = CanDeoptimize() ? | 653 Label* deopt = CanDeoptimize() ? |
654 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL; | 654 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL; |
655 | 655 |
656 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 656 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
657 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 657 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
658 ASSERT(data[0] == kSmiCid); | 658 ASSERT(data[0] == kSmiCid); |
659 bool result = data[1] == true_result; | 659 bool result = data[1] == true_result; |
660 __ testl(val_reg, Immediate(kSmiTagMask)); | 660 __ testl(val_reg, Immediate(kSmiTagMask)); |
661 __ j(ZERO, result ? labels.true_label : labels.false_label); | 661 __ j(ZERO, result ? labels.true_label : labels.false_label); |
662 __ LoadClassId(cid_reg, val_reg); | 662 __ LoadClassId(cid_reg, val_reg); |
663 for (intptr_t i = 2; i < data.length(); i += 2) { | 663 for (intptr_t i = 2; i < data.length(); i += 2) { |
664 const intptr_t test_cid = data[i]; | 664 const intptr_t test_cid = data[i]; |
(...skipping 5174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5839 __ Bind(&done); | 5839 __ Bind(&done); |
5840 } | 5840 } |
5841 | 5841 |
5842 | 5842 |
5843 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5843 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
5844 bool opt) const { | 5844 bool opt) const { |
5845 const intptr_t kNumInputs = 2; | 5845 const intptr_t kNumInputs = 2; |
5846 switch (op_kind()) { | 5846 switch (op_kind()) { |
5847 case Token::kBIT_AND: | 5847 case Token::kBIT_AND: |
5848 case Token::kBIT_OR: | 5848 case Token::kBIT_OR: |
5849 case Token::kBIT_XOR: { | 5849 case Token::kBIT_XOR: |
5850 const intptr_t kNumTemps = 0; | 5850 case Token::kADD: |
| 5851 case Token::kSUB: |
| 5852 case Token::kMUL: { |
| 5853 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; |
5851 LocationSummary* summary = new(isolate) LocationSummary( | 5854 LocationSummary* summary = new(isolate) LocationSummary( |
5852 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5855 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5853 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5856 summary->set_in(0, (op_kind() == Token::kMUL) |
5854 Location::RequiresRegister())); | 5857 ? Location::Pair(Location::RegisterLocation(EAX), |
| 5858 Location::RegisterLocation(EDX)) |
| 5859 : Location::Pair(Location::RequiresRegister(), |
| 5860 Location::RequiresRegister())); |
5855 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | 5861 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
5856 Location::RequiresRegister())); | 5862 Location::RequiresRegister())); |
5857 summary->set_out(0, Location::SameAsFirstInput()); | 5863 summary->set_out(0, Location::SameAsFirstInput()); |
5858 return summary; | 5864 if (kNumTemps > 0) { |
5859 } | 5865 summary->set_temp(0, Location::RequiresRegister()); |
5860 case Token::kADD: | 5866 } |
5861 case Token::kSUB: { | |
5862 const intptr_t kNumTemps = 0; | |
5863 LocationSummary* summary = new(isolate) LocationSummary( | |
5864 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
5865 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | |
5866 Location::RequiresRegister())); | |
5867 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | |
5868 Location::RequiresRegister())); | |
5869 summary->set_out(0, Location::SameAsFirstInput()); | |
5870 return summary; | 5867 return summary; |
5871 } | 5868 } |
5872 default: | 5869 default: |
5873 UNREACHABLE(); | 5870 UNREACHABLE(); |
5874 return NULL; | 5871 return NULL; |
5875 } | 5872 } |
5876 } | 5873 } |
5877 | 5874 |
5878 | 5875 |
5879 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5876 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5913 __ adcl(left_hi, right_hi); | 5910 __ adcl(left_hi, right_hi); |
5914 } else { | 5911 } else { |
5915 __ subl(left_lo, right_lo); | 5912 __ subl(left_lo, right_lo); |
5916 __ sbbl(left_hi, right_hi); | 5913 __ sbbl(left_hi, right_hi); |
5917 } | 5914 } |
5918 if (can_overflow()) { | 5915 if (can_overflow()) { |
5919 __ j(OVERFLOW, deopt); | 5916 __ j(OVERFLOW, deopt); |
5920 } | 5917 } |
5921 break; | 5918 break; |
5922 } | 5919 } |
5923 default: UNREACHABLE(); | 5920 case Token::kMUL: { |
| 5921 // The product of two signed 32-bit integers fits in a signed 64-bit |
| 5922 // result without causing overflow. |
| 5923 // We deopt on larger inputs. |
| 5924 // TODO(regis): Range analysis may eliminate the deopt check. |
| 5925 Register temp = locs()->temp(0).reg(); |
| 5926 __ movl(temp, left_lo); |
| 5927 __ sarl(temp, Immediate(31)); |
| 5928 __ cmpl(temp, left_hi); |
| 5929 __ j(NOT_EQUAL, deopt); |
| 5930 __ movl(temp, right_lo); |
| 5931 __ sarl(temp, Immediate(31)); |
| 5932 __ cmpl(temp, right_hi); |
| 5933 __ j(NOT_EQUAL, deopt); |
| 5934 ASSERT(left_lo == EAX); |
| 5935 __ imull(right_lo); // Result in EDX:EAX. |
| 5936 ASSERT(out_lo == EAX); |
| 5937 ASSERT(out_hi == EDX); |
| 5938 break; |
| 5939 } |
| 5940 default: |
| 5941 UNREACHABLE(); |
5924 } | 5942 } |
5925 if (FLAG_throw_on_javascript_int_overflow) { | 5943 if (FLAG_throw_on_javascript_int_overflow) { |
5926 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); | 5944 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); |
5927 } | 5945 } |
5928 } | 5946 } |
5929 | 5947 |
5930 | 5948 |
5931 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5949 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, |
5932 bool opt) const { | 5950 bool opt) const { |
5933 const intptr_t kNumInputs = 2; | 5951 const intptr_t kNumInputs = 2; |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6106 __ Bind(&large_shift); | 6124 __ Bind(&large_shift); |
6107 // No need to subtract 32 from CL, only 5 bits used by shll. | 6125 // No need to subtract 32 from CL, only 5 bits used by shll. |
6108 __ movl(left_hi, left_lo); // Shift by 32. | 6126 __ movl(left_hi, left_lo); // Shift by 32. |
6109 __ xorl(left_lo, left_lo); // Zero left_lo. | 6127 __ xorl(left_lo, left_lo); // Zero left_lo. |
6110 __ shll(left_hi, ECX); // Shift count: CL % 32. | 6128 __ shll(left_hi, ECX); // Shift count: CL % 32. |
6111 } | 6129 } |
6112 break; | 6130 break; |
6113 } | 6131 } |
6114 default: | 6132 default: |
6115 UNREACHABLE(); | 6133 UNREACHABLE(); |
6116 break; | |
6117 } | 6134 } |
6118 __ Bind(&done); | 6135 __ Bind(&done); |
6119 } | 6136 } |
6120 if (FLAG_throw_on_javascript_int_overflow) { | 6137 if (FLAG_throw_on_javascript_int_overflow) { |
6121 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); | 6138 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); |
6122 } | 6139 } |
6123 } | 6140 } |
6124 | 6141 |
6125 | 6142 |
6126 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 6143 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6185 | 6202 |
6186 | 6203 |
6187 CompileType UnboxUint32Instr::ComputeType() const { | 6204 CompileType UnboxUint32Instr::ComputeType() const { |
6188 return CompileType::Int(); | 6205 return CompileType::Int(); |
6189 } | 6206 } |
6190 | 6207 |
6191 | 6208 |
6192 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, | 6209 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
6193 bool opt) const { | 6210 bool opt) const { |
6194 const intptr_t kNumInputs = 2; | 6211 const intptr_t kNumInputs = 2; |
6195 const intptr_t kNumTemps = 0; | 6212 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; |
6196 LocationSummary* summary = new(isolate) LocationSummary( | 6213 LocationSummary* summary = new(isolate) LocationSummary( |
6197 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6214 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6198 summary->set_in(0, Location::RequiresRegister()); | 6215 if (op_kind() == Token::kMUL) { |
| 6216 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 6217 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 6218 } else { |
| 6219 summary->set_in(0, Location::RequiresRegister()); |
| 6220 } |
6199 summary->set_in(1, Location::RequiresRegister()); | 6221 summary->set_in(1, Location::RequiresRegister()); |
6200 summary->set_out(0, Location::SameAsFirstInput()); | 6222 summary->set_out(0, Location::SameAsFirstInput()); |
6201 return summary; | 6223 return summary; |
6202 } | 6224 } |
6203 | 6225 |
6204 | 6226 |
6205 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6227 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6206 Register left = locs()->in(0).reg(); | 6228 Register left = locs()->in(0).reg(); |
6207 Register right = locs()->in(1).reg(); | 6229 Register right = locs()->in(1).reg(); |
6208 Register out = locs()->out(0).reg(); | 6230 Register out = locs()->out(0).reg(); |
6209 ASSERT(out == left); | 6231 ASSERT(out == left); |
6210 switch (op_kind()) { | 6232 switch (op_kind()) { |
6211 case Token::kBIT_AND: | 6233 case Token::kBIT_AND: |
6212 __ andl(out, right); | 6234 __ andl(out, right); |
6213 break; | 6235 break; |
6214 case Token::kBIT_OR: | 6236 case Token::kBIT_OR: |
6215 __ orl(out, right); | 6237 __ orl(out, right); |
6216 break; | 6238 break; |
6217 case Token::kBIT_XOR: | 6239 case Token::kBIT_XOR: |
6218 __ xorl(out, right); | 6240 __ xorl(out, right); |
6219 break; | 6241 break; |
6220 case Token::kADD: | 6242 case Token::kADD: |
6221 __ addl(out, right); | 6243 __ addl(out, right); |
6222 break; | 6244 break; |
6223 case Token::kSUB: | 6245 case Token::kSUB: |
6224 __ subl(out, right); | 6246 __ subl(out, right); |
6225 break; | 6247 break; |
| 6248 case Token::kMUL: |
| 6249 __ mull(right); // Result in EDX:EAX. |
| 6250 ASSERT(out == EAX); |
| 6251 ASSERT(locs()->temp(0).reg() == EDX); |
| 6252 break; |
6226 default: | 6253 default: |
6227 UNREACHABLE(); | 6254 UNREACHABLE(); |
6228 } | 6255 } |
6229 } | 6256 } |
6230 | 6257 |
6231 | 6258 |
6232 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, | 6259 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
6233 bool opt) const { | 6260 bool opt) const { |
6234 const intptr_t kNumInputs = 2; | 6261 const intptr_t kNumInputs = 2; |
6235 const intptr_t kNumTemps = 0; | 6262 const intptr_t kNumTemps = 0; |
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6830 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6857 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6831 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6858 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6832 #endif | 6859 #endif |
6833 } | 6860 } |
6834 | 6861 |
6835 } // namespace dart | 6862 } // namespace dart |
6836 | 6863 |
6837 #undef __ | 6864 #undef __ |
6838 | 6865 |
6839 #endif // defined TARGET_ARCH_IA32 | 6866 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |