Switch to BigInt for ConstantValue.

Change-Id: I17eec094d794b1c4791d491ea523d284f9eae4ed
Reviewed-on: https://dart-review.googlesource.com/55500
Commit-Queue: Emily Fortuna <efortuna@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
This commit is contained in:
Emily Fortuna 2018-05-22 01:04:41 +00:00 committed by commit-bot@chromium.org
parent 9696c9dcd0
commit 49d5ca3bb4
28 changed files with 202 additions and 169 deletions

View file

@ -60,45 +60,45 @@ abstract class BinaryBitOperation implements BinaryOperation {
if (left.isInt && right.isInt) {
IntConstantValue leftInt = left;
IntConstantValue rightInt = right;
int resultValue = foldInts(leftInt.intValue, rightInt.intValue);
BigInt resultValue = foldInts(leftInt.intValue, rightInt.intValue);
if (resultValue == null) return null;
return DART_CONSTANT_SYSTEM.createInt(resultValue);
}
return null;
}
int foldInts(int left, int right);
BigInt foldInts(BigInt left, BigInt right);
}
class BitOrOperation extends BinaryBitOperation {
final String name = '|';
const BitOrOperation();
int foldInts(int left, int right) => left | right;
BigInt foldInts(BigInt left, BigInt right) => left | right;
apply(left, right) => left | right;
}
class BitAndOperation extends BinaryBitOperation {
final String name = '&';
const BitAndOperation();
int foldInts(int left, int right) => left & right;
BigInt foldInts(BigInt left, BigInt right) => left & right;
apply(left, right) => left & right;
}
class BitXorOperation extends BinaryBitOperation {
final String name = '^';
const BitXorOperation();
int foldInts(int left, int right) => left ^ right;
BigInt foldInts(BigInt left, BigInt right) => left ^ right;
apply(left, right) => left ^ right;
}
class ShiftLeftOperation extends BinaryBitOperation {
final String name = '<<';
const ShiftLeftOperation();
int foldInts(int left, int right) {
BigInt foldInts(BigInt left, BigInt right) {
// TODO(floitsch): find a better way to guard against excessive shifts to
// the left.
if (right > 100 || right < 0) return null;
return left << right;
if (right > new BigInt.from(100) || right < BigInt.zero) return null;
return left << right.toInt();
}
apply(left, right) => left << right;
@ -107,9 +107,9 @@ class ShiftLeftOperation extends BinaryBitOperation {
class ShiftRightOperation extends BinaryBitOperation {
final String name = '>>';
const ShiftRightOperation();
int foldInts(int left, int right) {
if (right < 0) return null;
return left >> right;
BigInt foldInts(BigInt left, BigInt right) {
if (right < BigInt.zero) return null;
return left >> right.toInt();
}
apply(left, right) => left >> right;
@ -150,7 +150,7 @@ abstract class ArithmeticNumOperation implements BinaryOperation {
if (left.isNum && right.isNum) {
NumConstantValue leftNum = left;
NumConstantValue rightNum = right;
num foldedValue;
var foldedValue;
if (left.isInt && right.isInt) {
IntConstantValue leftInt = leftNum;
IntConstantValue rightInt = rightNum;
@ -161,7 +161,7 @@ abstract class ArithmeticNumOperation implements BinaryOperation {
// A division by 0 means that we might not have a folded value.
if (foldedValue == null) return null;
if (left.isInt && right.isInt && !isDivide() || isTruncatingDivide()) {
assert(foldedValue is int);
assert(foldedValue is BigInt);
return DART_CONSTANT_SYSTEM.createInt(foldedValue);
} else {
return DART_CONSTANT_SYSTEM.createDouble(foldedValue);
@ -172,13 +172,14 @@ abstract class ArithmeticNumOperation implements BinaryOperation {
bool isDivide() => false;
bool isTruncatingDivide() => false;
num foldInts(int left, int right) => foldNums(left, right);
num foldNums(num left, num right);
foldInts(BigInt left, BigInt right);
foldNums(num left, num right);
}
class SubtractOperation extends ArithmeticNumOperation {
final String name = '-';
const SubtractOperation();
BigInt foldInts(BigInt left, BigInt right) => left - right;
num foldNums(num left, num right) => left - right;
apply(left, right) => left - right;
}
@ -186,6 +187,7 @@ class SubtractOperation extends ArithmeticNumOperation {
class MultiplyOperation extends ArithmeticNumOperation {
final String name = '*';
const MultiplyOperation();
BigInt foldInts(BigInt left, BigInt right) => left * right;
num foldNums(num left, num right) => left * right;
apply(left, right) => left * right;
}
@ -193,8 +195,8 @@ class MultiplyOperation extends ArithmeticNumOperation {
class ModuloOperation extends ArithmeticNumOperation {
final String name = '%';
const ModuloOperation();
int foldInts(int left, int right) {
if (right == 0) return null;
BigInt foldInts(BigInt left, BigInt right) {
if (right == BigInt.zero) return null;
return left % right;
}
@ -205,6 +207,7 @@ class ModuloOperation extends ArithmeticNumOperation {
class RemainderOperation extends ArithmeticNumOperation {
final String name = 'remainder';
const RemainderOperation();
BigInt foldInts(BigInt left, BigInt right) => null;
// Not a defined constant operation.
num foldNums(num left, num right) => null;
apply(left, right) => left.remainder(right);
@ -213,15 +216,15 @@ class RemainderOperation extends ArithmeticNumOperation {
class TruncatingDivideOperation extends ArithmeticNumOperation {
final String name = '~/';
const TruncatingDivideOperation();
int foldInts(int left, int right) {
if (right == 0) return null;
BigInt foldInts(BigInt left, BigInt right) {
if (right == BigInt.zero) return null;
return left ~/ right;
}
num foldNums(num left, num right) {
BigInt foldNums(num left, num right) {
num ratio = left / right;
if (ratio.isNaN || ratio.isInfinite) return null;
return ratio.truncate().toInt();
return new BigInt.from(ratio.truncate().toInt());
}
apply(left, right) => left ~/ right;
@ -231,6 +234,7 @@ class TruncatingDivideOperation extends ArithmeticNumOperation {
class DivideOperation extends ArithmeticNumOperation {
final String name = '/';
const DivideOperation();
double foldInts(BigInt left, BigInt right) => left / right;
num foldNums(num left, num right) => left / right;
bool isDivide() => true;
apply(left, right) => left / right;
@ -243,7 +247,7 @@ class AddOperation implements BinaryOperation {
if (left.isInt && right.isInt) {
IntConstantValue leftInt = left;
IntConstantValue rightInt = right;
int result = leftInt.intValue + rightInt.intValue;
BigInt result = leftInt.intValue + rightInt.intValue;
return DART_CONSTANT_SYSTEM.createInt(result);
} else if (left.isNum && right.isNum) {
NumConstantValue leftNum = left;
@ -281,14 +285,14 @@ abstract class RelationalNumOperation implements BinaryOperation {
return DART_CONSTANT_SYSTEM.createBool(foldedValue);
}
bool foldInts(int left, int right);
bool foldInts(BigInt left, BigInt right);
bool foldNums(num left, num right);
}
class LessOperation extends RelationalNumOperation {
final String name = '<';
const LessOperation();
bool foldInts(int left, int right) => left < right;
bool foldInts(BigInt left, BigInt right) => left < right;
bool foldNums(num left, num right) => left < right;
apply(left, right) => left < right;
}
@ -296,7 +300,7 @@ class LessOperation extends RelationalNumOperation {
class LessEqualOperation extends RelationalNumOperation {
final String name = '<=';
const LessEqualOperation();
bool foldInts(int left, int right) => left <= right;
bool foldInts(BigInt left, BigInt right) => left <= right;
bool foldNums(num left, num right) => left <= right;
apply(left, right) => left <= right;
}
@ -304,7 +308,7 @@ class LessEqualOperation extends RelationalNumOperation {
class GreaterOperation extends RelationalNumOperation {
final String name = '>';
const GreaterOperation();
bool foldInts(int left, int right) => left > right;
bool foldInts(BigInt left, BigInt right) => left > right;
bool foldNums(num left, num right) => left > right;
apply(left, right) => left > right;
}
@ -312,7 +316,7 @@ class GreaterOperation extends RelationalNumOperation {
class GreaterEqualOperation extends RelationalNumOperation {
final String name = '>=';
const GreaterEqualOperation();
bool foldInts(int left, int right) => left >= right;
bool foldInts(BigInt left, BigInt right) => left >= right;
bool foldNums(num left, num right) => left >= right;
apply(left, right) => left >= right;
}
@ -387,10 +391,10 @@ class CodeUnitAtRuntimeOperation extends CodeUnitAtOperation {
StringConstantValue stringConstant = left;
IntConstantValue indexConstant = right;
String string = stringConstant.stringValue;
int index = indexConstant.intValue;
int index = indexConstant.intValue.toInt();
if (index < 0 || index >= string.length) return null;
int value = string.codeUnitAt(index);
return DART_CONSTANT_SYSTEM.createInt(value);
return DART_CONSTANT_SYSTEM.createIntFromInt(value);
}
return null;
}
@ -442,7 +446,7 @@ class DartConstantSystem extends ConstantSystem {
const DartConstantSystem();
@override
IntConstantValue createInt(int i) => new IntConstantValue(i);
IntConstantValue createInt(BigInt i) => new IntConstantValue(i);
@override
DoubleConstantValue createDouble(double d) => new DoubleConstantValue(d);

View file

@ -59,7 +59,8 @@ abstract class ConstantSystem {
const ConstantSystem();
ConstantValue createInt(int i);
ConstantValue createInt(BigInt i);
ConstantValue createIntFromInt(int i) => createInt(new BigInt.from(i));
ConstantValue createDouble(double d);
ConstantValue createString(String string);
ConstantValue createBool(bool value);

View file

@ -235,7 +235,7 @@ class BoolConstantExpression extends ConstantExpression {
/// Integer literal constant.
class IntConstantExpression extends ConstantExpression {
final int intValue;
final BigInt intValue;
IntConstantExpression(this.intValue);
@ -1533,7 +1533,8 @@ class StringLengthConstantExpression extends ConstantExpression {
return new NonConstantValue();
} else {
StringConstantValue stringValue = value;
return constantSystem.createInt(stringValue.stringValue.length);
return constantSystem
.createInt(new BigInt.from(stringValue.stringValue.length));
}
}
@ -1907,9 +1908,9 @@ class IntFromEnvironmentConstantExpression
StringConstantValue nameStringConstantValue = nameConstantValue;
String text =
environment.readFromEnvironment(nameStringConstantValue.stringValue);
int value;
BigInt value;
if (text != null) {
value = int.parse(text, onError: (_) => null);
value = BigInt.tryParse(text);
}
if (value == null) {
return defaultConstantValue;

View file

@ -205,55 +205,38 @@ abstract class NumConstantValue extends PrimitiveConstantValue {
}
class IntConstantValue extends NumConstantValue {
final int intValue;
final BigInt intValue;
// Caching IntConstantValues representing -2 through 10 so that we don't have
// to create new ones every time those values are used.
static Map<BigInt, IntConstantValue> _cachedValues = {};
double get doubleValue => intValue.toDouble();
factory IntConstantValue(int value) {
switch (value) {
case 0:
return const IntConstantValue._internal(0);
case 1:
return const IntConstantValue._internal(1);
case 2:
return const IntConstantValue._internal(2);
case 3:
return const IntConstantValue._internal(3);
case 4:
return const IntConstantValue._internal(4);
case 5:
return const IntConstantValue._internal(5);
case 6:
return const IntConstantValue._internal(6);
case 7:
return const IntConstantValue._internal(7);
case 8:
return const IntConstantValue._internal(8);
case 9:
return const IntConstantValue._internal(9);
case 10:
return const IntConstantValue._internal(10);
case -1:
return const IntConstantValue._internal(-1);
case -2:
return const IntConstantValue._internal(-2);
default:
return new IntConstantValue._internal(value);
factory IntConstantValue(BigInt value) {
var existing = _cachedValues[value];
if (existing != null) return existing;
var intConstantVal = new IntConstantValue._internal(value);
var intValue = value.toInt();
if (intValue <= -2 && intValue >= 10) {
_cachedValues[value] = intConstantVal;
}
return intConstantVal;
}
const IntConstantValue._internal(this.intValue);
bool get isInt => true;
bool isUInt31() => intValue >= 0 && intValue < (1 << 31);
bool isUInt31() => intValue.toUnsigned(31) == intValue;
bool isUInt32() => intValue >= 0 && intValue < (1 << 32);
bool isUInt32() => intValue.toUnsigned(32) == intValue;
bool isPositive() => intValue >= 0;
bool isPositive() => intValue >= BigInt.zero;
bool get isZero => intValue == 0;
bool get isZero => intValue == BigInt.zero;
bool get isOne => intValue == 1;
bool get isOne => intValue == BigInt.one;
DartType getType(CommonElements types) => types.intType;
@ -264,7 +247,7 @@ class IntConstantValue extends NumConstantValue {
return intValue == otherInt.intValue;
}
int get hashCode => intValue & Hashing.SMI_MASK;
int get hashCode => intValue.hashCode & Hashing.SMI_MASK;
accept(ConstantValueVisitor visitor, arg) => visitor.visitInt(this, arg);

View file

@ -615,8 +615,8 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
ConstantSystem constantSystem = _closedWorld.constantSystem;
// The JavaScript backend may turn this literal into a double at
// runtime.
return _types.getConcreteTypeFor(
computeTypeMask(_closedWorld, constantSystem.createInt(node.value)));
return _types.getConcreteTypeFor(computeTypeMask(
_closedWorld, constantSystem.createIntFromInt(node.value)));
}
@override
@ -1012,7 +1012,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
ConstantValue value = _elementMap.getFieldConstantValue(member);
if (value != null && value.isInt) {
IntConstantValue intValue = value;
return intValue.intValue;
return intValue.intValue.toInt();
}
}
}

View file

@ -120,7 +120,7 @@ class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
@override
jsAst.Expression visitInt(IntConstantValue constant, [_]) {
int value = constant.intValue;
BigInt value = constant.intValue;
// Since we are in JavaScript we can shorten long integers to their shorter
// exponential representation, for example: "1e4" is shorter than "10000".
//
@ -131,9 +131,9 @@ class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
String representation = value.toString();
String alternative = null;
int cutoff = _options.enableMinification ? 10000 : 1e10.toInt();
if (value.abs() >= cutoff) {
alternative =
_shortenExponentialRepresentation(value.toStringAsExponential());
if (value.abs() >= new BigInt.from(cutoff)) {
alternative = _shortenExponentialRepresentation(
value.toDouble().toStringAsExponential());
}
if (alternative != null && alternative.length < representation.length) {
representation = alternative;

View file

@ -43,7 +43,7 @@ class JavaScriptConstantCompiler implements BackendConstantEnvironment {
JavaScriptConstantCompiler();
ConstantSystem get constantSystem => JAVA_SCRIPT_CONSTANT_SYSTEM;
ConstantSystem get constantSystem => JavaScriptConstantSystem.only;
@override
void registerLazyStatic(FieldEntity element) {

View file

@ -11,18 +11,18 @@ import '../common_elements.dart' show CommonElements;
import '../elements/types.dart';
import '../elements/entities.dart';
const JAVA_SCRIPT_CONSTANT_SYSTEM = const JavaScriptConstantSystem();
class JavaScriptBitNotOperation extends BitNotOperation {
const JavaScriptBitNotOperation();
ConstantValue fold(ConstantValue constant) {
if (JAVA_SCRIPT_CONSTANT_SYSTEM.isInt(constant)) {
if (JavaScriptConstantSystem.only.isInt(constant)) {
// In JavaScript we don't check for -0 and treat it as if it was zero.
if (constant.isMinusZero) constant = DART_CONSTANT_SYSTEM.createInt(0);
if (constant.isMinusZero) {
constant = DART_CONSTANT_SYSTEM.createInt(BigInt.zero);
}
IntConstantValue intConstant = constant;
// We convert the result of bit-operations to 32 bit unsigned integers.
return JAVA_SCRIPT_CONSTANT_SYSTEM.createInt32(~intConstant.intValue);
return JavaScriptConstantSystem.only.createInt32(~intConstant.intValue);
}
return null;
}
@ -41,12 +41,16 @@ class JavaScriptBinaryBitOperation implements BinaryOperation {
ConstantValue fold(ConstantValue left, ConstantValue right) {
// In JavaScript we don't check for -0 and treat it as if it was zero.
if (left.isMinusZero) left = DART_CONSTANT_SYSTEM.createInt(0);
if (right.isMinusZero) right = DART_CONSTANT_SYSTEM.createInt(0);
if (left.isMinusZero) {
left = DART_CONSTANT_SYSTEM.createInt(BigInt.zero);
}
if (right.isMinusZero) {
right = DART_CONSTANT_SYSTEM.createInt(BigInt.zero);
}
IntConstantValue result = dartBitOperation.fold(left, right);
if (result != null) {
// We convert the result of bit-operations to 32 bit unsigned integers.
return JAVA_SCRIPT_CONSTANT_SYSTEM.createInt32(result.intValue);
return JavaScriptConstantSystem.only.createInt32(result.intValue);
}
return result;
}
@ -61,9 +65,9 @@ class JavaScriptShiftRightOperation extends JavaScriptBinaryBitOperation {
// Truncate the input value to 32 bits if necessary.
if (left.isInt) {
IntConstantValue intConstant = left;
int value = intConstant.intValue;
int truncatedValue = value & JAVA_SCRIPT_CONSTANT_SYSTEM.BITS32;
if (value < 0) {
BigInt value = intConstant.intValue;
BigInt truncatedValue = value & JavaScriptConstantSystem.only.BITS32;
if (value < BigInt.zero) {
// Sign-extend if the input was negative. The current semantics don't
// make much sense, since we only look at bit 31.
// TODO(floitsch): we should treat the input to right shifts as
@ -74,8 +78,8 @@ class JavaScriptShiftRightOperation extends JavaScriptBinaryBitOperation {
// Example: 0xFFFFFFFF - 0x100000000 => -1.
// We simply and with the sign-bit and multiply by two. If the sign-bit
// was set, then the result is 0. Otherwise it will become 2^32.
final int SIGN_BIT = 0x80000000;
truncatedValue -= 2 * (truncatedValue & SIGN_BIT);
final BigInt SIGN_BIT = new BigInt.from(0x80000000);
truncatedValue -= BigInt.two * (truncatedValue & SIGN_BIT);
}
if (value != truncatedValue) {
left = DART_CONSTANT_SYSTEM.createInt(truncatedValue);
@ -95,8 +99,8 @@ class JavaScriptNegateOperation implements UnaryOperation {
ConstantValue fold(ConstantValue constant) {
if (constant.isInt) {
IntConstantValue intConstant = constant;
if (intConstant.intValue == 0) {
return JAVA_SCRIPT_CONSTANT_SYSTEM.createDouble(-0.0);
if (intConstant.intValue == BigInt.zero) {
return JavaScriptConstantSystem.only.createDouble(-0.0);
}
}
return dartNegateOperation.fold(constant);
@ -112,7 +116,7 @@ class JavaScriptAddOperation implements BinaryOperation {
ConstantValue fold(ConstantValue left, ConstantValue right) {
ConstantValue result = _addOperation.fold(left, right);
if (result != null && result.isNum) {
return JAVA_SCRIPT_CONSTANT_SYSTEM.convertToJavaScriptConstant(result);
return JavaScriptConstantSystem.only.convertToJavaScriptConstant(result);
}
return result;
}
@ -125,8 +129,8 @@ class JavaScriptRemainderOperation extends ArithmeticNumOperation {
const JavaScriptRemainderOperation();
int foldInts(int left, int right) {
if (right == 0) return null;
BigInt foldInts(BigInt left, BigInt right) {
if (right == BigInt.zero) return null;
return left.remainder(right);
}
@ -144,7 +148,7 @@ class JavaScriptBinaryArithmeticOperation implements BinaryOperation {
ConstantValue fold(ConstantValue left, ConstantValue right) {
ConstantValue result = dartArithmeticOperation.fold(left, right);
if (result == null) return result;
return JAVA_SCRIPT_CONSTANT_SYSTEM.convertToJavaScriptConstant(result);
return JavaScriptConstantSystem.only.convertToJavaScriptConstant(result);
}
apply(left, right) => dartArithmeticOperation.apply(left, right);
@ -186,7 +190,7 @@ class JavaScriptRoundOperation implements UnaryOperation {
ConstantValue fold(ConstantValue constant) {
// Be careful to round() only values that do not throw on either the host or
// target platform.
ConstantValue tryToRound(num value) {
ConstantValue tryToRound(double value) {
// Due to differences between browsers, only 'round' easy cases. Avoid
// cases where nudging the value up or down changes the answer.
// 13 digits is safely within the ~15 digit precision of doubles.
@ -196,13 +200,13 @@ class JavaScriptRoundOperation implements UnaryOperation {
double rounded1 = (value * (1.0 + severalULP)).roundToDouble();
double rounded2 = (value * (1.0 - severalULP)).roundToDouble();
if (rounded != rounded1 || rounded != rounded2) return null;
return JAVA_SCRIPT_CONSTANT_SYSTEM
.convertToJavaScriptConstant(new IntConstantValue(value.round()));
return JavaScriptConstantSystem.only.convertToJavaScriptConstant(
new IntConstantValue(new BigInt.from(value.round())));
}
if (constant.isInt) {
IntConstantValue intConstant = constant;
int value = intConstant.intValue;
double value = intConstant.intValue.toDouble();
if (value >= -double.maxFinite && value <= double.maxFinite) {
return tryToRound(value);
}
@ -224,7 +228,7 @@ class JavaScriptRoundOperation implements UnaryOperation {
* compiled to JavaScript.
*/
class JavaScriptConstantSystem extends ConstantSystem {
final int BITS32 = 0xFFFFFFFF;
final BITS32 = new BigInt.from(0xFFFFFFFF);
final add = const JavaScriptAddOperation();
final bitAnd = const JavaScriptBinaryBitOperation(const BitAndOperation());
@ -260,13 +264,16 @@ class JavaScriptConstantSystem extends ConstantSystem {
final round = const JavaScriptRoundOperation();
final abs = const UnfoldedUnaryOperation('abs');
const JavaScriptConstantSystem();
static final JavaScriptConstantSystem only =
new JavaScriptConstantSystem._internal();
JavaScriptConstantSystem._internal();
/**
* Returns true if [value] will turn into NaN or infinity
* at runtime.
*/
bool integerBecomesNanOrInfinity(int value) {
bool integerBecomesNanOrInfinity(BigInt value) {
double doubleValue = value.toDouble();
return doubleValue.isNaN || doubleValue.isInfinite;
}
@ -274,13 +281,13 @@ class JavaScriptConstantSystem extends ConstantSystem {
NumConstantValue convertToJavaScriptConstant(NumConstantValue constant) {
if (constant.isInt) {
IntConstantValue intConstant = constant;
int intValue = intConstant.intValue;
BigInt intValue = intConstant.intValue;
if (integerBecomesNanOrInfinity(intValue)) {
return new DoubleConstantValue(intValue.toDouble());
}
// If the integer loses precision with JavaScript numbers, use
// the floored version JavaScript will use.
int floorValue = intValue.toDouble().floor().toInt();
BigInt floorValue = new BigInt.from(intValue.toDouble());
if (floorValue != intValue) {
return new IntConstantValue(floorValue);
}
@ -290,9 +297,9 @@ class JavaScriptConstantSystem extends ConstantSystem {
if (!doubleValue.isInfinite &&
!doubleValue.isNaN &&
!constant.isMinusZero) {
int intValue = doubleValue.truncate();
if (intValue == doubleValue) {
return new IntConstantValue(intValue);
double truncated = doubleValue.truncateToDouble();
if (truncated == doubleValue) {
return new IntConstantValue(new BigInt.from(truncated));
}
}
}
@ -300,11 +307,11 @@ class JavaScriptConstantSystem extends ConstantSystem {
}
@override
NumConstantValue createInt(int i) {
NumConstantValue createInt(BigInt i) {
return convertToJavaScriptConstant(new IntConstantValue(i));
}
NumConstantValue createInt32(int i) => new IntConstantValue(i & BITS32);
NumConstantValue createInt32(BigInt i) => new IntConstantValue(i & BITS32);
NumConstantValue createDouble(double d) =>
convertToJavaScriptConstant(new DoubleConstantValue(d));
StringConstantValue createString(String string) {

View file

@ -1893,7 +1893,7 @@ class ConstantNamingVisitor implements ConstantValueVisitor {
@override
void visitInt(IntConstantValue constant, [_]) {
// No `addRoot` since IntConstants are always inlined.
if (constant.intValue < 0) {
if (constant.intValue < BigInt.zero) {
add('m${-constant.intValue}');
} else {
add('${constant.intValue}');
@ -2088,7 +2088,11 @@ class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> {
@override
int visitInt(IntConstantValue constant, [_]) {
return _hashInt(constant.intValue);
BigInt value = constant.intValue;
if (value.toSigned(32) == value) {
return value.toUnsigned(32).toInt() & _MASK;
}
return _hashDouble(value.toDouble());
}
@override

View file

@ -346,7 +346,7 @@ class JsClosedWorldBuilder {
elementEnvironment: _elementEnvironment,
dartTypes: _elementMap.types,
commonElements: _commonElements,
constantSystem: const JavaScriptConstantSystem(),
constantSystem: JavaScriptConstantSystem.only,
backendUsage: backendUsage,
noSuchMethodData: noSuchMethodData,
nativeData: nativeData,

View file

@ -1881,7 +1881,7 @@ class KernelConstantEnvironment implements ConstantEnvironment {
KernelConstantEnvironment(this._elementMap, this._environment);
@override
ConstantSystem get constantSystem => const JavaScriptConstantSystem();
ConstantSystem get constantSystem => JavaScriptConstantSystem.only;
ConstantValue _getConstantValue(
Spannable spannable, ConstantExpression expression,

View file

@ -295,7 +295,7 @@ abstract class KernelToElementMapBaseMixin implements KernelToElementMap {
assert(constant.fields.length == 1 || constant.fields.length == 2);
ConstantValue indexConstant = constant.fields.values.first;
if (indexConstant is IntConstantValue) {
return indexConstant.intValue;
return indexConstant.intValue.toInt();
}
}
}
@ -604,7 +604,7 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
@override
ConstantExpression visitIntLiteral(ir.IntLiteral node) {
return new IntConstantExpression(node.value);
return new IntConstantExpression(new BigInt.from(node.value));
}
@override

View file

@ -2361,7 +2361,9 @@ class KernelSsaGraphBuilder extends ir.Visitor
List<ConstantValue> getConstants(
ir.SwitchStatement parentSwitch, ir.SwitchCase switchCase) {
return <ConstantValue>[constantSystem.createInt(caseIndex[switchCase])];
return <ConstantValue>[
constantSystem.createIntFromInt(caseIndex[switchCase])
];
}
void buildSwitchCase(ir.SwitchCase switchCase) {
@ -4278,7 +4280,7 @@ class KernelSsaGraphBuilder extends ir.Visitor
add(argumentNamesInstruction);
ConstantValue kindConstant =
constantSystem.createInt(selector.invocationMirrorKind);
constantSystem.createIntFromInt(selector.invocationMirrorKind);
_pushStaticInvocation(
_commonElements.createInvocationMirror,

View file

@ -271,7 +271,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
int constant(HInstruction instruction) {
if (instruction is HConstant && instruction.isConstantInteger()) {
IntConstantValue constant = instruction.constant;
return constant.intValue;
return constant.intValue.toInt();
}
return null;
}

View file

@ -660,16 +660,16 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
if (!instruction.isConstantInteger()) return false;
HConstant rightConstant = instruction;
IntConstantValue intConstant = rightConstant.constant;
int count = intConstant.intValue;
return count != 0;
BigInt count = intConstant.intValue;
return count != BigInt.zero;
}
bool isTwoOrGreater(HInstruction instruction) {
if (!instruction.isConstantInteger()) return false;
HConstant rightConstant = instruction;
IntConstantValue intConstant = rightConstant.constant;
int count = intConstant.intValue;
return count >= 2;
BigInt count = intConstant.intValue;
return count >= BigInt.two;
}
bool hasUint31Result(HInstruction instruction, ClosedWorld closedWorld) {
@ -750,7 +750,9 @@ abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer {
if (instruction.isConstantInteger()) {
HConstant rightConstant = instruction;
IntConstantValue intConstant = rightConstant.constant;
int value = intConstant.intValue;
int value = intConstant.intValue.toInt();
assert(intConstant.intValue ==
new BigInt.from(intConstant.intValue.toInt()));
return value >= low && value <= high;
}
// TODO(sra): Integrate with the bit-width analysis in codegen.dart.

View file

@ -235,8 +235,8 @@ class KernelImpactBuilder extends ir.Visitor {
@override
void visitIntLiteral(ir.IntLiteral literal) {
impactBuilder
.registerConstantLiteral(new IntConstantExpression(literal.value));
impactBuilder.registerConstantLiteral(
new IntConstantExpression(new BigInt.from(literal.value)));
}
@override

View file

@ -292,7 +292,8 @@ class HGraph {
}
HConstant addConstantInt(int i, ClosedWorld closedWorld) {
return addConstant(closedWorld.constantSystem.createInt(i), closedWorld);
return addConstant(
closedWorld.constantSystem.createIntFromInt(i), closedWorld);
}
HConstant addConstantDouble(double d, ClosedWorld closedWorld) {

View file

@ -1005,7 +1005,7 @@ class SsaInstructionSimplifier extends HBaseVisitor
List<ConstantValue> entries = list.entries;
HConstant indexInstruction = node.index;
IntConstantValue indexConstant = indexInstruction.constant;
int index = indexConstant.intValue;
int index = indexConstant.intValue.toInt();
if (index >= 0 && index < entries.length) {
return _graph.addConstant(entries[index], _closedWorld);
}
@ -1986,20 +1986,20 @@ class SsaLiveBlockAnalyzer extends HBaseVisitor {
switchRange.upper is IntValue) {
IntValue lowerValue = switchRange.lower;
IntValue upperValue = switchRange.upper;
int lower = lowerValue.value;
int upper = upperValue.value;
Set<int> liveLabels = new Set<int>();
BigInt lower = lowerValue.value;
BigInt upper = upperValue.value;
Set<BigInt> liveLabels = new Set<BigInt>();
for (int pos = 1; pos < node.inputs.length; pos++) {
HConstant input = node.inputs[pos];
if (!input.isConstantInteger()) continue;
IntConstantValue constant = input.constant;
int label = constant.intValue;
BigInt label = constant.intValue;
if (!liveLabels.contains(label) && label <= upper && label >= lower) {
markBlockLive(node.block.successors[pos - 1]);
liveLabels.add(label);
}
}
if (liveLabels.length != upper - lower + 1) {
if (new BigInt.from(liveLabels.length) != upper - lower + BigInt.one) {
markBlockLive(node.defaultTarget);
}
return;

View file

@ -16,11 +16,11 @@ class ValueRangeInfo {
IntValue intOne;
ValueRangeInfo(this.constantSystem) {
intZero = newIntValue(0);
intOne = newIntValue(1);
intZero = newIntValue(BigInt.zero);
intOne = newIntValue(BigInt.one);
}
Value newIntValue(int value) {
Value newIntValue(BigInt value) {
return new IntValue(value, this);
}
@ -128,7 +128,7 @@ class MarkerValue extends Value {
* An [IntValue] contains a constant integer value.
*/
class IntValue extends Value {
final int value;
final BigInt value;
const IntValue(this.value, info) : super(info);
@ -187,9 +187,9 @@ class IntValue extends Value {
int get hashCode => throw new UnsupportedError('IntValue.hashCode');
String toString() => 'IntValue $value';
bool get isNegative => value < 0;
bool get isPositive => value >= 0;
bool get isZero => value == 0;
bool get isNegative => value < BigInt.zero;
bool get isPositive => value >= BigInt.zero;
bool get isZero => value == BigInt.zero;
}
/**
@ -694,11 +694,13 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase {
if (constantNum.isPositiveInfinity || constantNum.isNegativeInfinity) {
return info.newUnboundRange();
}
if (constantNum.isMinusZero) constantNum = new IntConstantValue(0);
if (constantNum.isMinusZero) {
constantNum = new IntConstantValue(BigInt.zero);
}
int intValue = constantNum is IntConstantValue
BigInt intValue = constantNum is IntConstantValue
? constantNum.intValue
: constantNum.doubleValue.toInt();
: new BigInt.from(constantNum.doubleValue.toInt());
Value value = info.newIntValue(intValue);
return info.newNormalizedRange(value, value);
}

View file

@ -160,6 +160,10 @@ LibTest/core/List/removeAt_A02_t01: RuntimeError # Issue 1533
LibTest/core/List/sort_A01_t06: Slow, Pass # Slow tests that needs extra time to finish.
LibTest/core/double/INFINITY_A01_t04: RuntimeError # Expected to fail because double.INFINITY is int.
LibTest/core/double/NEGATIVE_INFINITY_A01_t04: RuntimeError # Expected to fail because double.NEGATIVE_INFINITY is int.
LibTest/core/double/operator_addition_A01_t06: RuntimeError # Large integer literal. Not valid dart 2.
LibTest/core/double/operator_addition_A01_t08: Crash # Large integer literal. Not valid dart 2.
LibTest/core/double/operator_subtraction_A01_t06: RuntimeError # Large integer literal. Not valid dart 2.
LibTest/core/double/operator_subtraction_A01_t09: Crash # Large integer literal. Not valid dart 2.
LibTest/core/int/hashCode_A01_t01: RuntimeError, OK # co19 issue 308
LibTest/core/int/isEven_A01_t01: RuntimeError, OK # co19 issue 277
LibTest/core/int/isOdd_A01_t01: RuntimeError, OK # co19 issue 277
@ -170,8 +174,13 @@ LibTest/core/int/operator_NOT_A01_t01: RuntimeError, OK # Expects negative resul
LibTest/core/int/operator_OR_A01_t01: RuntimeError, OK # Requires bigints.
LibTest/core/int/operator_XOR_A01_t01: RuntimeError, OK # Requires bigints.
LibTest/core/int/operator_addition_A01_t01: RuntimeError, OK # co19 issue 200
LibTest/core/int/operator_division_A01_t01: RuntimeError # Large integer literal. Not valid dart 2.
LibTest/core/int/operator_multiplication_A01_t01: RuntimeError # Large integer literal. Not valid dart 2.
LibTest/core/int/operator_remainder_A01_t01: RuntimeError, OK # Requires bigints.
LibTest/core/int/operator_remainder_A01_t02: RuntimeError, OK # Requires bigints.
LibTest/core/int/operator_right_shift_A01_t01: RuntimeError, OK # Expects negative result from bit-operation.
LibTest/core/int/operator_subtraction_A01_t01: RuntimeError # Large integer literal. Not valid dart 2.
LibTest/core/int/operator_truncating_division_A01_t01: RuntimeError # Large integer literal. Not valid dart 2.
LibTest/core/int/toDouble_A01_t01: RuntimeError, OK # co19 issue 200
LibTest/html/Element/addEventListener_A01_t04: Skip # https://github.com/dart-lang/sdk/issues/28873
LibTest/html/Element/queryAll_A01_t01: RuntimeError # See issue 143

View file

@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// VMOptions= --no_limit_ints_to_64_bits
import 'dart:async';
import 'package:expect/expect.dart';
import 'package:compiler/compiler_new.dart';
@ -14,7 +13,8 @@ const MEMORY_SOURCE_FILES = const {
'main.dart': '''
main() {
print(12300000);
print(1234567890123456789012345);
// TODO(efortuna): Uncomment below when issue 33160 is fixed.
// print(0xffffffff00000000);
print(double.maxFinite);
print(-22230000);
}'''
@ -44,7 +44,9 @@ Future test({bool minify}) async {
Expect.isTrue(jsOutput.contains('12300000'));
Expect.isTrue(jsOutput.contains('-22230000'));
}
Expect.isTrue(jsOutput.contains('12345678901234568e8'));
// TODO(efortuna): Uncomment when issue 33160 is fixed.
//Expect.isTrue(jsOutput.contains('18446744069414584e3'));
//Expect.isFalse(jsOutput.contains('-4294967296'));
Expect.isTrue(jsOutput.contains('17976931348623157e292'));
Expect.isFalse(jsOutput.contains('1234567890123456789012345'));
// The decimal expansion of double.maxFinite has 308 digits. We only check

View file

@ -8,7 +8,7 @@ import "package:compiler/src/ssa/value_range_analyzer.dart";
import "package:compiler/src/types/abstract_value_domain.dart";
import "package:compiler/src/js_backend/constant_system_javascript.dart";
ValueRangeInfo info = new ValueRangeInfo(const JavaScriptConstantSystem());
ValueRangeInfo info = new ValueRangeInfo(JavaScriptConstantSystem.only);
class AbstractValueDomainMock implements AbstractValueDomain {
const AbstractValueDomainMock();
@ -27,7 +27,7 @@ Value lengthValue =
Range createSingleRange(Value value) => info.newNormalizedRange(value, value);
Range createSingleIntRange(int value) {
return createSingleRange(info.newIntValue(value));
return createSingleRange(info.newIntValue(new BigInt.from(value)));
}
Range createSingleInstructionRange() => createSingleRange(instructionValue);
@ -35,16 +35,18 @@ Range createSingleInstructionRange() => createSingleRange(instructionValue);
Range createSingleLengthRange() => createSingleRange(lengthValue);
Range createIntRange(int lower, int upper) {
return info.newNormalizedRange(
info.newIntValue(lower), info.newIntValue(upper));
return info.newNormalizedRange(info.newIntValue(new BigInt.from(lower)),
info.newIntValue(new BigInt.from(upper)));
}
Range createLengthRange(int lower) {
return info.newNormalizedRange(info.newIntValue(lower), lengthValue);
return info.newNormalizedRange(
info.newIntValue(new BigInt.from(lower)), lengthValue);
}
Range createInstructionRange(int lower) {
return info.newNormalizedRange(info.newIntValue(lower), instructionValue);
return info.newNormalizedRange(
info.newIntValue(new BigInt.from(lower)), instructionValue);
}
Range instruction = createSingleInstructionRange();
@ -60,8 +62,8 @@ Range _0_length = createLengthRange(0);
Range _0_instruction = createInstructionRange(0);
checkAndRange(Range one, Range two, lower, upper) {
if (lower is num) lower = info.newIntValue(lower);
if (upper is num) upper = info.newIntValue(upper);
if (lower is num) lower = info.newIntValue(new BigInt.from(lower));
if (upper is num) upper = info.newIntValue(new BigInt.from(upper));
Range range = info.newNormalizedRange(lower, upper);
Expect.equals(range, one & two);
}
@ -89,12 +91,12 @@ checkSubRange(Range one, Range two, [lower, upper]) {
if (lower == null) {
lower = buildBound(one.lower, two.upper);
} else if (lower is num) {
lower = info.newIntValue(lower);
lower = info.newIntValue(new BigInt.from(lower));
}
if (upper == null) {
upper = buildBound(one.upper, two.lower);
} else if (upper is num) {
upper = info.newIntValue(upper);
upper = info.newIntValue(new BigInt.from(upper));
}
Expect.equals(info.newNormalizedRange(lower, upper), one - two);
@ -106,14 +108,14 @@ checkNegateRange(Range range, [arg1, arg2]) {
} else {
Value low, up;
if (arg1 is num) {
low = info.newIntValue(arg1);
low = info.newIntValue(new BigInt.from(arg1));
} else if (arg1 == null) {
low = info.newNegateValue(range.upper);
} else {
low = arg1;
}
if (arg2 is num) {
up = info.newIntValue(arg2);
up = info.newIntValue(new BigInt.from(arg2));
} else if (arg2 == null) {
up = info.newNegateValue(range.lower);
} else {

View file

@ -29,12 +29,12 @@ void main() {
FieldEntity field1 = env.elementEnvironment.lookupClassMember(C, 'field1');
FieldEntity field2 = env.elementEnvironment.lookupClassMember(C, 'field2');
ConstructedConstantValue value1 = new ConstructedConstantValue(C_raw, {
field1: new IntConstantValue(0),
field2: new IntConstantValue(1),
field1: new IntConstantValue(BigInt.zero),
field2: new IntConstantValue(BigInt.one),
});
ConstantValue value2 = new ConstructedConstantValue(C_raw, {
field2: new IntConstantValue(1),
field1: new IntConstantValue(0),
field2: new IntConstantValue(BigInt.one),
field1: new IntConstantValue(BigInt.zero),
});
Expect.equals(value1.hashCode, value2.hashCode, "Hashcode mismatch.");
Expect.equals(value1, value2, "Value mismatch.");

View file

@ -12,7 +12,7 @@ import 'package:expect/expect.dart';
main() {
var a = new List.generate(100, (i) => i);
a.sort((a, b) => 1000000000000000000000 * a.compareTo(b));
a.sort((a, b) => 10000000000000 * a.compareTo(b));
Expect.equals(0, a.first);
Expect.equals(99, a.last);
}

View file

@ -6,8 +6,8 @@ import "package:expect/expect.dart";
// Make sure we use JavaScript semantics when compiling compile-time constants.
const x = 12345678901234567891;
const y = 12345678901234567890;
const x = 1234567890123456789;
const y = 1234567890123456788;
const z = x - y;
const a = 1.0;

View file

@ -151,16 +151,27 @@ big_integer_parsed_div_rem_vm_test: RuntimeError
big_integer_parsed_mul_div_vm_test: RuntimeError
bit_twiddling_bigint_test: RuntimeError
compare_to2_test: RuntimeError
double_ceil_test: RuntimeError # Large integer literal. Not representable in JS.
double_floor_test: RuntimeError # Large integer literal. Not representable in JS.
double_parse_test/01: RuntimeError
double_round_test: RuntimeError # Large integer literal. Not representable in JS.
double_truncate_test: RuntimeError # Large integer literal. Not representable in JS.
hash_set_test/01: RuntimeError
int_ceil_to_double_test: RuntimeError # Large integer literal. Not representable in JS.
int_floor_to_double_test: RuntimeError # Large integer literal. Not representable in JS.
int_from_environment_test: RuntimeError # Large integer literal. Not representable in JS.
int_modulo_arith_test/bignum: RuntimeError
int_modulo_arith_test/modPow: RuntimeError
int_parse_radix_test/01: RuntimeError
int_parse_radix_test/02: RuntimeError
int_round_to_double_test: RuntimeError # Large integer literal. Not representable in JS.
int_truncate_to_double_test: RuntimeError # Large integer literal. Not representable in JS.
integer_to_radix_string_test: RuntimeError
integer_to_string_test/01: RuntimeError
iterable_return_type_test/02: RuntimeError
nan_infinity_test/01: RuntimeError
num_parse_test/01: RuntimeError # Large integer literal. Not representable in JS.
num_parse_test/none: RuntimeError # Large integer literal. Not representable in JS.
regress_r21715_test: RuntimeError
string_base_vm_test: RuntimeError
symbol_reserved_word_test/03: RuntimeError

View file

@ -33,6 +33,7 @@ await_future_test: Pass, Timeout # Issue 26735
override_field_test/02: Pass, Slow # TODO(kasperl): Please triage.
[ $compiler == dart2js && $runtime == d8 && $fasta ]
int_round_to_double_test: RuntimeError # Large integer literal. Not valid in dart2.
regress_23408_test: RuntimeError
[ $compiler == dart2js && $runtime != drt ]

View file

@ -19,6 +19,7 @@ async/async_await_sync_completer_test: RuntimeError # sync-async is on by defaul
async/schedule_microtask6_test: RuntimeError # global error handling is not supported. Issue 5958
convert/base64_test/01: Fail, OK # Uses bit-wise operations to detect invalid values. Some large invalid values accepted by dart2js.
convert/chunked_conversion_utf88_test: Slow, Pass
convert/utf82_test: RuntimeError # Large integer literal. Not valid in dart2.
convert/utf85_test: Slow, Pass
developer/timeline_test: Skip # Not supported
math/double_pow_test: RuntimeError
@ -112,7 +113,7 @@ mirrors/typedef_test: RuntimeError # Issue 6490
mirrors/typevariable_mirror_metadata_test: RuntimeError # Issue 10905
mirrors/variable_is_const_test/none: RuntimeError # Issue 14671
profiler/metrics_num_test: Skip # Because of a int / double type test.
typed_data/int32x4_bigint_test: RuntimeError # Issue 1533
typed_data/int32x4_bigint_test: Pass
typed_data/int64_list_load_store_test: RuntimeError # Issue 10275
typed_data/typed_data_hierarchy_int64_test: RuntimeError # Issue 10275