JS: represent long as BigInt if available

This commit is contained in:
Alexey Andreev 2021-03-08 22:59:45 +03:00
parent 1eab7e41b1
commit ca23da939a
6 changed files with 765 additions and 530 deletions

View File

@ -312,8 +312,10 @@ class NameFrequencyEstimator extends RecursiveVisitor implements MethodNodeVisit
if (expr.getSource() == OperationType.LONG) { if (expr.getSource() == OperationType.LONG) {
if (expr.getTarget() == OperationType.DOUBLE || expr.getTarget() == OperationType.FLOAT) { if (expr.getTarget() == OperationType.DOUBLE || expr.getTarget() == OperationType.FLOAT) {
consumer.consumeFunction("Long_toNumber"); consumer.consumeFunction("Long_toNumber");
} else if (expr.getTarget() == OperationType.INT) {
consumer.consumeFunction("Long_lo");
} }
} else { } else if (expr.getTarget() == OperationType.LONG) {
switch (expr.getSource()) { switch (expr.getSource()) {
case INT: case INT:
consumer.consumeFunction("Long_fromInt"); consumer.consumeFunction("Long_fromInt");
@ -339,7 +341,7 @@ class NameFrequencyEstimator extends RecursiveVisitor implements MethodNodeVisit
} else if ((int) value == value) { } else if ((int) value == value) {
consumer.consumeFunction("Long_fromInt"); consumer.consumeFunction("Long_fromInt");
} else { } else {
consumer.consumeFunction("Long"); consumer.consumeFunction("Long_create");
} }
} }
} }

View File

