mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 12:30:03 +00:00
Fixes obo error in javascript int checking.
R=srdjan@google.com Review URL: https://codereview.chromium.org//21876005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@25733 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
7451cf3add
commit
f60d2f6df4
|
@ -99,7 +99,7 @@ class _IntegerImplementation {
|
|||
final int EQUAL = 0, LESS = -1, GREATER = 1;
|
||||
if (other is double) {
|
||||
// TODO(floitsch): the following locals should be 'const'.
|
||||
int MAX_EXACT_INT_TO_DOUBLE = 9007199254740991; // 2^53 - 1.
|
||||
int MAX_EXACT_INT_TO_DOUBLE = 9007199254740992; // 2^53.
|
||||
int MIN_EXACT_INT_TO_DOUBLE = -MAX_EXACT_INT_TO_DOUBLE;
|
||||
double d = other;
|
||||
if (d.isInfinite) {
|
||||
|
|
|
@ -2151,20 +2151,15 @@ void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
}
|
||||
|
||||
|
||||
static void Emit54BitOverflowCheck(FlowGraphCompiler* compiler,
|
||||
Label* overflow,
|
||||
Register result) {
|
||||
static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler,
|
||||
Label* overflow,
|
||||
Register result) {
|
||||
if (FLAG_throw_on_javascript_int_overflow) {
|
||||
ASSERT(overflow != NULL);
|
||||
__ movq(TMP, result); // result is a tagged Smi.
|
||||
// Bits 55...64 must be all 0 or all 1. (It would be bit 54, but result
|
||||
// is tagged.)
|
||||
__ shlq(result, Immediate(64 - 55));
|
||||
__ sarq(result, Immediate(64 - 55));
|
||||
__ cmpq(result, TMP);
|
||||
__ j(NOT_EQUAL, overflow); // 54-bit overflow.
|
||||
__ cmpq(result, Immediate(-0x1FFFFFFFFFFFFFLL - 1));
|
||||
__ j(EQUAL, overflow); // The most negative 54-bit int is also disallowed.
|
||||
__ cmpq(result, Immediate(-0x20000000000000));
|
||||
__ j(LESS, overflow);
|
||||
__ cmpq(result, Immediate(0x20000000000000));
|
||||
__ j(GREATER, overflow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2208,7 +2203,7 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
|
|||
// Shift for result now we know there is no overflow.
|
||||
__ shlq(left, Immediate(value));
|
||||
}
|
||||
Emit54BitOverflowCheck(compiler, deopt, result);
|
||||
EmitJavascriptOverflowCheck(compiler, deopt, result);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2238,7 +2233,7 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
|
|||
__ SmiUntag(right);
|
||||
__ shlq(left, right);
|
||||
}
|
||||
Emit54BitOverflowCheck(compiler, deopt, result);
|
||||
EmitJavascriptOverflowCheck(compiler, deopt, result);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2289,7 +2284,7 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
|
|||
// Shift for result now we know there is no overflow.
|
||||
__ shlq(left, right);
|
||||
}
|
||||
Emit54BitOverflowCheck(compiler, deopt, result);
|
||||
EmitJavascriptOverflowCheck(compiler, deopt, result);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2488,7 +2483,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
Emit54BitOverflowCheck(compiler, deopt, result);
|
||||
EmitJavascriptOverflowCheck(compiler, deopt, result);
|
||||
return;
|
||||
} // locs()->in(1).IsConstant().
|
||||
|
||||
|
@ -2531,7 +2526,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
Emit54BitOverflowCheck(compiler, deopt, result);
|
||||
EmitJavascriptOverflowCheck(compiler, deopt, result);
|
||||
return;
|
||||
} // locs()->in(1).IsStackSlot().
|
||||
|
||||
|
@ -2661,7 +2656,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
Emit54BitOverflowCheck(compiler, deopt, result);
|
||||
EmitJavascriptOverflowCheck(compiler, deopt, result);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3839,7 +3834,7 @@ void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
kDeoptUnaryOp);
|
||||
__ negq(value);
|
||||
__ j(OVERFLOW, deopt);
|
||||
Emit54BitOverflowCheck(compiler, deopt, value);
|
||||
EmitJavascriptOverflowCheck(compiler, deopt, value);
|
||||
break;
|
||||
}
|
||||
case Token::kBIT_NOT:
|
||||
|
@ -3900,7 +3895,7 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
__ shlq(temp, Immediate(1));
|
||||
__ j(OVERFLOW, &do_call, Assembler::kNearJump);
|
||||
__ SmiTag(result);
|
||||
Emit54BitOverflowCheck(compiler, &do_call, result);
|
||||
EmitJavascriptOverflowCheck(compiler, &do_call, result);
|
||||
__ jmp(&done);
|
||||
__ Bind(&do_call);
|
||||
ASSERT(instance_call()->HasICData());
|
||||
|
@ -3946,7 +3941,7 @@ void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
__ shlq(temp, Immediate(1));
|
||||
__ j(OVERFLOW, deopt);
|
||||
__ SmiTag(result);
|
||||
Emit54BitOverflowCheck(compiler, deopt, result);
|
||||
EmitJavascriptOverflowCheck(compiler, deopt, result);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11407,7 +11407,7 @@ RawInteger* Integer::New(const String& str, Heap::Space space) {
|
|||
|
||||
|
||||
// This is called from LiteralToken::New() in the parser, so we can't
|
||||
// raise an exception for 54-bit overflow here. Instead we do it in
|
||||
// raise an exception for javascript overflow here. Instead we do it in
|
||||
// Parser::CurrentIntegerLiteral(), which is the point in the parser where
|
||||
// integer literals escape, so we can call Parser::ErrorMsg().
|
||||
RawInteger* Integer::NewCanonical(const String& str) {
|
||||
|
@ -11427,13 +11427,10 @@ RawInteger* Integer::NewCanonical(const String& str) {
|
|||
}
|
||||
|
||||
|
||||
// dart2js represents integers as double precision floats. It does this using
|
||||
// a sign bit and 53 fraction bits. This gives us the range
|
||||
// -2^54 - 1 ... 2^54 - 1, i.e. the same as a 54-bit signed integer
|
||||
// without the most negative number. Thus, here we check if the value is
|
||||
// a 54-bit signed integer and not -2^54
|
||||
static bool Is54BitNoMinInt(int64_t value) {
|
||||
return (Utils::IsInt(54, value)) && (value != (-0x1FFFFFFFFFFFFFLL - 1));
|
||||
// dart2js represents integers as double precision floats, which can represent
|
||||
// anything in the range -2^53 ... 2^53.
|
||||
static bool IsJavascriptInt(int64_t value) {
|
||||
return ((-0x20000000000000LL <= value) && (value <= 0x20000000000000LL));
|
||||
}
|
||||
|
||||
|
||||
|
@ -11441,7 +11438,7 @@ RawInteger* Integer::New(int64_t value, Heap::Space space) {
|
|||
if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) {
|
||||
return Smi::New(value);
|
||||
}
|
||||
if (FLAG_throw_on_javascript_int_overflow && !Is54BitNoMinInt(value)) {
|
||||
if (FLAG_throw_on_javascript_int_overflow && !IsJavascriptInt(value)) {
|
||||
const Integer &i = Integer::Handle(Mint::New(value));
|
||||
ThrowJavascriptIntegerOverflow(i);
|
||||
}
|
||||
|
@ -11482,7 +11479,7 @@ int Integer::CompareWith(const Integer& other) const {
|
|||
|
||||
|
||||
// Returns true if the signed Integer does not fit into a
|
||||
// Javascript (54-bit) integer.
|
||||
// Javascript integer.
|
||||
bool Integer::CheckJavascriptIntegerOverflow() const {
|
||||
// Always overflow if the value doesn't fit into an int64_t.
|
||||
int64_t value = 1ULL << 63;
|
||||
|
@ -11500,7 +11497,7 @@ bool Integer::CheckJavascriptIntegerOverflow() const {
|
|||
value = BigintOperations::ToInt64(big_value);
|
||||
}
|
||||
}
|
||||
return !Is54BitNoMinInt(value);
|
||||
return !IsJavascriptInt(value);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
import "package:expect/expect.dart";
|
||||
|
||||
int literals() {
|
||||
var okay_literal = 0x1FFFFFFFFFFFFF;
|
||||
var too_big_literal = 0x20000000000000; /// 01: compile-time error
|
||||
var okay_literal = 0x20000000000000;
|
||||
var too_big_literal = 0x20000000000001; /// 01: compile-time error
|
||||
return okay_literal;
|
||||
}
|
||||
|
||||
main() {
|
||||
Expect.equals(0x1FFFFFFFFFFFFF, literals());
|
||||
Expect.equals(0x20000000000000, literals());
|
||||
}
|
||||
|
|
|
@ -29,12 +29,12 @@ int integer_shift() {
|
|||
|
||||
|
||||
int max_add_throws() {
|
||||
return 0x1FFFFFFFFFFFFF + 1;
|
||||
return 0x20000000000000 + 1;
|
||||
}
|
||||
|
||||
|
||||
int min_sub_throws() {
|
||||
return -0x1FFFFFFFFFFFFF - 1;
|
||||
return -0x20000000000000 - 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,12 +45,12 @@ int negate() {
|
|||
|
||||
|
||||
int max_literal() {
|
||||
return 0x1FFFFFFFFFFFFF;
|
||||
return 0x20000000000000;
|
||||
}
|
||||
|
||||
|
||||
int min_literal() {
|
||||
var min_literal = -0x1FFFFFFFFFFFFF;
|
||||
var min_literal = -0x20000000000000;
|
||||
return min_literal;
|
||||
}
|
||||
|
||||
|
@ -60,21 +60,21 @@ bool isJavascriptIntError(e) =>
|
|||
e is Error && "$e".startsWith("Javascript Integer Overflow:");
|
||||
|
||||
main() {
|
||||
Expect.equals(0x1FFFFFFFFFFFFF, max_literal());
|
||||
Expect.equals(-0x1FFFFFFFFFFFFF, min_literal());
|
||||
Expect.equals(0x20000000000000, max_literal());
|
||||
Expect.equals(-0x20000000000000, min_literal());
|
||||
|
||||
// Run the tests once before optimizations.
|
||||
dti_arg = 1.9e16;
|
||||
dti_arg = 1.9e17;
|
||||
Expect.throws(double_to_int, isJavascriptIntError);
|
||||
|
||||
ia_arg1 = (1 << 52);
|
||||
ia_arg2 = (1 << 52);
|
||||
ia_arg1 = (1 << 53);
|
||||
ia_arg2 = (1 << 53);
|
||||
Expect.throws(integer_add, isJavascriptIntError);
|
||||
|
||||
n_arg = -0x1FFFFFFFFFFFFF;
|
||||
Expect.equals(0x1FFFFFFFFFFFFF, negate());
|
||||
n_arg = -0x20000000000000;
|
||||
Expect.equals(0x20000000000000, negate());
|
||||
|
||||
is_arg = (1 << 52);
|
||||
is_arg = (1 << 53);
|
||||
Expect.throws(integer_shift, isJavascriptIntError);
|
||||
|
||||
Expect.throws(max_add_throws, isJavascriptIntError);
|
||||
|
@ -101,17 +101,17 @@ main() {
|
|||
}
|
||||
|
||||
// The optimized functions should now deoptimize and throw the error.
|
||||
dti_arg = 1.9e16;
|
||||
dti_arg = 1.9e17;
|
||||
Expect.throws(double_to_int, isJavascriptIntError);
|
||||
|
||||
ia_arg1 = (1 << 52);
|
||||
ia_arg2 = (1 << 52);
|
||||
ia_arg1 = (1 << 53);
|
||||
ia_arg2 = (1 << 53);
|
||||
Expect.throws(integer_add, isJavascriptIntError);
|
||||
|
||||
n_arg = -0x1FFFFFFFFFFFFF;
|
||||
Expect.equals(0x1FFFFFFFFFFFFF, negate());
|
||||
n_arg = -0x20000000000000;
|
||||
Expect.equals(0x20000000000000, negate());
|
||||
|
||||
is_arg = (1 << 52);
|
||||
is_arg = (1 << 53);
|
||||
Expect.throws(integer_shift, isJavascriptIntError);
|
||||
|
||||
Expect.throws(max_add_throws, isJavascriptIntError);
|
||||
|
|
Loading…
Reference in a new issue