Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: runtime/lib/integers.cc

Issue 2974633003: Option to truncate integers to 64 bits, part 1 (core VM changes) (Closed)
Patch Set: Corrections in comments Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698