Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES2020 BigInt #837

Merged
merged 39 commits into from
May 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
8072527
Add NativeBigInt
tuchida Dec 28, 2020
5f2e14b
ScriptRuntime.toBigInt
tuchida Apr 16, 2021
109a874
new BigInt(val) throws TypeError
tuchida Apr 16, 2021
f894307
ScriptRuntime.bigIntToString
tuchida Apr 16, 2021
3e4e704
Formatting changes.
tuchida Apr 16, 2021
34d7f83
BigInt in ScriptRuntime.toObject
tuchida Jan 24, 2021
9525490
Formatting changes.
tuchida Apr 16, 2021
8ec254f
Parse BigIntLiteral
tuchida Apr 16, 2021
c15b4ec
Formatting changes.
tuchida Apr 16, 2021
e4cf01f
BigInt Literal for interpreter
tuchida Apr 16, 2021
19a32f3
Formatting changes.
tuchida May 4, 2021
7516806
BigInt Literal for byte code
tuchida Jan 5, 2021
4fdd036
BigInt equality comparison
tuchida Apr 16, 2021
587017d
Formatting changes.
tuchida Apr 16, 2021
9725d59
Decompile BigIntLiteral
tuchida Apr 16, 2021
a7917a3
Enable test262 for BigInt
tuchida Apr 16, 2021
3644983
Implement Symbol.toStringTag in BigInt
tuchida Apr 16, 2021
8842088
Formatting changes.
tuchida Apr 16, 2021
87d944c
typeof 0n === "bigint"
tuchida Apr 16, 2021
7bf3628
unary minus operator for BigInt
tuchida Apr 16, 2021
5796845
Delete duplicates test
tuchida Feb 7, 2021
fd772c2
Formatting changes.
tuchida Apr 16, 2021
a3aa168
unary plus operator for BigInt
tuchida Apr 16, 2021
cbfe4c2
Increment/Decrement for BigInt
tuchida Feb 8, 2021
a998063
Addition for BigInt
tuchida Apr 16, 2021
6480895
subtract/multiply/divide/remainder/exponentiate for BigInt
tuchida Apr 16, 2021
c762c32
greater or less for BigInt
tuchida Apr 16, 2021
bea0a1d
bit operations for BigInt
tuchida Apr 16, 2021
b464012
bitwise NOT for BigInt
tuchida Apr 16, 2021
dc007c3
ToBoolean for BigInt
tuchida Apr 16, 2021
56d3802
JSON.stringify for BigInt
tuchida Feb 9, 2021
3107199
Print original line number of file in test262.
tuchida Feb 10, 2021
1bae866
BigInt.asIntN / BigInt.asUintN
tuchida Apr 16, 2021
bf5cfa4
Enable BigInt only for ES6
tuchida Apr 16, 2021
6d47e28
Formatting changes.
tuchida Apr 16, 2021
85394dc
No wrap BigInteger
tuchida Apr 16, 2021
d4af0f5
Formatting changes.
tuchida Apr 17, 2021
9a7390d
Consider that the binary operation becomes BigInt during optimization.
tuchida Apr 17, 2021
e1f5a26
Throws RangeError for arithmetic.
tuchida Apr 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,762 changes: 886 additions & 876 deletions src/org/mozilla/javascript/CodeGenerator.java

Large diffs are not rendered by default.

1,248 changes: 608 additions & 640 deletions src/org/mozilla/javascript/Decompiler.java

Large diffs are not rendered by default.

1,197 changes: 599 additions & 598 deletions src/org/mozilla/javascript/IRFactory.java

Large diffs are not rendered by default.

492 changes: 285 additions & 207 deletions src/org/mozilla/javascript/Icode.java

Large diffs are not rendered by default.

275 changes: 197 additions & 78 deletions src/org/mozilla/javascript/Interpreter.java

Large diffs are not rendered by default.

63 changes: 24 additions & 39 deletions src/org/mozilla/javascript/InterpreterData.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,28 @@
package org.mozilla.javascript;

import java.io.Serializable;
import java.math.BigInteger;
import java.util.Arrays;

import org.mozilla.javascript.debug.DebuggableScript;

