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 case Token::kADD: | |
5851 case Token::kSUB: { | |
5850 const intptr_t kNumTemps = 0; | 5852 const intptr_t kNumTemps = 0; |
5851 LocationSummary* summary = new(isolate) LocationSummary( | 5853 LocationSummary* summary = new(isolate) LocationSummary( |
5852 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5854 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5853 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5855 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5854 Location::RequiresRegister())); | 5856 Location::RequiresRegister())); |
5855 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | 5857 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
5856 Location::RequiresRegister())); | 5858 Location::RequiresRegister())); |
5857 summary->set_out(0, Location::SameAsFirstInput()); | 5859 summary->set_out(0, Location::SameAsFirstInput()); |
5858 return summary; | 5860 return summary; |
5859 } | 5861 } |
5860 case Token::kADD: | 5862 case Token::kMUL: { |
5861 case Token::kSUB: { | |
5862 const intptr_t kNumTemps = 0; | 5863 const intptr_t kNumTemps = 0; |
5863 LocationSummary* summary = new(isolate) LocationSummary( | 5864 LocationSummary* summary = new(isolate) LocationSummary( |
5864 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5865 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5865 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5866 summary->set_in(0, Location::Pair(Location::RegisterLocation(EAX), |
5866 Location::RequiresRegister())); | 5867 Location::RegisterLocation(EDX))); |
5867 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | 5868 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
5868 Location::RequiresRegister())); | 5869 Location::RequiresRegister())); |
5869 summary->set_out(0, Location::SameAsFirstInput()); | 5870 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
5871 Location::RegisterLocation(EDX))); | |
5870 return summary; | 5872 return summary; |
5871 } | 5873 } |
5872 default: | 5874 default: |
5873 UNREACHABLE(); | 5875 UNREACHABLE(); |
5874 return NULL; | 5876 return NULL; |
5875 } | 5877 } |
5876 } | 5878 } |
5877 | 5879 |
5878 | 5880 |
5879 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5881 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5913 __ adcl(left_hi, right_hi); | 5915 __ adcl(left_hi, right_hi); |
5914 } else { | 5916 } else { |
5915 __ subl(left_lo, right_lo); | 5917 __ subl(left_lo, right_lo); |
5916 __ sbbl(left_hi, right_hi); | 5918 __ sbbl(left_hi, right_hi); |
5917 } | 5919 } |
5918 if (can_overflow()) { | 5920 if (can_overflow()) { |
5919 __ j(OVERFLOW, deopt); | 5921 __ j(OVERFLOW, deopt); |
5920 } | 5922 } |
5921 break; | 5923 break; |
5922 } | 5924 } |
5925 case Token::kMUL: { | |
5926 // We only support the multiplication of two positive 32-bit integers | |
5927 // resulting in a positive 64-bit integer fitting in a mint. | |
5928 // We deopt in all other cases. | |
5929 // This guarantees that the multiplication of 16-bit unsigned integers, | |
5930 // as used in bignum arithmetic, will always succeed. | |
5931 __ orl(left_hi, right_hi); | |
5932 __ j(NOT_ZERO, deopt); | |
5933 ASSERT(left_lo == EAX); | |
5934 __ mull(right_lo); // Result in EDX:EAX. | |
5935 ASSERT(out_lo == EAX); | |
5936 ASSERT(out_hi == EDX); | |
5937 if (can_overflow()) { | |
5938 __ testl(out_hi, Immediate(0xc0000000)); | |
5939 __ j(NOT_ZERO, deopt); | |
Vyacheslav Egorov (Google)
2014/07/16 19:51:22
I am very wary of this kind of optimistic optimiza
regis
2014/07/16 23:12:42
Fair enough. I have added a range check, so that t
| |
5940 } | |
5941 break; | |
5942 } | |
5923 default: UNREACHABLE(); | 5943 default: UNREACHABLE(); |
5924 } | 5944 } |
5925 if (FLAG_throw_on_javascript_int_overflow) { | 5945 if (FLAG_throw_on_javascript_int_overflow) { |
5926 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); | 5946 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); |
5927 } | 5947 } |
5928 } | 5948 } |
5929 | 5949 |
5930 | 5950 |
5931 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5951 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, |
5932 bool opt) const { | 5952 bool opt) const { |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6186 | 6206 |
6187 | 6207 |
6188 CompileType UnboxUint32Instr::ComputeType() const { | 6208 CompileType UnboxUint32Instr::ComputeType() const { |
6189 return CompileType::Int(); | 6209 return CompileType::Int(); |
6190 } | 6210 } |
6191 | 6211 |
6192 | 6212 |
6193 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, | 6213 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
6194 bool opt) const { | 6214 bool opt) const { |
6195 const intptr_t kNumInputs = 2; | 6215 const intptr_t kNumInputs = 2; |
6196 const intptr_t kNumTemps = 0; | 6216 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; |
6197 LocationSummary* summary = new(isolate) LocationSummary( | 6217 LocationSummary* summary = new(isolate) LocationSummary( |
6198 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6218 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6199 summary->set_in(0, Location::RequiresRegister()); | 6219 if (op_kind() == Token::kMUL) { |
6220 summary->set_in(0, Location::RegisterLocation(EAX)); | |
6221 summary->set_temp(0, Location::RegisterLocation(EDX)); | |
6222 } else { | |
6223 summary->set_in(0, Location::RequiresRegister()); | |
6224 } | |
6200 summary->set_in(1, Location::RequiresRegister()); | 6225 summary->set_in(1, Location::RequiresRegister()); |
6201 summary->set_out(0, Location::SameAsFirstInput()); | 6226 summary->set_out(0, Location::SameAsFirstInput()); |
6202 return summary; | 6227 return summary; |
6203 } | 6228 } |
6204 | 6229 |
6205 | 6230 |
6206 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6231 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6207 Register left = locs()->in(0).reg(); | 6232 Register left = locs()->in(0).reg(); |
6208 Register right = locs()->in(1).reg(); | 6233 Register right = locs()->in(1).reg(); |
6209 Register out = locs()->out(0).reg(); | 6234 Register out = locs()->out(0).reg(); |
6210 ASSERT(out == left); | 6235 ASSERT(out == left); |
6236 Label* deopt = CanDeoptimize() ? | |
6237 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryUint32Op) : NULL; | |
6211 switch (op_kind()) { | 6238 switch (op_kind()) { |
6212 case Token::kBIT_AND: | 6239 case Token::kBIT_AND: |
6213 __ andl(out, right); | 6240 __ andl(out, right); |
6214 break; | 6241 break; |
6215 case Token::kBIT_OR: | 6242 case Token::kBIT_OR: |
6216 __ orl(out, right); | 6243 __ orl(out, right); |
6217 break; | 6244 break; |
6218 case Token::kBIT_XOR: | 6245 case Token::kBIT_XOR: |
6219 __ xorl(out, right); | 6246 __ xorl(out, right); |
6220 break; | 6247 break; |
6221 case Token::kADD: | 6248 case Token::kADD: |
6222 __ addl(out, right); | 6249 __ addl(out, right); |
6223 break; | 6250 break; |
6224 case Token::kSUB: | 6251 case Token::kSUB: |
6225 __ subl(out, right); | 6252 __ subl(out, right); |
6226 break; | 6253 break; |
6254 case Token::kMUL: | |
6255 __ mull(right); // Result in EDX:EAX, CF set if EDX != 0. | |
Cutch
2014/07/16 18:09:48
Uint32 operations are only used in places where we
regis
2014/07/16 23:12:42
I have removed the overflow check.
| |
6256 __ j(OVERFLOW, deopt); | |
6257 break; | |
6227 default: | 6258 default: |
6228 UNREACHABLE(); | 6259 UNREACHABLE(); |
6229 } | 6260 } |
6230 } | 6261 } |
6231 | 6262 |
6232 | 6263 |
6233 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, | 6264 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
6234 bool opt) const { | 6265 bool opt) const { |
6235 const intptr_t kNumInputs = 2; | 6266 const intptr_t kNumInputs = 2; |
6236 const intptr_t kNumTemps = 0; | 6267 const intptr_t kNumTemps = 0; |
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6831 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6862 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6832 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6863 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6833 #endif | 6864 #endif |
6834 } | 6865 } |
6835 | 6866 |
6836 } // namespace dart | 6867 } // namespace dart |
6837 | 6868 |
6838 #undef __ | 6869 #undef __ |
6839 | 6870 |
6840 #endif // defined TARGET_ARCH_IA32 | 6871 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |