Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ea6d22c
Literal operands.
aardvark179 Jun 2, 2026
ca0ba7b
Variable, this, super, and stack operators.
aardvark179 Jun 2, 2026
daf7dbe
Instruction stats tracking.
aardvark179 Jun 3, 2026
87dd3f7
Literals and simple keyword instructions.
aardvark179 Jun 3, 2026
ed77b76
Comparison and object operations.
aardvark179 Jun 3, 2026
30f0ffb
Arithmetic operation instructions.
aardvark179 Jun 3, 2026
cd9bbbc
Bit op instructions.
aardvark179 Jun 3, 2026
9eedbe0
Name instructions.
aardvark179 Jun 3, 2026
af68c13
Local variable instructions.
aardvark179 Jun 3, 2026
67206c5
Element and property instructions.
aardvark179 Jun 3, 2026
3be2ba7
Ref instructions.
aardvark179 Jun 3, 2026
86bde63
"... and this" instructions.
aardvark179 Jun 3, 2026
2f8c842
Call related instructions.
aardvark179 Jun 3, 2026
d6e7411
Complex literal instructions.
aardvark179 Jun 3, 2026
53548db
Simple control flow instructions.
aardvark179 Jun 3, 2026
0ece3f9
Exception related instructions.
aardvark179 Jun 3, 2026
83810ff
Generator related instructions.
aardvark179 Jun 3, 2026
468ecd3
Enumeration instructions.
aardvark179 Jun 3, 2026
1c9b4fb
XML related instructions.
aardvark179 Jun 3, 2026
9ff2f2b
Stack related instructions.
aardvark179 Jun 3, 2026
93a733f
Debugger instruction.
aardvark179 Jun 3, 2026
6630952
Add the compiler and enable all this.
aardvark179 Jun 2, 2026
e8ccc90
Fix for proxy get issue.
aardvark179 Jun 3, 2026
6241a8b
Enable in 262 tests.
aardvark179 Jun 2, 2026
dbdc1c0
Enable benchmarks in V2.
aardvark179 Jun 2, 2026
418d2c9
Tests.
aardvark179 Jun 23, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class BuiltinBenchmark {
@State(Scope.Thread)
public static class AbstractClassState {

@Param({"Interpreter", "Compiler"})
@Param({"Interpreter", "InterpreterV2", "Compiler"})
public EvaluationMethod evalMethod;

public void init()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static class GeneratorState {
Function transpiledGenerator;
Function noReturnGenerator;

@Param({"Interpreter", "Compiler"})
@Param({"Interpreter", "InterpreterV2", "Compiler"})
public EvaluationMethod evalMethod;

@Setup(Level.Trial)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static class MathState {
Function bitwiseRsh;
Function bitwiseSignedRsh;

@Param({"Interpreter", "Compiler"})
@Param({"Interpreter", "InterpreterV2", "Compiler"})
public EvaluationMethod evalMethod;

@Setup(Level.Trial)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static class FieldTestState {
Scriptable strings;
Scriptable ints;

@Param({"Interpreter", "Compiler"})
@Param({"Interpreter", "InterpreterV2", "Compiler"})
public EvaluationMethod evalMethod;

@Setup(Level.Trial)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public static class PropertyState {

Object object;

@Param({"Interpreter", "Compiler"})
@Param({"Interpreter", "InterpreterV2", "Compiler"})
public EvaluationMethod evalMethod;

@Setup(Level.Trial)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public abstract static class AbstractState {
Script script;
String fileName;

@Param({"Interpreter", "Compiler"})
@Param({"Interpreter", "InterpreterV2", "Compiler"})
public EvaluationMethod evalMethod;

AbstractState(String fileName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static class GeneratorState {
Function mediumThrow;
Function deepThrow;

@Param({"Interpreter", "Compiler"})
@Param({"Interpreter", "InterpreterV2", "Compiler"})
public EvaluationMethod evalMethod;

@Setup(Level.Trial)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public abstract static class AbstractState {
Context cx;
TopLevel scope;

@Param({"Interpreter", "Compiler"})
@Param({"Interpreter", "InterpreterV2", "Compiler"})
public EvaluationMethod evalMethod;

Callable getFunc(String name) {
Expand Down
6 changes: 6 additions & 0 deletions rhino/src/main/java/org/mozilla/javascript/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -2796,6 +2796,10 @@ private static void notifyDebugger_r(Context cx, DebuggableScript dscript, Strin
private static final Class<? extends Evaluator> InterpreterClass =
(Class<? extends Evaluator>) Kit.classOrNull("org.mozilla.javascript.Interpreter");

@SuppressWarnings("unchecked")
private static final Class<? extends Evaluator> InterpreterV2Class =
(Class<? extends Evaluator>) Kit.classOrNull("org.mozilla.javascript.InterpreterV2");

private Evaluator createCompiler() {
return evaluationMethod.createEvaluator();
}
Expand Down Expand Up @@ -2943,6 +2947,8 @@ public static boolean isCurrentContextStrict() {
public enum EvaluationMethod {
/** Original bytecode-based interpreter. */
Interpreter(-1, true, InterpreterClass),
/** New instruction & operand-based interpreter. */
InterpreterV2(-2, true, InterpreterV2Class),
/** JVM bytecode compiler. */
Compiler(9, false, CodegenClass);

Expand Down
9 changes: 7 additions & 2 deletions rhino/src/main/java/org/mozilla/javascript/InterpreterV2.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Objects;
import org.mozilla.javascript.ast.ScriptNode;
import org.mozilla.javascript.debug.DebuggableScript;
import org.mozilla.javascript.interpreterv2.Compiler;
import org.mozilla.javascript.interpreterv2.CompilerData;
import org.mozilla.javascript.interpreterv2.GeneratorState;
import org.mozilla.javascript.interpreterv2.instruction.JumpInstruction;
Expand Down Expand Up @@ -545,13 +546,17 @@ public static boolean doEquals(Context cx, CallFrameV2 frame, Operand left, Oper
@Override
public CompilationResult<JSScript> compileScript(
CompilerEnvirons compilerEnv, ScriptNode tree, String rawSource) {
throw new UnsupportedOperationException();
var compiler = new Compiler<JSScript>();
var res = compiler.compile(compilerEnv, tree, rawSource, false);
return new V2CompilationResult<>(res, compilerEnv.homeObject());
}

@Override
public CompilationResult<JSFunction> compileFunction(
CompilerEnvirons compilerEnv, ScriptNode tree, String rawSource) {
throw new UnsupportedOperationException();
var compiler = new Compiler<JSFunction>();
var res = compiler.compile(compilerEnv, tree, rawSource, true);
return new V2CompilationResult<>(res, compilerEnv.homeObject());
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion rhino/src/main/java/org/mozilla/javascript/JSFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public JSFunction(
}
}

JSFunction(
public JSFunction(
VarScope scope,
JSDescriptor<JSFunction> descriptor,
Scriptable lexicalThis,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ public Object get(String name, Scriptable start) {
DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), name);
if (targetDesc != null && targetDesc.isConfigurable(false)) {
if (targetDesc.isDataDescriptor() && targetDesc.isWritable(false)) {
if (!Objects.equals(trapResult, targetDesc.value)) {
if (!ScriptRuntime.shallowEq(trapResult, targetDesc.value)) {
throw ScriptRuntime.typeError(
"proxy get has to return the same value as the plain call");
}
Expand Down
93 changes: 62 additions & 31 deletions rhino/src/main/java/org/mozilla/javascript/NewLiteralStorage.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,24 @@ public void pushKey(Object key) {
}
}

public void setKeyAt(int idx, Object key) {
keys[idx] = key;
}

public void setValueAt(int idx, Object value) {
values[idx] = value;
}

public void setGetterAt(int idx, Object value) {
getterSetters[idx] = -1;
values[idx] = value;
}

public void setSetterAt(int idx, Object value) {
getterSetters[idx] = +1;
values[idx] = value;
}

public void spread(Context cx, VarScope scope, Object source, int sourcePosition) {
int indexBefore = index;
if (keys == null) {
Expand Down Expand Up @@ -231,44 +249,57 @@ private static final class NameInference extends NewLiteralStorage {

@Override
protected void attemptToInferFunctionName(Object value) {
// Try to infer the name if the value is a normal JS function
if (this.keys == null || !(value instanceof JSFunction)) {
if (this.keys == null) {
return;
}
int gs = getterSetters == null ? 0 : getterSetters[index];
inferFunctionName(this.keys[index], value, gs);
}
}

BaseFunction fun = (BaseFunction) value;
if (!"".equals(fun.get("name", fun))) {
return;
}
/**
* Set the inferred name on a function value placed under {@code propKey} in an object literal,
* matching the semantics of {@code SetFunctionName} (ECMA 9.2.13). Used by both V1 (via {@link
* NewLiteralStorage}) and V2 (directly from its ObjectLit instruction).
*
* @param propKey the property key (String, Symbol, or other id)
* @param value the candidate function value
* @param getterSetter -1 for getter, +1 for setter, 0 for regular value
*/
public static void inferFunctionName(Object propKey, Object value, int getterSetter) {
if (!(value instanceof JSFunction)) {
return;
}
BaseFunction fun = (BaseFunction) value;
if (!"".equals(fun.get("name", fun))) {
return;
}

String prefix = "";
if (getterSetters[index] == -1) {
prefix = "get ";
} else if (getterSetters[index] == +1) {
prefix = "set ";
}
String prefix = "";
if (getterSetter == -1) {
prefix = "get ";
} else if (getterSetter == +1) {
prefix = "set ";
}

Object propKey = this.keys[index];
if (propKey instanceof Symbol) {
// For symbol keys, valid names are: `[foo]`, `get [foo]`
// However `[]` or `get []` aren't, and become `` and `get `
String symbolName = ((Symbol) propKey).getName();
if (!symbolName.isEmpty()) {
fun.setFunctionName(prefix + "[" + symbolName + "]");
} else if (!prefix.isEmpty()) {
fun.setFunctionName(prefix);
}
if (propKey instanceof Symbol) {
// For symbol keys, valid names are: `[foo]`, `get [foo]`
// However `[]` or `get []` aren't, and become `` and `get `
String symbolName = ((Symbol) propKey).getName();
if (!symbolName.isEmpty()) {
fun.setFunctionName(prefix + "[" + symbolName + "]");
} else if (!prefix.isEmpty()) {
fun.setFunctionName(prefix);
}
} else {
if (!propKey.equals(PROTO_PROPERTY)) {
fun.setFunctionName(prefix + propKey);
} else {
// Key was already converted to a string
if (!propKey.equals(PROTO_PROPERTY)) {
// `__proto__` is, as usual, weird and applies only to methods, meaning:
// - { __proto__(){} } infers the name
// - { __proto__: function(){} } does not!
if (((JSFunction) fun).isShorthand()) {
fun.setFunctionName(prefix + propKey);
} else {
// `__proto__` is, as usual, weird and applies only to methods, meaning:
// - { __proto__(){} } infers the name
// - { __proto__: function(){} } does not!
if (fun instanceof JSFunction && ((JSFunction) fun).isShorthand()) {
fun.setFunctionName(prefix + propKey);
}
}
}
}
Expand Down
Loading
Loading