OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/bootstrap_natives.h" | 5 #include "vm/bootstrap_natives.h" |
6 | 6 |
7 #include "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
9 #include "vm/exceptions.h" | 9 #include "vm/exceptions.h" |
10 #include "vm/native_entry.h" | 10 #include "vm/native_entry.h" |
11 #include "vm/object.h" | 11 #include "vm/object.h" |
12 #include "vm/symbols.h" | 12 #include "vm/symbols.h" |
13 | 13 |
14 namespace dart { | 14 namespace dart { |
15 | 15 |
16 DEFINE_FLAG(bool, trace_intrinsified_natives, false, | 16 DEFINE_FLAG(bool, trace_intrinsified_natives, false, |
17 "Report if any of the intrinsified natives are called"); | 17 "Report if any of the intrinsified natives are called"); |
18 | 18 |
19 // Smi natives. | 19 // Smi natives. |
20 | 20 |
21 // Returns false if integer is in wrong representation, e.g., as is a Bigint | 21 // Returns false if integer is in wrong representation, e.g., as is a Bigint |
22 // when it could have been a Smi. | 22 // when it could have been a Smi. |
23 static bool CheckInteger(const Integer& i) { | 23 static bool CheckInteger(const Integer& i) { |
24 if (i.IsBigint()) { | 24 if (i.IsBigint()) { |
25 Bigint& bigint = Bigint::Handle(); | 25 const Bigint& bigint = Bigint::Cast(i); |
26 bigint |= i.raw(); | |
27 return !BigintOperations::FitsIntoSmi(bigint) && | 26 return !BigintOperations::FitsIntoSmi(bigint) && |
28 !BigintOperations::FitsIntoMint(bigint); | 27 !BigintOperations::FitsIntoMint(bigint); |
29 } | 28 } |
30 if (i.IsMint()) { | 29 if (i.IsMint()) { |
31 Mint& mint = Mint::Handle(); | 30 const Mint& mint = Mint::Cast(i); |
32 mint |= i.raw(); | |
33 return !Smi::IsValid64(mint.value()); | 31 return !Smi::IsValid64(mint.value()); |
34 } | 32 } |
35 return true; | 33 return true; |
36 } | 34 } |
37 | 35 |
38 | 36 |
39 DEFINE_NATIVE_ENTRY(Integer_bitAndFromInteger, 2) { | 37 DEFINE_NATIVE_ENTRY(Integer_bitAndFromInteger, 2) { |
40 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 38 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
41 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); | 39 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); |
42 ASSERT(CheckInteger(right)); | 40 ASSERT(CheckInteger(right)); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 | 208 |
211 static RawInteger* ShiftOperationHelper(Token::Kind kind, | 209 static RawInteger* ShiftOperationHelper(Token::Kind kind, |
212 const Integer& value, | 210 const Integer& value, |
213 const Smi& amount) { | 211 const Smi& amount) { |
214 if (amount.Value() < 0) { | 212 if (amount.Value() < 0) { |
215 const Array& args = Array::Handle(Array::New(1)); | 213 const Array& args = Array::Handle(Array::New(1)); |
216 args.SetAt(0, amount); | 214 args.SetAt(0, amount); |
217 Exceptions::ThrowByType(Exceptions::kArgument, args); | 215 Exceptions::ThrowByType(Exceptions::kArgument, args); |
218 } | 216 } |
219 if (value.IsSmi()) { | 217 if (value.IsSmi()) { |
220 Smi& smi_value = Smi::Handle(); | 218 const Smi& smi_value = Smi::Cast(value); |
221 smi_value |= value.raw(); | |
222 return smi_value.ShiftOp(kind, amount); | 219 return smi_value.ShiftOp(kind, amount); |
223 } | 220 } |
224 Bigint& big_value = Bigint::Handle(); | 221 Bigint& big_value = Bigint::Handle(); |
225 if (value.IsMint()) { | 222 if (value.IsMint()) { |
226 const int64_t mint_value = value.AsInt64Value(); | 223 const int64_t mint_value = value.AsInt64Value(); |
227 const int count = Utils::HighestBit(mint_value); | 224 const int count = Utils::HighestBit(mint_value); |
228 if ((count + amount.Value()) < Mint::kBits) { | 225 if ((count + amount.Value()) < Mint::kBits) { |
229 switch (kind) { | 226 switch (kind) { |
230 case Token::kSHL: | 227 case Token::kSHL: |
231 return Integer::New(mint_value << amount.Value()); | 228 return Integer::New(mint_value << amount.Value()); |
232 case Token::kSHR: | 229 case Token::kSHR: |
233 return Integer::New(mint_value >> amount.Value()); | 230 return Integer::New(mint_value >> amount.Value()); |
234 default: | 231 default: |
235 UNIMPLEMENTED(); | 232 UNIMPLEMENTED(); |
236 } | 233 } |
237 } else { | 234 } else { |
238 // Overflow in shift, use Bigints | 235 // Overflow in shift, use Bigints |
239 big_value = BigintOperations::NewFromInt64(mint_value); | 236 big_value = BigintOperations::NewFromInt64(mint_value); |
240 } | 237 } |
241 } else { | 238 } else { |
242 ASSERT(value.IsBigint()); | 239 ASSERT(value.IsBigint()); |
243 big_value |= value.raw(); | 240 big_value = Bigint::Cast(value).raw(); |
244 } | 241 } |
245 switch (kind) { | 242 switch (kind) { |
246 case Token::kSHL: | 243 case Token::kSHL: |
247 return BigintOperations::ShiftLeft(big_value, amount.Value()); | 244 return BigintOperations::ShiftLeft(big_value, amount.Value()); |
248 case Token::kSHR: | 245 case Token::kSHR: |
249 return BigintOperations::ShiftRight(big_value, amount.Value()); | 246 return BigintOperations::ShiftRight(big_value, amount.Value()); |
250 default: | 247 default: |
251 UNIMPLEMENTED(); | 248 UNIMPLEMENTED(); |
252 } | 249 } |
253 return Integer::null(); | 250 return Integer::null(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 | 304 |
308 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { | 305 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { |
309 const Bigint& value = Bigint::CheckedHandle(arguments->NativeArgAt(0)); | 306 const Bigint& value = Bigint::CheckedHandle(arguments->NativeArgAt(0)); |
310 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); | 307 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); |
311 ASSERT(CheckInteger(value)); | 308 ASSERT(CheckInteger(value)); |
312 ASSERT(CheckInteger(result)); | 309 ASSERT(CheckInteger(result)); |
313 return result.AsValidInteger(); | 310 return result.AsValidInteger(); |
314 } | 311 } |
315 | 312 |
316 } // namespace dart | 313 } // namespace dart |
OLD | NEW |