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

Unified Diff: runtime/vm/object.cc

Issue 2974633003: Option to truncate integers to 64 bits, part 1 (core VM changes) (Closed)
Patch Set: Merged 2 flags into 1 (--limit-ints-to-64-bits) 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/intermediate_language_x64.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index bb9334f92b4849e3ff4e40c8f7934707bfc5d433..0eb69a9d0bb9b786bb69e2b71c623918f0e892d3 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -18998,7 +18998,11 @@ RawInteger* Integer::New(const String& str, Heap::Space space) {
Bigint::Handle(Bigint::NewFromCString(str.ToCString(), space));
ASSERT(!big.FitsIntoSmi());
ASSERT(!big.FitsIntoInt64());
- return big.raw();
+ if (!FLAG_limit_ints_to_64_bits) {
+ return big.raw();
+ }
+ // TODO(alexmarkov): Throw error in FLAG_limit_ints_to_64_bits mode.
+ value = big.AsTruncatedInt64Value();
}
return Integer::New(value, space);
}
@@ -19012,7 +19016,11 @@ RawInteger* Integer::NewCanonical(const String& str) {
const Bigint& big = Bigint::Handle(Bigint::NewCanonical(str));
ASSERT(!big.FitsIntoSmi());
ASSERT(!big.FitsIntoInt64());
- return big.raw();
+ if (!FLAG_limit_ints_to_64_bits) {
+ return big.raw();
+ }
+ // TODO(alexmarkov): Throw error in FLAG_limit_ints_to_64_bits mode.
+ value = big.AsTruncatedInt64Value();
}
if (Smi::IsValid(value)) {
return Smi::New(static_cast<intptr_t>(value));
@@ -19032,7 +19040,12 @@ RawInteger* Integer::New(int64_t value, Heap::Space space) {
RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) {
if (value > static_cast<uint64_t>(Mint::kMaxValue)) {
- return Bigint::NewFromUint64(value, space);
+ if (FLAG_limit_ints_to_64_bits) {
+ // TODO(alexmarkov): Throw error in FLAG_limit_ints_to_64_bits mode.
+ return Integer::New(static_cast<int64_t>(value), space);
+ } else {
+ return Bigint::NewFromUint64(value, space);
+ }
} else {
return Integer::New(value, space);
}
@@ -19141,13 +19154,18 @@ RawInteger* Integer::ArithmeticOp(Token::Kind operation,
static_cast<int64_t>(right_value),
space);
} else {
- // In 64-bit mode, the product of two signed integers fits in a
- // 64-bit result if the sum of the highest bits of their absolute
- // values is smaller than 62.
ASSERT(sizeof(intptr_t) == sizeof(int64_t));
- if ((Utils::HighestBit(left_value) + Utils::HighestBit(right_value)) <
- 62) {
- return Integer::New(left_value * right_value, space);
+ if (FLAG_limit_ints_to_64_bits) {
+ return Integer::New(
+ Utils::MulWithWrapAround(left_value, right_value), space);
+ } else {
+ // In 64-bit mode, the product of two signed integers fits in a
+ // 64-bit result if the sum of the highest bits of their absolute
+ // values is smaller than 62.
+ if ((Utils::HighestBit(left_value) +
+ Utils::HighestBit(right_value)) < 62) {
+ return Integer::New(left_value * right_value, space);
+ }
}
}
// Perform a Bigint multiplication below.
@@ -19175,26 +19193,47 @@ RawInteger* Integer::ArithmeticOp(Token::Kind operation,
const int64_t right_value = other.AsInt64Value();
switch (operation) {
case Token::kADD: {
- if (!Utils::WillAddOverflow(left_value, right_value)) {
- return Integer::New(left_value + right_value, space);
+ if (FLAG_limit_ints_to_64_bits) {
+ return Integer::New(Utils::AddWithWrapAround(left_value, right_value),
+ space);
+ } else {
+ if (!Utils::WillAddOverflow(left_value, right_value)) {
+ return Integer::New(left_value + right_value, space);
+ }
}
break;
}
case Token::kSUB: {
- if (!Utils::WillSubOverflow(left_value, right_value)) {
- return Integer::New(left_value - right_value, space);
+ if (FLAG_limit_ints_to_64_bits) {
+ return Integer::New(Utils::SubWithWrapAround(left_value, right_value),
+ space);
+ } else {
+ if (!Utils::WillSubOverflow(left_value, right_value)) {
+ return Integer::New(left_value - right_value, space);
+ }
}
break;
}
case Token::kMUL: {
- if ((Utils::HighestBit(left_value) + Utils::HighestBit(right_value)) <
- 62) {
- return Integer::New(left_value * right_value, space);
+ if (FLAG_limit_ints_to_64_bits) {
+ return Integer::New(Utils::MulWithWrapAround(left_value, right_value),
+ space);
+ } else {
+ if ((Utils::HighestBit(left_value) + Utils::HighestBit(right_value)) <
+ 62) {
+ return Integer::New(left_value * right_value, space);
+ }
}
break;
}
case Token::kTRUNCDIV: {
- if ((left_value != Mint::kMinValue) || (right_value != -1)) {
+ if ((left_value == Mint::kMinValue) && (right_value == -1)) {
+ // Division special case: overflow in int64_t.
+ if (FLAG_limit_ints_to_64_bits) {
+ // MIN_VALUE / -1 = (MAX_VALUE + 1), which wraps around to MIN_VALUE
+ return Integer::New(Mint::kMinValue, space);
+ }
+ } else {
return Integer::New(left_value / right_value, space);
}
break;
@@ -19214,6 +19253,7 @@ RawInteger* Integer::ArithmeticOp(Token::Kind operation,
UNIMPLEMENTED();
}
}
+ ASSERT(!FLAG_limit_ints_to_64_bits);
return Integer::null(); // Notify caller that a bigint operation is required.
}
@@ -19259,6 +19299,7 @@ RawInteger* Integer::BitOp(Token::Kind kind,
UNIMPLEMENTED();
}
}
+ ASSERT(!FLAG_limit_ints_to_64_bits);
return Integer::null(); // Notify caller that a bigint operation is required.
}
@@ -19278,12 +19319,18 @@ RawInteger* Smi::ShiftOp(Token::Kind kind,
}
{ // Check for overflow.
int cnt = Utils::BitLength(left_value);
- if ((cnt + right_value) > Smi::kBits) {
- if ((cnt + right_value) > Mint::kBits) {
- return Bigint::NewFromShiftedInt64(left_value, right_value, space);
+ if (right_value > (Smi::kBits - cnt)) {
+ if (FLAG_limit_ints_to_64_bits) {
+ return Integer::New(
+ Utils::ShiftLeftWithTruncation(left_value, right_value), space);
} else {
- int64_t left_64 = left_value;
- return Integer::New(left_64 << right_value, space);
+ if (right_value > (Mint::kBits - cnt)) {
+ return Bigint::NewFromShiftedInt64(left_value, right_value,
+ space);
+ } else {
+ int64_t left_64 = left_value;
+ return Integer::New(left_64 << right_value, space);
+ }
}
}
}
@@ -19705,6 +19752,7 @@ bool Bigint::CheckAndCanonicalizeFields(Thread* thread,
RawBigint* Bigint::New(Heap::Space space) {
+ // TODO(alexmarkov): Throw error or assert in --limit-ints-to-64-bits mode.
zra 2017/07/10 21:54:03 ... until there's something in the language spec o
alexmarkov 2017/07/10 22:21:54 Acknowledged.
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
@@ -19728,6 +19776,7 @@ RawBigint* Bigint::New(bool neg,
intptr_t used,
const TypedData& digits,
Heap::Space space) {
+ // TODO(alexmarkov): Throw error or assert in --limit-ints-to-64-bits mode.
ASSERT((used == 0) ||
(!digits.IsNull() && (digits.Length() >= (used + (used & 1)))));
Thread* thread = Thread::Current();
@@ -19767,6 +19816,7 @@ RawBigint* Bigint::New(bool neg,
RawBigint* Bigint::NewFromInt64(int64_t value, Heap::Space space) {
// Currently only used to convert Smi or Mint to hex String, therefore do
// not throw RangeError if --limit-ints-to-64-bits.
+ // TODO(alexmarkov): Throw error or assert in --limit-ints-to-64-bits mode.
const TypedData& digits = TypedData::Handle(NewDigits(2, space));
bool neg;
uint64_t abs_value;
@@ -19784,10 +19834,9 @@ RawBigint* Bigint::NewFromInt64(int64_t value, Heap::Space space) {
RawBigint* Bigint::NewFromUint64(uint64_t value, Heap::Space space) {
- if (FLAG_limit_ints_to_64_bits) {
- Exceptions::ThrowRangeErrorMsg(
- "Integer operand requires conversion to Bigint");
- }
+ // TODO(alexmarkov): Revise this assertion if this factory method is used
+ // to explicitly allocate Bigint objects in --limit-ints-to-64-bits mode.
+ ASSERT(!FLAG_limit_ints_to_64_bits);
const TypedData& digits = TypedData::Handle(NewDigits(2, space));
SetDigitAt(digits, 0, static_cast<uint32_t>(value));
SetDigitAt(digits, 1, static_cast<uint32_t>(value >> 32));
@@ -19798,12 +19847,9 @@ RawBigint* Bigint::NewFromUint64(uint64_t value, Heap::Space space) {
RawBigint* Bigint::NewFromShiftedInt64(int64_t value,
intptr_t shift,
Heap::Space space) {
- if (FLAG_limit_ints_to_64_bits) {
- // The allocated Bigint value is not necessarily out of range, but it may
- // be used as an operand in an operation resulting in a Bigint.
- Exceptions::ThrowRangeErrorMsg(
- "Integer operand requires conversion to Bigint");
- }
+ // TODO(alexmarkov): Revise this assertion if this factory method is used
+ // to explicitly allocate Bigint objects in --limit-ints-to-64-bits mode.
+ ASSERT(!FLAG_limit_ints_to_64_bits);
ASSERT(kBitsPerDigit == 32);
ASSERT(shift >= 0);
const intptr_t digit_shift = shift / kBitsPerDigit;
@@ -19835,6 +19881,7 @@ RawBigint* Bigint::NewFromShiftedInt64(int64_t value,
RawBigint* Bigint::NewFromCString(const char* str, Heap::Space space) {
// Allow parser to scan Bigint literal, even with --limit-ints-to-64-bits.
+ // TODO(alexmarkov): Throw error or assert in --limit-ints-to-64-bits mode.
ASSERT(str != NULL);
bool neg = false;
TypedData& digits = TypedData::Handle();
@@ -19857,6 +19904,7 @@ RawBigint* Bigint::NewFromCString(const char* str, Heap::Space space) {
RawBigint* Bigint::NewCanonical(const String& str) {
// Allow parser to scan Bigint literal, even with --limit-ints-to-64-bits.
+ // TODO(alexmarkov): Throw error or assert in --limit-ints-to-64-bits mode.
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
« no previous file with comments | « runtime/vm/intermediate_language_x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698