Skip to content

Commit 9a1f218

Browse files
authored
Fix interpreter bytecode printing
* Fixed exception in the interpreter when using many literal bigint The interpreter has various special icode for big int literals, but the ones to access the 5th onward literal were broken. I've fixed it and added a test. * Fixed a NPE when printing interpreter bytecode This is caused by the function descriptor refactoring of mozilla#2091 * Fixed exception when printing code that uses literal bigintegers --------- Co-authored-by: andrea.bergia <andrea.bergia@servicenow.com>
1 parent 774fb20 commit 9a1f218

4 files changed

Lines changed: 134 additions & 11 deletions

File tree

rhino/src/main/java/org/mozilla/javascript/CodeGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ private void generateICodeFromTree(Node tree) {
174174
itsData.literalIds = literalIds.toArray();
175175
}
176176

177-
if (Token.printICode) Interpreter.dumpICode(itsData);
177+
if (Token.printICode) Interpreter.dumpICode(itsData, builder);
178178
}
179179

180180
private void generateNestedFunctions() {

rhino/src/main/java/org/mozilla/javascript/Interpreter.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -657,19 +657,20 @@ private static int getExceptionHandler(CallFrame frame, boolean onlyFinally) {
657657
return best;
658658
}
659659

660-
static void dumpICode(InterpreterData.Builder idata) {
660+
static PrintStream interpreterBytecodePrintStream = System.out;
661+
662+
static <T extends ScriptOrFn<T>> void dumpICode(
663+
InterpreterData.Builder<T> idata, JSDescriptor.Builder<T> desc) {
661664
if (!Token.printICode) {
662665
return;
663666
}
664667

665-
JSDescriptor desc = null;
666-
667668
byte[] iCode = idata.itsICode;
668669
int iCodeLength = iCode.length;
669670
String[] strings = idata.itsStringTable;
670671
BigInteger[] bigInts = idata.itsBigIntTable;
671-
PrintStream out = System.out;
672-
out.println("ICode dump, for " + desc.getName() + ", length = " + iCodeLength);
672+
PrintStream out = interpreterBytecodePrintStream;
673+
out.println("ICode dump, for " + desc.name + ", length = " + iCodeLength);
673674
out.println("MaxStack = " + idata.itsMaxStack);
674675

675676
int indexReg = 0;
@@ -752,7 +753,7 @@ static void dumpICode(InterpreterData.Builder idata) {
752753
case Icode_CLOSURE_EXPR:
753754
case Icode_CLOSURE_STMT:
754755
case Icode_METHOD_EXPR:
755-
out.println(tname + " " + idata.itsNestedFunctions[indexReg]);
756+
out.println(tname + " #" + indexReg);
756757
break;
757758
case Token.CALL:
758759
case Icode_CALL_ON_SUPER:
@@ -897,12 +898,17 @@ static void dumpICode(InterpreterData.Builder idata) {
897898
out.println(tname + " " + indexReg);
898899
++pc;
899900
break;
900-
// TODO: Icode_REG_STR_C0-3 is not dump. I made this the same it.
901901
case Icode_REG_BIGINT_C0:
902+
out.println(tname + " " + bigInts[0].toString() + 'n');
903+
break;
902904
case Icode_REG_BIGINT_C1:
905+
out.println(tname + " " + bigInts[1].toString() + 'n');
906+
break;
903907
case Icode_REG_BIGINT_C2:
908+
out.println(tname + " " + bigInts[2].toString() + 'n');
909+
break;
904910
case Icode_REG_BIGINT_C3:
905-
Kit.codeBug();
911+
out.println(tname + " " + bigInts[3].toString() + 'n');
906912
break;
907913
case Icode_REG_BIGINT1:
908914
{

rhino/src/main/java/org/mozilla/javascript/Token.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ public static enum CommentType {
2727

2828
// debug flags
2929
public static final boolean printTrees = RhinoConfig.get("rhino.printTrees", false);
30-
static final boolean printICode = RhinoConfig.get("rhino.printICode", false);
31-
static final boolean printNames = printTrees || printICode;
30+
static boolean printICode = RhinoConfig.get("rhino.printICode", false);
31+
static boolean printNames = printTrees || printICode;
3232

3333
/** Token types. These values correspond to JSTokenType values in jsscan.c. */
3434
public static final int
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
package org.mozilla.javascript;
6+
7+
import static java.nio.charset.StandardCharsets.UTF_8;
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
10+
import java.io.ByteArrayOutputStream;
11+
import java.io.IOException;
12+
import java.io.PrintStream;
13+
import org.junit.jupiter.api.Test;
14+
15+
// Simple smoke tests for dumping of the bytecode generated in interpreter mode
16+
class InterpreterBytecodeDumpTest {
17+
@Test
18+
void basicSmokeTest() throws IOException {
19+
assertEquals(
20+
""
21+
+ "ICode dump, for null, length = 8\n"
22+
+ "MaxStack = 1\n"
23+
+ " [0] LINE : 1\n"
24+
+ " [3] SHORTNUMBER 42\n"
25+
+ " [6] POP_RESULT\n"
26+
+ " [7] RETURN_RESULT\n",
27+
getByteCodeFrom("42"));
28+
}
29+
30+
@Test
31+
void functionNamesArePrinted() throws IOException {
32+
assertEquals(
33+
""
34+
+ "ICode dump, for f, length = 4\n"
35+
+ "MaxStack = 0\n"
36+
+ " [0] LINE : 1\n"
37+
+ " [3] RETUNDEF\n"
38+
+ "ICode dump, for null, length = 1\n"
39+
+ "MaxStack = 0\n"
40+
+ " [0] RETURN_RESULT\n",
41+
getByteCodeFrom("function f() {}"));
42+
}
43+
44+
@Test
45+
void methodsArePrinted() throws IOException {
46+
assertEquals(
47+
""
48+
+ "ICode dump, for f, length = 4\n"
49+
+ "MaxStack = 0\n"
50+
+ " [0] LINE : 1\n"
51+
+ " [3] RETUNDEF\n"
52+
+ "ICode dump, for null, length = 16\n"
53+
+ "MaxStack = 4\n"
54+
+ " [0] LINE : 1\n"
55+
+ " [3] REG_STR_C0 \"o\"\n"
56+
+ " [4] BINDNAME\n"
57+
+ " [5] REG_IND_C0\n"
58+
+ " [6] LITERAL_NEW_OBJECT [f] false\n"
59+
+ " [8] REG_IND_C0\n"
60+
+ " [9] METHOD_EXPR #0\n"
61+
+ " [10] LITERAL_SET\n"
62+
+ " [11] OBJECTLIT\n"
63+
+ " [12] REG_STR_C0 \"o\"\n"
64+
+ " [13] SETNAME\n"
65+
+ " [14] POP_RESULT\n"
66+
+ " [15] RETURN_RESULT\n",
67+
getByteCodeFrom("o = { f() {} }"));
68+
}
69+
70+
@Test
71+
void bigIntsArePrinted() throws IOException {
72+
assertEquals(
73+
""
74+
+ "ICode dump, for null, length = 20\n"
75+
+ "MaxStack = 2\n"
76+
+ " [0] LINE : 1\n"
77+
+ " [3] REG_BIGINT_C0 1n\n"
78+
+ " [4] BIGINT\n"
79+
+ " [5] REG_BIGINT_C1 2n\n"
80+
+ " [6] BIGINT\n"
81+
+ " [7] ADD\n"
82+
+ " [8] REG_BIGINT_C2 3n\n"
83+
+ " [9] BIGINT\n"
84+
+ " [10] ADD\n"
85+
+ " [11] REG_BIGINT_C3 4n\n"
86+
+ " [12] BIGINT\n"
87+
+ " [13] ADD\n"
88+
+ " [14] LOAD_BIGINT1 5n\n"
89+
+ " [16] BIGINT\n"
90+
+ " [17] ADD\n"
91+
+ " [18] POP_RESULT\n"
92+
+ " [19] RETURN_RESULT\n",
93+
getByteCodeFrom("1n + 2n + 3n + 4n + 5n"));
94+
}
95+
96+
private static String getByteCodeFrom(String source) throws IOException {
97+
var oldBytecodePrintStream = Interpreter.interpreterBytecodePrintStream;
98+
var oldTokenPrintICode = Token.printICode;
99+
var oldTokenPrintNames = Token.printNames;
100+
try (var buffer = new ByteArrayOutputStream()) {
101+
Interpreter.interpreterBytecodePrintStream = new PrintStream(buffer);
102+
Token.printICode = true;
103+
Token.printNames = true;
104+
105+
try (Context cx = Context.enter()) {
106+
cx.setInterpretedMode(true);
107+
cx.compileString(source, "test", 1, null);
108+
}
109+
110+
return buffer.toString(UTF_8);
111+
} finally {
112+
Token.printNames = oldTokenPrintNames;
113+
Token.printICode = oldTokenPrintICode;
114+
Interpreter.interpreterBytecodePrintStream = oldBytecodePrintStream;
115+
}
116+
}
117+
}

0 commit comments

Comments
 (0)