final class InterpreterData implements Serializable, DebuggableScript
{
final class InterpreterData implements Serializable, DebuggableScript {
private static final long serialVersionUID = 5067677351589230234L;

static final int INITIAL_MAX_ICODE_LENGTH = 1024;
static final int INITIAL_STRINGTABLE_SIZE = 64;
static final int INITIAL_NUMBERTABLE_SIZE = 64;
static final int INITIAL_BIGINTTABLE_SIZE = 64;

InterpreterData(int languageVersion, String sourceFile,
String encodedSource, boolean isStrict)
{
InterpreterData(
int languageVersion, String sourceFile, String encodedSource, boolean isStrict) {
this.languageVersion = languageVersion;
this.itsSourceFile = sourceFile;
this.encodedSource = encodedSource;
this.isStrict = isStrict;
init();
}

InterpreterData(InterpreterData parent)
{
InterpreterData(InterpreterData parent) {
this.parentData = parent;
this.languageVersion = parent.languageVersion;
this.itsSourceFile = parent.itsSourceFile;
Expand All @@ -39,10 +37,10 @@ final class InterpreterData implements Serializable, DebuggableScript
init();
}

private void init()
{
private void init() {
itsICode = new byte[INITIAL_MAX_ICODE_LENGTH];
itsStringTable = new String[INITIAL_STRINGTABLE_SIZE];
itsBigIntTable = new BigInteger[INITIAL_BIGINTTABLE_SIZE];
}

String itsName;
Expand All @@ -52,6 +50,7 @@ private void init()

String[] itsStringTable;
double[] itsDoubleTable;
BigInteger[] itsBigIntTable;
InterpreterData[] itsNestedFunctions;
Object[] itsRegExpLiterals;

Expand Down Expand Up @@ -100,84 +99,70 @@ private void init()
boolean declaredAsFunctionExpression;

@Override
public boolean isTopLevel()
{
public boolean isTopLevel() {
return topLevel;
}

@Override
public boolean isFunction()
{
public boolean isFunction() {
return itsFunctionType != 0;
}

@Override
public String getFunctionName()
{
public String getFunctionName() {
return itsName;
}

@Override
public int getParamCount()
{
public int getParamCount() {
return argCount;
}

@Override
public int getParamAndVarCount()
{
public int getParamAndVarCount() {
return argNames.length;
}

@Override
public String getParamOrVarName(int index)
{
public String getParamOrVarName(int index) {
return argNames[index];
}

public boolean getParamOrVarConst(int index)
{
public boolean getParamOrVarConst(int index) {
return argIsConst[index];
}

@Override
public String getSourceName()
{
public String getSourceName() {
return itsSourceFile;
}

@Override
public boolean isGeneratedScript()
{
public boolean isGeneratedScript() {
return ScriptRuntime.isGeneratedScript(itsSourceFile);
}

@Override
public int[] getLineNumbers()
{
public int[] getLineNumbers() {
return Interpreter.getLineNumbers(this);
}

@Override
public int getFunctionCount()
{
public int getFunctionCount() {
return (itsNestedFunctions == null) ? 0 : itsNestedFunctions.length;
}

@Override
public DebuggableScript getFunction(int index)
{
public DebuggableScript getFunction(int index) {
return itsNestedFunctions[index];
}

@Override
public DebuggableScript getParent()
{
return parentData;
public DebuggableScript getParent() {
return parentData;
}

public int icodeHashCode()
{
public int icodeHashCode() {
int h = icodeHashCode;
if (h == 0) {
icodeHashCode = h = Arrays.hashCode(itsICode);
Expand Down
223 changes: 223 additions & 0 deletions src/org/mozilla/javascript/NativeBigInt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.javascript;

import java.math.BigInteger;
import java.util.Arrays;

/** This class implements the BigInt native object. */
final class NativeBigInt extends IdScriptableObject {
private static final long serialVersionUID = 1335609231306775449L;

private static final Object BIG_INT_TAG = "BigInt";

static void init(Scriptable scope, boolean sealed) {
NativeBigInt obj = new NativeBigInt(BigInteger.ZERO);
obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed);
}

NativeBigInt(BigInteger bigInt) {
bigIntValue = bigInt;
}

@Override
public String getClassName() {
return "BigInt";
}

@Override
protected void fillConstructorProperties(IdFunctionObject ctor) {
addIdFunctionProperty(ctor, BIG_INT_TAG, ConstructorId_asIntN, "asIntN", 2);
addIdFunctionProperty(ctor, BIG_INT_TAG, ConstructorId_asUintN, "asUintN", 2);

super.fillConstructorProperties(ctor);
}

@Override
protected void initPrototypeId(int id) {
if (id == SymbolId_toStringTag) {
initPrototypeValue(
SymbolId_toStringTag,
SymbolKey.TO_STRING_TAG,
getClassName(),
DONTENUM | READONLY);
return;
}

String s;
int arity;
switch (id) {
case Id_constructor:
arity = 1;
s = "constructor";
break;
case Id_toString:
arity = 0;
s = "toString";
break;
case Id_toLocaleString:
arity = 0;
s = "toLocaleString";
break;
case Id_toSource:
arity = 0;
s = "toSource";
break;
case Id_valueOf:
arity = 0;
s = "valueOf";
break;
default:
throw new IllegalArgumentException(String.valueOf(id));
}
initPrototypeMethod(BIG_INT_TAG, id, s, arity);
}

@Override
public Object execIdCall(
IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
if (!f.hasTag(BIG_INT_TAG)) {
return super.execIdCall(f, cx, scope, thisObj, args);
}
int id = f.methodId();
if (id == Id_constructor) {
if (thisObj == null) {
// new BigInt(val) throws TypeError.
throw ScriptRuntime.typeErrorById("msg.not.ctor", BIG_INT_TAG);
}
BigInteger val = (args.length >= 1) ? ScriptRuntime.toBigInt(args[0]) : BigInteger.ZERO;
// BigInt(val) converts val to a BigInteger value.
return val;

} else if (id < Id_constructor) {
return execConstructorCall(id, args);
}

// The rest of BigInt.prototype methods require thisObj to be BigInt
BigInteger value = ensureType(thisObj, NativeBigInt.class, f).bigIntValue;

switch (id) {
case Id_toString:
case Id_toLocaleString:
{
// toLocaleString is just an alias for toString for now
int base =
(args.length == 0 || args[0] == Undefined.instance)
? 10
: ScriptRuntime.toInt32(args[0]);
return ScriptRuntime.bigIntToString(value, base);
}

case Id_toSource:
return "(new BigInt(" + ScriptRuntime.toString(value) + "))";

case Id_valueOf:
return value;

default:
throw new IllegalArgumentException(String.valueOf(id));
}
}

private static Object execConstructorCall(int id, Object[] args) {
switch (id) {
case ConstructorId_asIntN:
case ConstructorId_asUintN:
{
int bits =
ScriptRuntime.toIndex(args.length < 1 ? Undefined.instance : args[0]);
BigInteger bigInt =
ScriptRuntime.toBigInt(args.length < 2 ? Undefined.instance : args[1]);

if (bits == 0) {
return BigInteger.ZERO;
}

byte[] bytes = bigInt.toByteArray();

int newBytesLen = (bits / Byte.SIZE) + 1;
if (newBytesLen > bytes.length) {
return bigInt;
}

byte[] newBytes =
Arrays.copyOfRange(bytes, bytes.length - newBytesLen, bytes.length);

int mod = bits % Byte.SIZE;
switch (id) {
case ConstructorId_asIntN:
if (mod == 0) {
newBytes[0] = newBytes[1] < 0 ? (byte) -1 : 0;
} else if ((newBytes[0] & (1 << (mod - 1))) != 0) {
newBytes[0] |= -1 << mod;
} else {
newBytes[0] &= (1 << mod) - 1;
}
break;
case ConstructorId_asUintN:
newBytes[0] &= (1 << mod) - 1;
break;
}
return new BigInteger(newBytes);
}

default:
throw new IllegalArgumentException(String.valueOf(id));
}
}

@Override
public String toString() {
return ScriptRuntime.bigIntToString(bigIntValue, 10);
}

@Override
protected int findPrototypeId(Symbol k) {
if (SymbolKey.TO_STRING_TAG.equals(k)) {
return SymbolId_toStringTag;
}
return 0;
}

@Override
protected int findPrototypeId(String s) {
int id;
switch (s) {
case "constructor":
id = Id_constructor;
break;
case "toString":
id = Id_toString;
break;
case "toLocaleString":
id = Id_toLocaleString;
break;
case "toSource":
id = Id_toSource;
break;
case "valueOf":
id = Id_valueOf;
break;
default:
id = 0;
break;
}
return id;
}

private static final int ConstructorId_asIntN = -1,
ConstructorId_asUintN = -2,
Id_constructor = 1,
Id_toString = 2,
Id_toLocaleString = 3,
Id_toSource = 4,
Id_valueOf = 5,
SymbolId_toStringTag = 6,
MAX_PROTOTYPE_ID = SymbolId_toStringTag;

private BigInteger bigIntValue;
}
Loading