Chromium Code Reviews| 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 "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/dart_api_impl.h" | 9 #include "vm/dart_api_impl.h" |
| 10 #include "vm/exceptions.h" | 10 #include "vm/exceptions.h" |
| 11 #include "vm/isolate.h" | 11 #include "vm/isolate.h" |
| 12 #include "vm/native_entry.h" | 12 #include "vm/native_entry.h" |
| 13 #include "vm/object.h" | 13 #include "vm/object.h" |
| 14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 15 #include "vm/symbols.h" | 15 #include "vm/symbols.h" |
| 16 | 16 |
| 17 namespace dart { | 17 namespace dart { |
| 18 | 18 |
| 19 DEFINE_FLAG(bool, | 19 DEFINE_FLAG(bool, |
| 20 trace_intrinsified_natives, | 20 trace_intrinsified_natives, |
| 21 false, | 21 false, |
| 22 "Report if any of the intrinsified natives are called"); | 22 "Report if any of the intrinsified natives are called"); |
| 23 | 23 |
| 24 // Smi natives. | 24 // Smi natives. |
| 25 | 25 |
| 26 // Returns false if integer is in wrong representation, e.g., as is a Bigint | 26 // Returns false if integer is in wrong representation, e.g., as is a Bigint |
| 27 // when it could have been a Smi. | 27 // when it could have been a Smi. |
| 28 static bool CheckInteger(const Integer& i) { | 28 static bool CheckInteger(const Integer& i) { |
| 29 if (i.IsBigint()) { | 29 if (i.IsBigint()) { |
| 30 ASSERT(!FLAG_truncate_ints_to_64_bits); | |
| 30 const Bigint& bigint = Bigint::Cast(i); | 31 const Bigint& bigint = Bigint::Cast(i); |
| 31 return !bigint.FitsIntoSmi() && !bigint.FitsIntoInt64(); | 32 return !bigint.FitsIntoSmi() && !bigint.FitsIntoInt64(); |
| 32 } | 33 } |
| 33 if (i.IsMint()) { | 34 if (i.IsMint()) { |
| 34 const Mint& mint = Mint::Cast(i); | 35 const Mint& mint = Mint::Cast(i); |
| 35 return !Smi::IsValid(mint.value()); | 36 return !Smi::IsValid(mint.value()); |
| 36 } | 37 } |
| 37 return true; | 38 return true; |
| 38 } | 39 } |
| 39 | 40 |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 const Smi& amount) { | 254 const Smi& amount) { |
| 254 if (amount.Value() < 0) { | 255 if (amount.Value() < 0) { |
| 255 Exceptions::ThrowArgumentError(amount); | 256 Exceptions::ThrowArgumentError(amount); |
| 256 } | 257 } |
| 257 if (value.IsSmi()) { | 258 if (value.IsSmi()) { |
| 258 const Smi& smi_value = Smi::Cast(value); | 259 const Smi& smi_value = Smi::Cast(value); |
| 259 return smi_value.ShiftOp(kind, amount, Heap::kNew); | 260 return smi_value.ShiftOp(kind, amount, Heap::kNew); |
| 260 } | 261 } |
| 261 if (value.IsMint()) { | 262 if (value.IsMint()) { |
| 262 const int64_t mint_value = value.AsInt64Value(); | 263 const int64_t mint_value = value.AsInt64Value(); |
| 263 const int count = Utils::HighestBit(mint_value); | |
| 264 intptr_t shift_count = amount.Value(); | 264 intptr_t shift_count = amount.Value(); |
| 265 if (kind == Token::kSHR) { | 265 switch (kind) { |
| 266 shift_count = -shift_count; | 266 case Token::kSHL: |
| 267 } | 267 if (FLAG_truncate_ints_to_64_bits) { |
| 268 if ((count + shift_count) < Mint::kBits) { | 268 return Integer::New( |
| 269 switch (kind) { | 269 Utils::ShiftLeftWithTruncation(mint_value, shift_count), |
| 270 case Token::kSHL: | 270 Heap::kNew); |
| 271 return Integer::New(mint_value << shift_count, Heap::kNew); | 271 } else { |
| 272 case Token::kSHR: | 272 const int count = Utils::HighestBit(mint_value); |
| 273 shift_count = | 273 if (shift_count < (Mint::kBits - count)) { |
| 274 (-shift_count > Mint::kBits) ? Mint::kBits : -shift_count; | 274 return Integer::New(mint_value << shift_count, Heap::kNew); |
| 275 return Integer::New(mint_value >> shift_count, Heap::kNew); | 275 } else { |
| 276 default: | 276 // Overflow in shift, use Bigints |
| 277 UNIMPLEMENTED(); | 277 return Integer::null(); |
| 278 } | 278 } |
| 279 } else { | 279 } |
| 280 // Overflow in shift, use Bigints | 280 case Token::kSHR: |
| 281 return Integer::null(); | 281 shift_count = Utils::Minimum(shift_count, Mint::kBits); |
| 282 return Integer::New(mint_value >> shift_count, Heap::kNew); | |
| 283 default: | |
| 284 UNIMPLEMENTED(); | |
| 282 } | 285 } |
| 283 } else { | 286 } else { |
| 284 ASSERT(value.IsBigint()); | 287 ASSERT(value.IsBigint()); |
| 285 } | 288 } |
| 289 ASSERT(!FLAG_truncate_ints_to_64_bits); | |
| 286 return Integer::null(); | 290 return Integer::null(); |
| 287 } | 291 } |
| 288 | 292 |
| 289 | 293 |
| 290 DEFINE_NATIVE_ENTRY(Smi_bitAndFromSmi, 2) { | 294 DEFINE_NATIVE_ENTRY(Smi_bitAndFromSmi, 2) { |
| 291 const Smi& left = Smi::CheckedHandle(arguments->NativeArgAt(0)); | 295 const Smi& left = Smi::CheckedHandle(arguments->NativeArgAt(0)); |
| 292 GET_NON_NULL_NATIVE_ARGUMENT(Smi, right, arguments->NativeArgAt(1)); | 296 GET_NON_NULL_NATIVE_ARGUMENT(Smi, right, arguments->NativeArgAt(1)); |
| 293 if (FLAG_trace_intrinsified_natives) { | 297 if (FLAG_trace_intrinsified_natives) { |
| 294 OS::Print("Smi_bitAndFromSmi %s & %s\n", left.ToCString(), | 298 OS::Print("Smi_bitAndFromSmi %s & %s\n", left.ToCString(), |
| 295 right.ToCString()); | 299 right.ToCString()); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 402 } | 406 } |
| 403 | 407 |
| 404 | 408 |
| 405 DEFINE_NATIVE_ENTRY(Bigint_getDigits, 1) { | 409 DEFINE_NATIVE_ENTRY(Bigint_getDigits, 1) { |
| 406 const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0)); | 410 const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0)); |
| 407 return bigint.digits(); | 411 return bigint.digits(); |
| 408 } | 412 } |
| 409 | 413 |
| 410 | 414 |
| 411 DEFINE_NATIVE_ENTRY(Bigint_allocate, 4) { | 415 DEFINE_NATIVE_ENTRY(Bigint_allocate, 4) { |
| 416 // TODO(alexmarkov): Consider throwing error if --truncate-ints-to-64-bits. | |
| 412 if (FLAG_limit_ints_to_64_bits) { | 417 if (FLAG_limit_ints_to_64_bits) { |
|
siva
2017/07/07 23:11:20
Not sure I understand why we should have two flags
alexmarkov
2017/07/10 16:58:12
Done.
| |
| 413 // The allocated Bigint value is not necessarily out of range, but it may | 418 // The allocated Bigint value is not necessarily out of range, but it may |
| 414 // be used as an operand in an operation resulting in a Bigint. | 419 // be used as an operand in an operation resulting in a Bigint. |
| 415 Exceptions::ThrowRangeErrorMsg( | 420 Exceptions::ThrowRangeErrorMsg( |
| 416 "Integer operand requires conversion to Bigint"); | 421 "Integer operand requires conversion to Bigint"); |
| 417 } | 422 } |
| 418 // First arg is null type arguments, since class Bigint is not parameterized. | 423 // First arg is null type arguments, since class Bigint is not parameterized. |
| 419 const Bool& neg = Bool::CheckedHandle(arguments->NativeArgAt(1)); | 424 const Bool& neg = Bool::CheckedHandle(arguments->NativeArgAt(1)); |
| 420 const Smi& used = Smi::CheckedHandle(arguments->NativeArgAt(2)); | 425 const Smi& used = Smi::CheckedHandle(arguments->NativeArgAt(2)); |
| 421 const TypedData& digits = TypedData::CheckedHandle(arguments->NativeArgAt(3)); | 426 const TypedData& digits = TypedData::CheckedHandle(arguments->NativeArgAt(3)); |
| 422 ASSERT(!digits.IsNull()); | 427 ASSERT(!digits.IsNull()); |
| 423 return Bigint::New(neg.value(), used.Value(), digits); | 428 return Bigint::New(neg.value(), used.Value(), digits); |
| 424 } | 429 } |
| 425 | 430 |
| 426 } // namespace dart | 431 } // namespace dart |
| OLD | NEW |