Chromium Code Reviews| Index: runtime/lib/integers.cc |
| =================================================================== |
| --- runtime/lib/integers.cc (revision 23032) |
| +++ runtime/lib/integers.cc (working copy) |
| @@ -13,6 +13,9 @@ |
| namespace dart { |
| +DEFINE_FLAG(bool, throw_on_53bit_overflow, false, |
| + "Throw an exception when integer arithmetic exceeds 53 bits."); |
| + |
| DEFINE_FLAG(bool, trace_intrinsified_natives, false, |
| "Report if any of the intrinsified natives are called"); |
| @@ -34,6 +37,17 @@ |
| } |
| +// Throw kFiftyThreeBitOverflow if the result of an operation overflows |
| +// 53 bits. |
| +static void ThrowExceptionOnOverflow(const Integer& i, const char* msg) { |
|
siva
2013/05/23 01:28:22
The name ThrowExceptionOnOverflow seems like a gen
zra
2013/05/23 15:59:07
Done.
|
| + if (i.FitsIn53Bits()) return; |
| + const Array& exc_args = Array::Handle(Array::New(1)); |
| + exc_args.SetAt(0, Object::Handle(String::New(msg))); |
| + Exceptions::ThrowByType(Exceptions::kFiftyThreeBitOverflowError, exc_args); |
| + return; |
| +} |
| + |
| + |
| DEFINE_NATIVE_ENTRY(Integer_bitAndFromInteger, 2) { |
| const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
| GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); |
| @@ -45,6 +59,9 @@ |
| } |
| const Integer& result = |
| Integer::Handle(left.BitOp(Token::kBIT_AND, right)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(result, "Integer_bitAndFromInteger"); |
| + } |
| return result.AsValidInteger(); |
| } |
| @@ -60,6 +77,9 @@ |
| } |
| const Integer& result = |
| Integer::Handle(left.BitOp(Token::kBIT_OR, right)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(result, "Integer_bitOrFromInteger"); |
| + } |
| return result.AsValidInteger(); |
| } |
| @@ -75,6 +95,9 @@ |
| } |
| const Integer& result = |
| Integer::Handle(left.BitOp(Token::kBIT_XOR, right)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(result, "Integer_bitXorFromInteger"); |
| + } |
| return result.AsValidInteger(); |
| } |
| @@ -90,6 +113,9 @@ |
| } |
| const Integer& result = |
| Integer::Handle(left_int.ArithmeticOp(Token::kADD, right_int)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(result, "Integer_addFromInteger"); |
| + } |
| return result.AsValidInteger(); |
| } |
| @@ -105,6 +131,9 @@ |
| } |
| const Integer& result = |
| Integer::Handle(left_int.ArithmeticOp(Token::kSUB, right_int)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(result, "Integer_subFromInteger"); |
| + } |
| return result.AsValidInteger(); |
| } |
| @@ -120,6 +149,9 @@ |
| } |
| const Integer& result = |
| Integer::Handle(left_int.ArithmeticOp(Token::kMUL, right_int)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(result, "Integer_mulFromInteger"); |
| + } |
| return result.AsValidInteger(); |
| } |
| @@ -132,6 +164,9 @@ |
| ASSERT(!right_int.IsZero()); |
| const Integer& result = |
| Integer::Handle(left_int.ArithmeticOp(Token::kTRUNCDIV, right_int)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(result, "Integer_trucDivFromInteger"); |
| + } |
| return result.AsValidInteger(); |
| } |
| @@ -151,6 +186,9 @@ |
| } |
| const Integer& result = |
| Integer::Handle(left_int.ArithmeticOp(Token::kMOD, right_int)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(result, "Integer_moduloFromInteger"); |
| + } |
| return result.AsValidInteger(); |
| } |
| @@ -193,7 +231,11 @@ |
| const int64_t int_value = strtoll(cstr, &p_end, 10); |
| if (p_end == (cstr + len)) { |
| if ((int_value != LLONG_MIN) && (int_value != LLONG_MAX)) { |
| - return Integer::New(int_value); |
| + const Integer& i = Integer::Handle(Integer::New(int_value)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(i, "Integer_parse"); |
| + } |
| + return i.AsValidInteger(); |
| } |
| } |
| } |
| @@ -212,7 +254,11 @@ |
| } |
| String& temp = String::Handle(); |
| temp = String::Concat(Symbols::Dash(), *int_string); |
| - return Integer::New(temp); |
| + const Integer& i = Integer::Handle(Integer::New(temp)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(i, "Integer_parse"); |
| + } |
| + return i.AsValidInteger(); |
| } |
| const Array& args = Array::Handle(Array::New(1)); |
| @@ -274,6 +320,9 @@ |
| ASSERT(CheckInteger(value)); |
| const Integer& result = Integer::Handle( |
| ShiftOperationHelper(Token::kSHR, value, amount)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(result, "Smi_shrFromInt"); |
| + } |
| return result.AsValidInteger(); |
| } |
| @@ -290,6 +339,9 @@ |
| } |
| const Integer& result = Integer::Handle( |
| ShiftOperationHelper(Token::kSHL, value, amount)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(result, "Smi_shlFromInt"); |
| + } |
| return result.AsValidInteger(); |
| } |
| @@ -313,7 +365,11 @@ |
| OS::Print("Mint_bitNegate: %s\n", operand.ToCString()); |
| } |
| int64_t result = ~operand.value(); |
| - return Integer::New(result); |
| + const Integer& i = Integer::Handle(Integer::New(result)); |
| + if (FLAG_throw_on_53bit_overflow) { |
| + ThrowExceptionOnOverflow(i, "Integer_bitAndFromInteger"); |
| + } |
| + return i.AsValidInteger(); |
|
siva
2013/05/23 01:28:22
Ditto question about the need for AsValidInteger.
zra
2013/05/23 15:59:07
Done.
|
| } |
| // Bigint natives. |