@ -261,7 +261,8 @@ public class Renderer implements RenderingManager {
"$rt_createLongArrayFromData", "$rt_createBooleanArray", "$rt_createByteArray", "$rt_createLongArrayFromData", "$rt_createBooleanArray", "$rt_createByteArray",
"$rt_createShortArray", "$rt_createCharArray", "$rt_createIntArray", "$rt_createLongArray", "$rt_createShortArray", "$rt_createCharArray", "$rt_createIntArray", "$rt_createLongArray",
"$rt_createFloatArray", "$rt_createDoubleArray", "$rt_compare", "$rt_createFloatArray", "$rt_createDoubleArray", "$rt_compare",
"Long_toNumber", "Long_fromInt", "Long_fromNumber", "Long", "Long_ZERO"); "Long_toNumber", "Long_fromInt", "Long_fromNumber", "Long_create", "Long_ZERO",
"Long_hi", "Long_lo");
} }
public void renderLongRuntimeAliases() throws IOException { public void renderLongRuntimeAliases() throws IOException {

View File

@ -239,7 +239,7 @@ public class RenderingContext {
} else if ((int) value == value) { } else if ((int) value == value) {
writer.appendFunction("Long_fromInt").append("(").append(String.valueOf(value)).append(")"); writer.appendFunction("Long_fromInt").append("(").append(String.valueOf(value)).append(")");
} else { } else {
writer.append("new ").appendFunction("Long").append("(" + (value & 0xFFFFFFFFL) writer.appendFunction("Long_create").append("(" + (value & 0xFFFFFFFFL)
+ ", " + (value >>> 32) + ")"); + ", " + (value >>> 32) + ")");
} }
} else if (cst instanceof Character) { } else if (cst instanceof Character) {

View File

@ -929,11 +929,13 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
precedence = Precedence.MEMBER_ACCESS; precedence = Precedence.MEMBER_ACCESS;
Expr longShifted = extractLongRightShiftedBy32(expr.getValue()); Expr longShifted = extractLongRightShiftedBy32(expr.getValue());
if (longShifted != null) { if (longShifted != null) {
writer.appendFunction("Long_hi").append("(");
longShifted.acceptVisitor(this); longShifted.acceptVisitor(this);
writer.append(".hi"); writer.append(")");
} else { } else {
writer.appendFunction("Long_lo").append("(");
expr.getValue().acceptVisitor(this); expr.getValue().acceptVisitor(this);
writer.append(".lo"); writer.append(")");
} }
break; break;
case FLOAT: case FLOAT:

File diff suppressed because it is too large Load Diff

View File

@ -74,18 +74,31 @@ function $rt_wrapArray(cls, data) {
function $rt_createUnfilledArray(cls, sz) { function $rt_createUnfilledArray(cls, sz) {
return new $rt_array(cls, new Array(sz)); return new $rt_array(cls, new Array(sz));
} }
function $rt_createLongArray(sz) {
var data = new Array(sz);
var arr = new $rt_array($rt_longcls(), data);
data.fill(Long_ZERO);
return arr;
}
function $rt_createLongArrayFromData(init) {
return new $rt_array($rt_longcls(), init);
}
function $rt_createNumericArray(cls, nativeArray) { function $rt_createNumericArray(cls, nativeArray) {
return new $rt_array(cls, nativeArray); return new $rt_array(cls, nativeArray);
} }
var $rt_createLongArray;
var $rt_createLongArrayFromData;
if (typeof BigInt !== 'function') {
$rt_createLongArray = function(sz) {
var data = new Array(sz);
var arr = new $rt_array($rt_longcls(), data);
data.fill(Long_ZERO);
return arr;
}
$rt_createLongArrayFromData = function(init) {
return new $rt_array($rt_longcls(), init);
}
} else {
$rt_createLongArray = function (sz) {
return $rt_createNumericArray($rt_longcls(), new BigInt64Array(sz));
}
$rt_createLongArrayFromData = function(data) {
var buffer = new BigInt64Array(data.length);
buffer.set(data);
return $rt_createNumericArray($rt_longcls(), buffer);
}
}
function $rt_createCharArray(sz) { function $rt_createCharArray(sz) {
return $rt_createNumericArray($rt_charcls(), new Uint16Array(sz)); return $rt_createNumericArray($rt_charcls(), new Uint16Array(sz));
} }
@ -630,15 +643,29 @@ function $rt_eraseClinit(target) {
var $rt_numberConversionView = new DataView(new ArrayBuffer(8)); var $rt_numberConversionView = new DataView(new ArrayBuffer(8));
function $rt_doubleToLongBits(n) { var $rt_doubleToLongBits;
$rt_numberConversionView.setFloat64(0, n, true); var $rt_longBitsToDouble;
return new Long($rt_numberConversionView.getInt32(0, true), $rt_numberConversionView.getInt32(4, true)); if (typeof BigInt !== 'function') {
} $rt_doubleToLongBits = function(n) {
function $rt_longBitsToDouble(n) { $rt_numberConversionView.setFloat64(0, n, true);
$rt_numberConversionView.setInt32(0, n.lo, true); return new Long($rt_numberConversionView.getInt32(0, true), $rt_numberConversionView.getInt32(4, true));
$rt_numberConversionView.setInt32(4, n.hi, true); }
return $rt_numberConversionView.getFloat64(0, true); $rt_longBitsToDouble = function(n) {
$rt_numberConversionView.setInt32(0, n.lo, true);
$rt_numberConversionView.setInt32(4, n.hi, true);
return $rt_numberConversionView.getFloat64(0, true);
}
} else {
$rt_doubleToLongBits = function(n) {
$rt_numberConversionView.setFloat64(0, n, true);
return $rt_numberConversionView.getBigInt64(0, true);
}
$rt_longBitsToDouble = function(n) {
$rt_numberConversionView.setBigInt64(0, n, true);
return $rt_numberConversionView.getFloat64(0, true);
}
} }
function $rt_floatToIntBits(n) { function $rt_floatToIntBits(n) {
$rt_numberConversionView.setFloat32(0, n); $rt_numberConversionView.setFloat32(0, n);
return $rt_numberConversionView.getInt32(0); return $rt_numberConversionView.getInt32(0);
@ -697,46 +724,94 @@ function $dbg_class(obj) {
} }
return clsName; return clsName;
} }
function Long(lo, hi) {
this.lo = lo | 0;
this.hi = hi | 0;
}
Long.prototype.__teavm_class__ = function() {
return "long";
};
Long.prototype.toString = function() {
var result = [];
var n = this;
var positive = Long_isPositive(n);
if (!positive) {
n = Long_neg(n);
}
var radix = new Long(10, 0);
do {
var divRem = Long_divRem(n, radix);
result.push(String.fromCharCode(48 + divRem[1].lo));
n = divRem[0];
} while (n.lo !== 0 || n.hi !== 0);
result = result.reverse().join('');
return positive ? result : "-" + result;
};
Long.prototype.valueOf = function() {
return Long_toNumber(this);
};
var Long_ZERO = new Long(0, 0);
var Long_MAX_NORMAL = 1 << 18; var Long_MAX_NORMAL = 1 << 18;
function Long_fromInt(val) { var Long_ZERO;
return new Long(val, (-(val < 0)) | 0); var Long_create;
} var Long_fromInt;
function Long_fromNumber(val) { var Long_fromNumber;
if (val >= 0) { var Long_toNumber;
return new Long(val | 0, (val / 0x100000000) | 0); var Long_hi;
} else { var Long_lo;
return Long_neg(new Long(-val | 0, (-val / 0x100000000) | 0)); if (typeof BigInt !== "function") {
function Long(lo, hi) {
this.lo = lo | 0;
this.hi = hi | 0;
}
Long.prototype.__teavm_class__ = function() {
return "long";
};
function Long_isPositive(a) {
return (a.hi & 0x80000000) === 0;
}
function Long_isNegative(a) {
return (a.hi & 0x80000000) !== 0;
}
Long.prototype.toString = function() {
var result = [];
var n = this;
var positive = Long_isPositive(n);
if (!positive) {
n = Long_neg(n);
}
var radix = new Long(10, 0);
do {
var divRem = Long_divRem(n, radix);
result.push(String.fromCharCode(48 + divRem[1].lo));
n = divRem[0];
} while (n.lo !== 0 || n.hi !== 0);
result = result.reverse().join('');
return positive ? result : "-" + result;
};
Long.prototype.valueOf = function() {
return Long_toNumber(this);
};
Long_ZERO = new Long(0, 0);
Long_fromInt = function(val) {
return new Long(val, (-(val < 0)) | 0);
}
Long_fromNumber = function(val) {
if (val >= 0) {
return new Long(val | 0, (val / 0x100000000) | 0);
} else {
return Long_neg(new Long(-val | 0, (-val / 0x100000000) | 0));
}
}
Long_create = function(lo, hi) {
return new Long(hi, lo);
}
Long_toNumber = function(val) {
return 0x100000000 * val.hi + (val.lo >>> 0);
}
Long_hi = function(val) {
return val.hi;
}
Long_lo = function(val) {
return val.lo;
}
} else {
Long_ZERO = BigInt(0);
Long_create = function(lo, hi) {
return BigInt.asIntN(64, BigInt(lo) | (BigInt(hi) << BigInt(32)));
}
Long_fromInt = function(val) {
return BigInt(val);
}
Long_fromNumber = function(val) {
return BigInt(val >= 0 ? Math.floor(val) : Math.ceil(val));
}
Long_toNumber = function(val) {
return Number(val);
}
Long_hi = function(val) {
return Number(BigInt.asIntN(64, val >> BigInt(32))) | 0;
}
Long_lo = function(val) {
return Number(BigInt.asIntN(32, val)) | 0;
} }
}
function Long_toNumber(val) {
return 0x100000000 * val.hi + (val.lo >>> 0);
} }
var $rt_imul = Math.imul || function(a, b) { var $rt_imul = Math.imul || function(a, b) {
var ah = (a >>> 16) & 0xFFFF; var ah = (a >>> 16) & 0xFFFF;