[VM] Relax constraints for integer literals according to int64 spec

Handling of integer literals is corrected according to the informal spec
for the fixed-size integers:

https://github.com/dart-lang/sdk/blob/master/docs/language/informal/int64.md

This change allows unsigned 64-bit hexadecimal literals and MIN_INT64
to be used when running on the VM with --limit-ints-to-64-bits option.

Change-Id: Ied7a7688768bcf4ff40ab5b499dd71622d2c3948
Reviewed-on: https://dart-review.googlesource.com/19400
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov
2017-11-09 16:58:38 +00:00
committed by commit-bot@chromium.org
parent 76ea9d3dfd
commit 59cdc65dc7
8 changed files with 68 additions and 11 deletions
-2
View File
@@ -75,8 +75,6 @@ static RawInteger* DoubleToInteger(double val, const char* error_msg) {
Exceptions::ThrowByType(Exceptions::kUnsupported, args);
}
if (FLAG_limit_ints_to_64_bits) {
// TODO(alexmarkov): decide on the double-to-integer conversion semantics
// in truncating mode.
int64_t ival = 0;
if (val <= static_cast<double>(kMinInt64)) {
ival = kMinInt64;
@@ -167,6 +167,17 @@ test_shl(var v2, var v3, var v8, var v40) {
}
}
test_literals() {
Expect.equals(0x7fffffffffffffff, 9223372036854775807);
Expect.equals(0x8000000000000000, -9223372036854775808);
Expect.equals(0x8000000000000000, -0x8000000000000000);
Expect.equals(0x8000000000000001, -0x7fffffffffffffff);
Expect.equals(0xabcdef0123456789, -0x543210FEDCBA9877);
Expect.equals(0xffffffffffffffff, -1);
Expect.equals(-9223372036854775808, -0x8000000000000000);
Expect.equals(9223372036854775807 + 1, -9223372036854775808);
}
main() {
var v2 = 2; // smi
var v3 = 3; // smi
@@ -181,4 +192,5 @@ main() {
test_sub(v2, v3, v3fxx, v5fxx, v7fxx, n60xx);
test_mul(v2, v3, v3fxx, v5fxx, v7fxx, n60xx);
test_shl(v2, v3, v8, v40);
test_literals();
}
+21 -4
View File
@@ -18313,12 +18313,22 @@ const char* Integer::ToCString() const {
return "NULL Integer";
}
// String representation of kMaxInt64 + 1.
static const char* kMaxInt64Plus1 = "9223372036854775808";
RawInteger* Integer::New(const String& str, Heap::Space space) {
// We are not supposed to have integers represented as two byte strings.
ASSERT(str.IsOneByteString());
int64_t value;
if (!OS::StringToInt64(str.ToCString(), &value)) {
int64_t value = 0;
const char* cstr = str.ToCString();
if (!OS::StringToInt64(cstr, &value)) {
if (FLAG_limit_ints_to_64_bits) {
if (strcmp(cstr, kMaxInt64Plus1) == 0) {
// Allow MAX_INT64 + 1 integer literal as it can be used as an argument
// of unary minus to produce MIN_INT64 value. The value is automatically
// wrapped to MIN_INT64.
return Integer::New(kMinInt64, space);
}
// Out of range.
return Integer::null();
}
@@ -18334,9 +18344,16 @@ RawInteger* Integer::New(const String& str, Heap::Space space) {
RawInteger* Integer::NewCanonical(const String& str) {
// We are not supposed to have integers represented as two byte strings.
ASSERT(str.IsOneByteString());
int64_t value;
if (!OS::StringToInt64(str.ToCString(), &value)) {
int64_t value = 0;
const char* cstr = str.ToCString();
if (!OS::StringToInt64(cstr, &value)) {
if (FLAG_limit_ints_to_64_bits) {
if (strcmp(cstr, kMaxInt64Plus1) == 0) {
// Allow MAX_INT64 + 1 integer literal as it can be used as an argument
// of unary minus to produce MIN_INT64 value. The value is automatically
// wrapped to MIN_INT64.
return Mint::NewCanonical(kMinInt64);
}
// Out of range.
return Integer::null();
}
+7 -1
View File
@@ -353,7 +353,13 @@ bool OS::StringToInt64(const char* str, int64_t* value) {
base = 16;
}
errno = 0;
*value = strtoll(str, &endptr, base);
if (FLAG_limit_ints_to_64_bits && (base == 16)) {
// Unsigned 64-bit hexadecimal integer literals are allowed but
// immediately interpreted as signed 64-bit integers.
*value = static_cast<int64_t>(strtoull(str, &endptr, base));
} else {
*value = strtoll(str, &endptr, base);
}
return ((errno == 0) && (endptr != str) && (*endptr == 0));
}
+7 -1
View File
@@ -233,7 +233,13 @@ bool OS::StringToInt64(const char* str, int64_t* value) {
base = 16;
}
errno = 0;
*value = strtoll(str, &endptr, base);
if (FLAG_limit_ints_to_64_bits && (base == 16)) {
// Unsigned 64-bit hexadecimal integer literals are allowed but
// immediately interpreted as signed 64-bit integers.
*value = static_cast<int64_t>(strtoull(str, &endptr, base));
} else {
*value = strtoll(str, &endptr, base);
}
return ((errno == 0) && (endptr != str) && (*endptr == 0));
}
+7 -1
View File
@@ -339,7 +339,13 @@ bool OS::StringToInt64(const char* str, int64_t* value) {
base = 16;
}
errno = 0;
*value = strtoll(str, &endptr, base);
if (FLAG_limit_ints_to_64_bits && (base == 16)) {
// Unsigned 64-bit hexadecimal integer literals are allowed but
// immediately interpreted as signed 64-bit integers.
*value = static_cast<int64_t>(strtoull(str, &endptr, base));
} else {
*value = strtoll(str, &endptr, base);
}
return ((errno == 0) && (endptr != str) && (*endptr == 0));
}
+7 -1
View File
@@ -328,7 +328,13 @@ bool OS::StringToInt64(const char* str, int64_t* value) {
base = 16;
}
errno = 0;
*value = strtoll(str, &endptr, base);
if (FLAG_limit_ints_to_64_bits && (base == 16)) {
// Unsigned 64-bit hexadecimal integer literals are allowed but
// immediately interpreted as signed 64-bit integers.
*value = static_cast<int64_t>(strtoull(str, &endptr, base));
} else {
*value = strtoll(str, &endptr, base);
}
return ((errno == 0) && (endptr != str) && (*endptr == 0));
}
+7 -1
View File
@@ -355,7 +355,13 @@ bool OS::StringToInt64(const char* str, int64_t* value) {
base = 16;
}
errno = 0;
*value = _strtoi64(str, &endptr, base);
if (FLAG_limit_ints_to_64_bits && (base == 16)) {
// Unsigned 64-bit hexadecimal integer literals are allowed but
// immediately interpreted as signed 64-bit integers.
*value = static_cast<int64_t>(_strtoui64(str, &endptr, base));
} else {
*value = _strtoi64(str, &endptr, base);
}
return ((errno == 0) && (endptr != str) && (*endptr == 0));
}