зеркало из https://github.com/mozilla/pjs.git
More tokens used only in Interpreter are moved from Token to Interpreter. I also added addToken/addIcode to be used instead of simple addByte to catch bugs about wrong byte code as soon as possible.
This commit is contained in:
Родитель
8cd43155f4
Коммит
b4041d1788
|
@ -46,40 +46,55 @@ public class Interpreter
|
|||
{
|
||||
|
||||
// Additional interpreter-specific codes
|
||||
private static final int BASE_ICODE = Token.LAST_BYTECODE_TOKEN;
|
||||
|
||||
private static final int
|
||||
Icode_DUP = BASE_ICODE + 1,
|
||||
|
||||
Icode_DUP = Token.LAST_BYTECODE_TOKEN + 1,
|
||||
// various types of ++/--
|
||||
Icode_NAMEINC = BASE_ICODE + 2,
|
||||
Icode_PROPINC = BASE_ICODE + 3,
|
||||
Icode_ELEMINC = BASE_ICODE + 4,
|
||||
Icode_VARINC = BASE_ICODE + 5,
|
||||
Icode_NAMEDEC = BASE_ICODE + 6,
|
||||
Icode_PROPDEC = BASE_ICODE + 7,
|
||||
Icode_ELEMDEC = BASE_ICODE + 8,
|
||||
Icode_VARDEC = BASE_ICODE + 9,
|
||||
|
||||
// GETVAR helper
|
||||
Icode_SCOPE = Token.LAST_BYTECODE_TOKEN + 2,
|
||||
// helper codes to deal with activation
|
||||
Icode_SCOPE = BASE_ICODE + 10,
|
||||
Icode_TYPEOFNAME = BASE_ICODE + 11,
|
||||
|
||||
// Access to parent scope and prototype
|
||||
Icode_GETPROTO = Token.LAST_BYTECODE_TOKEN + 3,
|
||||
Icode_GETPARENT = Token.LAST_BYTECODE_TOKEN + 4,
|
||||
Icode_GETSCOPEPARENT = Token.LAST_BYTECODE_TOKEN + 5,
|
||||
Icode_SETPROTO = Token.LAST_BYTECODE_TOKEN + 6,
|
||||
Icode_SETPARENT = Token.LAST_BYTECODE_TOKEN + 7,
|
||||
Icode_GETPROTO = BASE_ICODE + 12,
|
||||
Icode_GETPARENT = BASE_ICODE + 13,
|
||||
Icode_GETSCOPEPARENT = BASE_ICODE + 14,
|
||||
Icode_SETPROTO = BASE_ICODE + 15,
|
||||
Icode_SETPARENT = BASE_ICODE + 16,
|
||||
|
||||
// Create closure object for nested functions
|
||||
Icode_CLOSURE = BASE_ICODE + 17,
|
||||
|
||||
// Special calls
|
||||
Icode_CALLSPECIAL = Token.LAST_BYTECODE_TOKEN + 8,
|
||||
Icode_CALLSPECIAL = BASE_ICODE + 18,
|
||||
|
||||
// To return undefined value
|
||||
Icode_RETUNDEF = Token.LAST_BYTECODE_TOKEN + 9,
|
||||
Icode_RETUNDEF = BASE_ICODE + 19,
|
||||
|
||||
// Exception handling implementation
|
||||
Icode_CATCH = Token.LAST_BYTECODE_TOKEN + 10,
|
||||
Icode_GOSUB = Token.LAST_BYTECODE_TOKEN + 11,
|
||||
Icode_RETSUB = Token.LAST_BYTECODE_TOKEN + 12,
|
||||
Icode_CATCH = BASE_ICODE + 20,
|
||||
Icode_GOSUB = BASE_ICODE + 21,
|
||||
Icode_RETSUB = BASE_ICODE + 22,
|
||||
|
||||
// To indicating a line number change in icodes.
|
||||
Icode_LINE = Token.LAST_BYTECODE_TOKEN + 13,
|
||||
Icode_LINE = BASE_ICODE + 23,
|
||||
|
||||
// To store shorts and ints inline
|
||||
Icode_SHORTNUMBER = Token.LAST_BYTECODE_TOKEN + 14,
|
||||
Icode_INTNUMBER = Token.LAST_BYTECODE_TOKEN + 15,
|
||||
Icode_SHORTNUMBER = BASE_ICODE + 24,
|
||||
Icode_INTNUMBER = BASE_ICODE + 25,
|
||||
|
||||
// Last icode
|
||||
Icode_END = Token.LAST_BYTECODE_TOKEN + 16;
|
||||
Icode_END = BASE_ICODE + 26;
|
||||
|
||||
|
||||
public IRFactory createIRFactory(Context cx, TokenStream ts)
|
||||
|
@ -200,17 +215,18 @@ public class Interpreter
|
|||
itsData.itsRegExpLiterals = array;
|
||||
}
|
||||
|
||||
private void generateICodeFromTree(Node tree) {
|
||||
private void generateICodeFromTree(Node tree)
|
||||
{
|
||||
int theICodeTop = 0;
|
||||
theICodeTop = generateICode(tree, theICodeTop);
|
||||
itsLabels.fixLabelGotos(itsData.itsICode);
|
||||
// add Icode_END only to scripts as function always ends with RETURN
|
||||
if (itsData.itsFunctionType == 0) {
|
||||
theICodeTop = addByte(Icode_END, theICodeTop);
|
||||
theICodeTop = addIcode(Icode_END, theICodeTop);
|
||||
}
|
||||
// Add special CATCH to simplify Interpreter.interpret logic
|
||||
// and workaround lack of goto in Java
|
||||
theICodeTop = addByte(Icode_CATCH, theICodeTop);
|
||||
theICodeTop = addIcode(Icode_CATCH, theICodeTop);
|
||||
|
||||
itsData.itsICodeTop = theICodeTop;
|
||||
|
||||
|
@ -261,17 +277,19 @@ public class Interpreter
|
|||
itsData.argCount = scriptOrFn.getParamCount();
|
||||
}
|
||||
|
||||
private int updateLineNumber(Node node, int iCodeTop) {
|
||||
private int updateLineNumber(Node node, int iCodeTop)
|
||||
{
|
||||
int lineno = node.getLineno();
|
||||
if (lineno != itsLineNumber && lineno >= 0) {
|
||||
itsLineNumber = lineno;
|
||||
iCodeTop = addByte(Icode_LINE, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_LINE, iCodeTop);
|
||||
iCodeTop = addShort(lineno, iCodeTop);
|
||||
}
|
||||
return iCodeTop;
|
||||
}
|
||||
|
||||
private void badTree(Node node) {
|
||||
private void badTree(Node node)
|
||||
{
|
||||
try {
|
||||
out = new PrintWriter(new FileOutputStream("icode.txt", true));
|
||||
out.println("Un-handled node : " + node.toString());
|
||||
|
@ -282,7 +300,8 @@ public class Interpreter
|
|||
+ node.toString());
|
||||
}
|
||||
|
||||
private int generateICode(Node node, int iCodeTop) {
|
||||
private int generateICode(Node node, int iCodeTop)
|
||||
{
|
||||
int type = node.getType();
|
||||
Node child = node.getFirstChild();
|
||||
Node firstChild = child;
|
||||
|
@ -296,7 +315,7 @@ public class Interpreter
|
|||
// statements needs closure code creating new function
|
||||
// object on stack as function statements are initialized
|
||||
// at script/function start
|
||||
iCodeTop = addByte(Token.CLOSURE, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_CLOSURE, iCodeTop);
|
||||
iCodeTop = addIndex(fnIndex, iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
|
@ -349,7 +368,7 @@ public class Interpreter
|
|||
case Token.COMMA :
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
while (null != (child = child.getNext())) {
|
||||
iCodeTop = addByte(Token.POP, iCodeTop);
|
||||
iCodeTop = addToken(Token.POP, iCodeTop);
|
||||
itsStackDepth--;
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
}
|
||||
|
@ -359,9 +378,9 @@ public class Interpreter
|
|||
iCodeTop = updateLineNumber(node, iCodeTop);
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
int theLocalSlot = itsData.itsMaxLocals++;
|
||||
iCodeTop = addByte(Token.NEWTEMP, iCodeTop);
|
||||
iCodeTop = addToken(Token.NEWTEMP, iCodeTop);
|
||||
iCodeTop = addByte(theLocalSlot, iCodeTop);
|
||||
iCodeTop = addByte(Token.POP, iCodeTop);
|
||||
iCodeTop = addToken(Token.POP, iCodeTop);
|
||||
itsStackDepth--;
|
||||
|
||||
ObjArray cases = (ObjArray) node.getProp(Node.CASES_PROP);
|
||||
|
@ -373,12 +392,12 @@ public class Interpreter
|
|||
// statements are encountered as siblings of
|
||||
// the switch statement.
|
||||
iCodeTop = generateICode(first, iCodeTop);
|
||||
iCodeTop = addByte(Token.USETEMP, iCodeTop);
|
||||
iCodeTop = addToken(Token.USETEMP, iCodeTop);
|
||||
iCodeTop = addByte(theLocalSlot, iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
itsData.itsMaxStack = itsStackDepth;
|
||||
iCodeTop = addByte(Token.SHEQ, iCodeTop);
|
||||
iCodeTop = addToken(Token.SHEQ, iCodeTop);
|
||||
itsStackDepth--;
|
||||
Node target = new Node(Token.TARGET);
|
||||
thisCase.addChildAfter(target, first);
|
||||
|
@ -418,7 +437,7 @@ public class Interpreter
|
|||
op = Token.SHNE;
|
||||
}
|
||||
}
|
||||
iCodeTop = addByte(op, iCodeTop);
|
||||
iCodeTop = addToken(op, iCodeTop);
|
||||
itsStackDepth--;
|
||||
break;
|
||||
}
|
||||
|
@ -444,13 +463,12 @@ public class Interpreter
|
|||
Node.NON_SPECIALCALL);
|
||||
if (callType != Node.NON_SPECIALCALL) {
|
||||
// embed line number and source filename
|
||||
iCodeTop = addByte(Icode_CALLSPECIAL, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_CALLSPECIAL, iCodeTop);
|
||||
iCodeTop = addByte(callType, iCodeTop);
|
||||
iCodeTop = addByte(type == Token.NEW ? 1 : 0,
|
||||
iCodeTop);
|
||||
iCodeTop = addByte(type == Token.NEW ? 1 : 0, iCodeTop);
|
||||
iCodeTop = addShort(itsLineNumber, iCodeTop);
|
||||
} else {
|
||||
iCodeTop = addByte(type, iCodeTop);
|
||||
iCodeTop = addToken(type, iCodeTop);
|
||||
iCodeTop = addString(functionName, iCodeTop);
|
||||
}
|
||||
|
||||
|
@ -470,16 +488,16 @@ public class Interpreter
|
|||
case Token.NEWLOCAL :
|
||||
case Token.NEWTEMP : {
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(Token.NEWTEMP, iCodeTop);
|
||||
iCodeTop = addToken(Token.NEWTEMP, iCodeTop);
|
||||
iCodeTop = addLocalRef(node, iCodeTop);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.USELOCAL : {
|
||||
if (node.getProp(Node.TARGET_PROP) != null) {
|
||||
iCodeTop = addByte(Icode_RETSUB, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_RETSUB, iCodeTop);
|
||||
} else {
|
||||
iCodeTop = addByte(Token.USETEMP, iCodeTop);
|
||||
iCodeTop = addToken(Token.USETEMP, iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
itsData.itsMaxStack = itsStackDepth;
|
||||
|
@ -490,7 +508,7 @@ public class Interpreter
|
|||
}
|
||||
|
||||
case Token.USETEMP : {
|
||||
iCodeTop = addByte(Token.USETEMP, iCodeTop);
|
||||
iCodeTop = addToken(Token.USETEMP, iCodeTop);
|
||||
Node temp = (Node) node.getProp(Node.TEMP_PROP);
|
||||
iCodeTop = addLocalRef(temp, iCodeTop);
|
||||
itsStackDepth++;
|
||||
|
@ -518,13 +536,13 @@ public class Interpreter
|
|||
|
||||
case Token.AND : {
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(Icode_DUP, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_DUP, iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
itsData.itsMaxStack = itsStackDepth;
|
||||
int falseJumpStart = iCodeTop;
|
||||
iCodeTop = addForwardGoto(Token.IFNE, iCodeTop);
|
||||
iCodeTop = addByte(Token.POP, iCodeTop);
|
||||
iCodeTop = addToken(Token.POP, iCodeTop);
|
||||
itsStackDepth--;
|
||||
child = child.getNext();
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
|
@ -534,13 +552,13 @@ public class Interpreter
|
|||
|
||||
case Token.OR : {
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(Icode_DUP, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_DUP, iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
itsData.itsMaxStack = itsStackDepth;
|
||||
int trueJumpStart = iCodeTop;
|
||||
iCodeTop = addForwardGoto(Token.IFEQ, iCodeTop);
|
||||
iCodeTop = addByte(Token.POP, iCodeTop);
|
||||
iCodeTop = addToken(Token.POP, iCodeTop);
|
||||
itsStackDepth--;
|
||||
child = child.getNext();
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
|
@ -553,16 +571,16 @@ public class Interpreter
|
|||
String s = (String) node.getProp(Node.SPECIAL_PROP_PROP);
|
||||
if (s != null) {
|
||||
if (s.equals("__proto__")) {
|
||||
iCodeTop = addByte(Icode_GETPROTO, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_GETPROTO, iCodeTop);
|
||||
} else if (s.equals("__parent__")) {
|
||||
iCodeTop = addByte(Icode_GETSCOPEPARENT, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_GETSCOPEPARENT, iCodeTop);
|
||||
} else {
|
||||
badTree(node);
|
||||
}
|
||||
} else {
|
||||
child = child.getNext();
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(Token.GETPROP, iCodeTop);
|
||||
iCodeTop = addToken(Token.GETPROP, iCodeTop);
|
||||
itsStackDepth--;
|
||||
}
|
||||
break;
|
||||
|
@ -584,7 +602,7 @@ public class Interpreter
|
|||
iCodeTop = generateICode(child, iCodeTop);
|
||||
child = child.getNext();
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(type, iCodeTop);
|
||||
iCodeTop = addToken(type, iCodeTop);
|
||||
itsStackDepth--;
|
||||
break;
|
||||
|
||||
|
@ -592,7 +610,7 @@ public class Interpreter
|
|||
iCodeTop = generateICode(child, iCodeTop);
|
||||
Object toType = node.getProp(Node.TYPE_PROP);
|
||||
if (toType == ScriptRuntime.NumberClass) {
|
||||
iCodeTop = addByte(Token.POS, iCodeTop);
|
||||
iCodeTop = addToken(Token.POS, iCodeTop);
|
||||
} else {
|
||||
badTree(node);
|
||||
}
|
||||
|
@ -603,33 +621,33 @@ public class Interpreter
|
|||
iCodeTop = generateICode(child, iCodeTop);
|
||||
switch (node.getOperation()) {
|
||||
case Token.VOID :
|
||||
iCodeTop = addByte(Token.POP, iCodeTop);
|
||||
iCodeTop = addByte(Token.UNDEFINED, iCodeTop);
|
||||
iCodeTop = addToken(Token.POP, iCodeTop);
|
||||
iCodeTop = addToken(Token.UNDEFINED, iCodeTop);
|
||||
break;
|
||||
case Token.NOT : {
|
||||
int trueJumpStart = iCodeTop;
|
||||
iCodeTop = addForwardGoto(Token.IFEQ,
|
||||
iCodeTop);
|
||||
iCodeTop = addByte(Token.TRUE, iCodeTop);
|
||||
iCodeTop = addToken(Token.TRUE, iCodeTop);
|
||||
int beyondJumpStart = iCodeTop;
|
||||
iCodeTop = addForwardGoto(Token.GOTO,
|
||||
iCodeTop);
|
||||
resolveForwardGoto(trueJumpStart, iCodeTop);
|
||||
iCodeTop = addByte(Token.FALSE, iCodeTop);
|
||||
iCodeTop = addToken(Token.FALSE, iCodeTop);
|
||||
resolveForwardGoto(beyondJumpStart, iCodeTop);
|
||||
break;
|
||||
}
|
||||
case Token.BITNOT :
|
||||
iCodeTop = addByte(Token.BITNOT, iCodeTop);
|
||||
iCodeTop = addToken(Token.BITNOT, iCodeTop);
|
||||
break;
|
||||
case Token.TYPEOF :
|
||||
iCodeTop = addByte(Token.TYPEOF, iCodeTop);
|
||||
iCodeTop = addToken(Token.TYPEOF, iCodeTop);
|
||||
break;
|
||||
case Token.SUB :
|
||||
iCodeTop = addByte(Token.NEG, iCodeTop);
|
||||
iCodeTop = addToken(Token.NEG, iCodeTop);
|
||||
break;
|
||||
case Token.ADD :
|
||||
iCodeTop = addByte(Token.POS, iCodeTop);
|
||||
iCodeTop = addToken(Token.POS, iCodeTop);
|
||||
break;
|
||||
default:
|
||||
badTree(node);
|
||||
|
@ -644,16 +662,16 @@ public class Interpreter
|
|||
String s = (String) node.getProp(Node.SPECIAL_PROP_PROP);
|
||||
if (s != null) {
|
||||
if (s.equals("__proto__")) {
|
||||
iCodeTop = addByte(Icode_SETPROTO, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_SETPROTO, iCodeTop);
|
||||
} else if (s.equals("__parent__")) {
|
||||
iCodeTop = addByte(Icode_SETPARENT, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_SETPARENT, iCodeTop);
|
||||
} else {
|
||||
badTree(node);
|
||||
}
|
||||
} else {
|
||||
child = child.getNext();
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(Token.SETPROP, iCodeTop);
|
||||
iCodeTop = addToken(Token.SETPROP, iCodeTop);
|
||||
itsStackDepth -= 2;
|
||||
}
|
||||
break;
|
||||
|
@ -665,7 +683,7 @@ public class Interpreter
|
|||
iCodeTop = generateICode(child, iCodeTop);
|
||||
child = child.getNext();
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(type, iCodeTop);
|
||||
iCodeTop = addToken(Token.SETELEM, iCodeTop);
|
||||
itsStackDepth -= 2;
|
||||
break;
|
||||
|
||||
|
@ -673,7 +691,7 @@ public class Interpreter
|
|||
iCodeTop = generateICode(child, iCodeTop);
|
||||
child = child.getNext();
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(Token.SETNAME, iCodeTop);
|
||||
iCodeTop = addToken(Token.SETNAME, iCodeTop);
|
||||
iCodeTop = addString(firstChild.getString(), iCodeTop);
|
||||
itsStackDepth--;
|
||||
break;
|
||||
|
@ -686,12 +704,12 @@ public class Interpreter
|
|||
if (itsInFunctionFlag && !itsData.itsNeedsActivation)
|
||||
index = scriptOrFn.getParamOrVarIndex(name);
|
||||
if (index == -1) {
|
||||
iCodeTop = addByte(Token.TYPEOFNAME, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_TYPEOFNAME, iCodeTop);
|
||||
iCodeTop = addString(name, iCodeTop);
|
||||
} else {
|
||||
iCodeTop = addByte(Token.GETVAR, iCodeTop);
|
||||
iCodeTop = addToken(Token.GETVAR, iCodeTop);
|
||||
iCodeTop = addByte(index, iCodeTop);
|
||||
iCodeTop = addByte(Token.TYPEOF, iCodeTop);
|
||||
iCodeTop = addToken(Token.TYPEOF, iCodeTop);
|
||||
}
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
|
@ -701,14 +719,14 @@ public class Interpreter
|
|||
|
||||
case Token.PARENT :
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(Icode_GETPARENT, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_GETPARENT, iCodeTop);
|
||||
break;
|
||||
|
||||
case Token.GETBASE :
|
||||
case Token.BINDNAME :
|
||||
case Token.NAME :
|
||||
case Token.STRING :
|
||||
iCodeTop = addByte(type, iCodeTop);
|
||||
iCodeTop = addToken(type, iCodeTop);
|
||||
iCodeTop = addString(node.getString(), iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
|
@ -722,23 +740,23 @@ public class Interpreter
|
|||
case Token.GETVAR : {
|
||||
String name = child.getString();
|
||||
if (itsData.itsNeedsActivation) {
|
||||
iCodeTop = addByte(Icode_SCOPE, iCodeTop);
|
||||
iCodeTop = addByte(Token.STRING, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_SCOPE, iCodeTop);
|
||||
iCodeTop = addToken(Token.STRING, iCodeTop);
|
||||
iCodeTop = addString(name, iCodeTop);
|
||||
itsStackDepth += 2;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
itsData.itsMaxStack = itsStackDepth;
|
||||
iCodeTop = addByte(type == Token.INC
|
||||
? Token.PROPINC
|
||||
: Token.PROPDEC,
|
||||
iCodeTop);
|
||||
iCodeTop = addIcode(type == Token.INC
|
||||
? Icode_PROPINC
|
||||
: Icode_PROPDEC,
|
||||
iCodeTop);
|
||||
itsStackDepth--;
|
||||
} else {
|
||||
int i = scriptOrFn.getParamOrVarIndex(name);
|
||||
iCodeTop = addByte(type == Token.INC
|
||||
? Token.VARINC
|
||||
: Token.VARDEC,
|
||||
iCodeTop);
|
||||
iCodeTop = addIcode(type == Token.INC
|
||||
? Icode_VARINC
|
||||
: Icode_VARDEC,
|
||||
iCodeTop);
|
||||
iCodeTop = addByte(i, iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
|
@ -752,25 +770,23 @@ public class Interpreter
|
|||
iCodeTop = generateICode(getPropChild, iCodeTop);
|
||||
getPropChild = getPropChild.getNext();
|
||||
iCodeTop = generateICode(getPropChild, iCodeTop);
|
||||
int icode;
|
||||
if (childType == Token.GETPROP) {
|
||||
iCodeTop = addByte(type == Token.INC
|
||||
? Token.PROPINC
|
||||
: Token.PROPDEC,
|
||||
iCodeTop);
|
||||
icode = (type == Token.INC)
|
||||
? Icode_PROPINC : Icode_PROPDEC;
|
||||
} else {
|
||||
iCodeTop = addByte(type == Token.INC
|
||||
? Token.ELEMINC
|
||||
: Token.ELEMDEC,
|
||||
iCodeTop);
|
||||
icode = (type == Token.INC)
|
||||
? Icode_ELEMINC : Icode_ELEMDEC;
|
||||
}
|
||||
iCodeTop = addIcode(icode, iCodeTop);
|
||||
itsStackDepth--;
|
||||
break;
|
||||
}
|
||||
default : {
|
||||
iCodeTop = addByte(type == Token.INC
|
||||
? Token.NAMEINC
|
||||
: Token.NAMEDEC,
|
||||
iCodeTop);
|
||||
iCodeTop = addIcode(type == Token.INC
|
||||
? Icode_NAMEINC
|
||||
: Icode_NAMEDEC,
|
||||
iCodeTop);
|
||||
iCodeTop = addString(child.getString(), iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
|
@ -786,18 +802,18 @@ public class Interpreter
|
|||
int inum = (int)num;
|
||||
if (inum == num) {
|
||||
if (inum == 0) {
|
||||
iCodeTop = addByte(Token.ZERO, iCodeTop);
|
||||
iCodeTop = addToken(Token.ZERO, iCodeTop);
|
||||
} else if (inum == 1) {
|
||||
iCodeTop = addByte(Token.ONE, iCodeTop);
|
||||
iCodeTop = addToken(Token.ONE, iCodeTop);
|
||||
} else if ((short)inum == inum) {
|
||||
iCodeTop = addByte(Icode_SHORTNUMBER, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_SHORTNUMBER, iCodeTop);
|
||||
iCodeTop = addShort(inum, iCodeTop);
|
||||
} else {
|
||||
iCodeTop = addByte(Icode_INTNUMBER, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_INTNUMBER, iCodeTop);
|
||||
iCodeTop = addInt(inum, iCodeTop);
|
||||
}
|
||||
} else {
|
||||
iCodeTop = addByte(Token.NUMBER, iCodeTop);
|
||||
iCodeTop = addToken(Token.NUMBER, iCodeTop);
|
||||
iCodeTop = addDouble(num, iCodeTop);
|
||||
}
|
||||
itsStackDepth++;
|
||||
|
@ -811,24 +827,24 @@ public class Interpreter
|
|||
iCodeTop = updateLineNumber(node, iCodeTop);
|
||||
case Token.ENTERWITH :
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(type, iCodeTop);
|
||||
iCodeTop = addToken(type, iCodeTop);
|
||||
itsStackDepth--;
|
||||
break;
|
||||
|
||||
case Token.GETTHIS :
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(type, iCodeTop);
|
||||
iCodeTop = addToken(Token.GETTHIS, iCodeTop);
|
||||
break;
|
||||
|
||||
case Token.NEWSCOPE :
|
||||
iCodeTop = addByte(type, iCodeTop);
|
||||
iCodeTop = addToken(Token.NEWSCOPE, iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
itsData.itsMaxStack = itsStackDepth;
|
||||
break;
|
||||
|
||||
case Token.LEAVEWITH :
|
||||
iCodeTop = addByte(type, iCodeTop);
|
||||
iCodeTop = addToken(Token.LEAVEWITH, iCodeTop);
|
||||
break;
|
||||
|
||||
case Token.TRY : {
|
||||
|
@ -905,7 +921,7 @@ public class Interpreter
|
|||
case Token.THROW :
|
||||
iCodeTop = updateLineNumber(node, iCodeTop);
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(Token.THROW, iCodeTop);
|
||||
iCodeTop = addToken(Token.THROW, iCodeTop);
|
||||
itsStackDepth--;
|
||||
break;
|
||||
|
||||
|
@ -913,10 +929,10 @@ public class Interpreter
|
|||
iCodeTop = updateLineNumber(node, iCodeTop);
|
||||
if (child != null) {
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(Token.RETURN, iCodeTop);
|
||||
iCodeTop = addToken(Token.RETURN, iCodeTop);
|
||||
itsStackDepth--;
|
||||
} else {
|
||||
iCodeTop = addByte(Icode_RETUNDEF, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_RETUNDEF, iCodeTop);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -927,17 +943,17 @@ public class Interpreter
|
|||
// we can't do that to a GETVAR without manufacturing
|
||||
// bogus children. Instead we use a special op to
|
||||
// push the current scope.
|
||||
iCodeTop = addByte(Icode_SCOPE, iCodeTop);
|
||||
iCodeTop = addByte(Token.STRING, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_SCOPE, iCodeTop);
|
||||
iCodeTop = addToken(Token.STRING, iCodeTop);
|
||||
iCodeTop = addString(name, iCodeTop);
|
||||
itsStackDepth += 2;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
itsData.itsMaxStack = itsStackDepth;
|
||||
iCodeTop = addByte(Token.GETPROP, iCodeTop);
|
||||
iCodeTop = addToken(Token.GETPROP, iCodeTop);
|
||||
itsStackDepth--;
|
||||
} else {
|
||||
int index = scriptOrFn.getParamOrVarIndex(name);
|
||||
iCodeTop = addByte(Token.GETVAR, iCodeTop);
|
||||
iCodeTop = addToken(Token.GETVAR, iCodeTop);
|
||||
iCodeTop = addByte(index, iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
|
@ -956,14 +972,14 @@ public class Interpreter
|
|||
child = child.getNext();
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
int index = scriptOrFn.getParamOrVarIndex(name);
|
||||
iCodeTop = addByte(Token.SETVAR, iCodeTop);
|
||||
iCodeTop = addToken(Token.SETVAR, iCodeTop);
|
||||
iCodeTop = addByte(index, iCodeTop);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.PRIMARY:
|
||||
iCodeTop = addByte(node.getOperation(), iCodeTop);
|
||||
iCodeTop = addToken(node.getOperation(), iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
itsData.itsMaxStack = itsStackDepth;
|
||||
|
@ -971,13 +987,13 @@ public class Interpreter
|
|||
|
||||
case Token.ENUMINIT :
|
||||
iCodeTop = generateICode(child, iCodeTop);
|
||||
iCodeTop = addByte(Token.ENUMINIT, iCodeTop);
|
||||
iCodeTop = addToken(Token.ENUMINIT, iCodeTop);
|
||||
iCodeTop = addLocalRef(node, iCodeTop);
|
||||
itsStackDepth--;
|
||||
break;
|
||||
|
||||
case Token.ENUMNEXT : {
|
||||
iCodeTop = addByte(Token.ENUMNEXT, iCodeTop);
|
||||
iCodeTop = addToken(Token.ENUMNEXT, iCodeTop);
|
||||
Node init = (Node)node.getProp(Node.ENUM_PROP);
|
||||
iCodeTop = addLocalRef(init, iCodeTop);
|
||||
itsStackDepth++;
|
||||
|
@ -992,7 +1008,7 @@ public class Interpreter
|
|||
|
||||
case Token.REGEXP : {
|
||||
int index = node.getExistingIntProp(Node.REGEXP_PROP);
|
||||
iCodeTop = addByte(Token.REGEXP, iCodeTop);
|
||||
iCodeTop = addToken(Token.REGEXP, iCodeTop);
|
||||
iCodeTop = addIndex(index, iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
|
@ -1029,16 +1045,22 @@ public class Interpreter
|
|||
return targetLabel;
|
||||
}
|
||||
|
||||
private void markTargetLabel(Node target, int iCodeTop) {
|
||||
private void markTargetLabel(Node target, int iCodeTop)
|
||||
{
|
||||
int label = getTargetLabel(target);
|
||||
itsLabels.markLabel(label, iCodeTop);
|
||||
}
|
||||
|
||||
private int addGoto(Node target, int gotoOp, int iCodeTop) {
|
||||
private int addGoto(Node target, int gotoOp, int iCodeTop)
|
||||
{
|
||||
int targetLabel = getTargetLabel(target);
|
||||
|
||||
int gotoPC = iCodeTop;
|
||||
iCodeTop = addByte(gotoOp, iCodeTop);
|
||||
if (gotoOp > BASE_ICODE) {
|
||||
iCodeTop = addIcode(gotoOp, iCodeTop);
|
||||
} else {
|
||||
iCodeTop = addToken(gotoOp, iCodeTop);
|
||||
}
|
||||
iCodeTop = addShort(0, iCodeTop);
|
||||
|
||||
int targetPC = itsLabels.getLabelPC(targetLabel);
|
||||
|
@ -1050,20 +1072,23 @@ public class Interpreter
|
|||
return iCodeTop;
|
||||
}
|
||||
|
||||
private int addForwardGoto(int gotoOp, int iCodeTop) {
|
||||
iCodeTop = addByte(gotoOp, iCodeTop);
|
||||
private int addForwardGoto(int gotoOp, int iCodeTop)
|
||||
{
|
||||
iCodeTop = addToken(gotoOp, iCodeTop);
|
||||
iCodeTop = addShort(0, iCodeTop);
|
||||
return iCodeTop;
|
||||
}
|
||||
|
||||
private void resolveForwardGoto(int jumpStart, int iCodeTop) {
|
||||
private void resolveForwardGoto(int jumpStart, int iCodeTop)
|
||||
{
|
||||
if (jumpStart + 3 > iCodeTop) Context.codeBug();
|
||||
int offset = iCodeTop - jumpStart;
|
||||
// +1 to write after jump icode
|
||||
recordJumpOffset(jumpStart + 1, offset);
|
||||
}
|
||||
|
||||
private void recordJumpOffset(int pos, int offset) {
|
||||
private void recordJumpOffset(int pos, int offset)
|
||||
{
|
||||
if (offset != (short)offset) {
|
||||
throw Context.reportRuntimeError0("msg.too.big.jump");
|
||||
}
|
||||
|
@ -1071,7 +1096,8 @@ public class Interpreter
|
|||
itsData.itsICode[pos + 1] = (byte)offset;
|
||||
}
|
||||
|
||||
private int addByte(int b, int iCodeTop) {
|
||||
private int addByte(int b, int iCodeTop)
|
||||
{
|
||||
byte[] array = itsData.itsICode;
|
||||
if (iCodeTop == array.length) {
|
||||
array = increaseICodeCapasity(iCodeTop, 1);
|
||||
|
@ -1080,7 +1106,24 @@ public class Interpreter
|
|||
return iCodeTop;
|
||||
}
|
||||
|
||||
private int addShort(int s, int iCodeTop) {
|
||||
private int addToken(int token, int iCodeTop)
|
||||
{
|
||||
if (!(Token.FIRST_BYTECODE_TOKEN <= token
|
||||
&& token <= Token.LAST_BYTECODE_TOKEN))
|
||||
{
|
||||
Context.codeBug();
|
||||
}
|
||||
return addByte(token, iCodeTop);
|
||||
}
|
||||
|
||||
private int addIcode(int icode, int iCodeTop)
|
||||
{
|
||||
if (!(BASE_ICODE < icode && icode <= Icode_END)) Context.codeBug();
|
||||
return addByte(icode, iCodeTop);
|
||||
}
|
||||
|
||||
private int addShort(int s, int iCodeTop)
|
||||
{
|
||||
byte[] array = itsData.itsICode;
|
||||
if (iCodeTop + 2 > array.length) {
|
||||
array = increaseICodeCapasity(iCodeTop, 2);
|
||||
|
@ -1090,7 +1133,8 @@ public class Interpreter
|
|||
return iCodeTop + 2;
|
||||
}
|
||||
|
||||
private int addIndex(int index, int iCodeTop) {
|
||||
private int addIndex(int index, int iCodeTop)
|
||||
{
|
||||
if (index < 0) Context.codeBug();
|
||||
if (index > 0xFFFF) {
|
||||
throw Context.reportRuntimeError0("msg.too.big.index");
|
||||
|
@ -1104,7 +1148,8 @@ public class Interpreter
|
|||
return iCodeTop + 2;
|
||||
}
|
||||
|
||||
private int addInt(int i, int iCodeTop) {
|
||||
private int addInt(int i, int iCodeTop)
|
||||
{
|
||||
byte[] array = itsData.itsICode;
|
||||
if (iCodeTop + 4 > array.length) {
|
||||
array = increaseICodeCapasity(iCodeTop, 4);
|
||||
|
@ -1116,7 +1161,8 @@ public class Interpreter
|
|||
return iCodeTop + 4;
|
||||
}
|
||||
|
||||
private int addDouble(double num, int iCodeTop) {
|
||||
private int addDouble(double num, int iCodeTop)
|
||||
{
|
||||
int index = itsDoubleTableTop;
|
||||
if (index == 0) {
|
||||
itsData.itsDoubleTable = new double[64];
|
||||
|
@ -1132,7 +1178,8 @@ public class Interpreter
|
|||
return iCodeTop;
|
||||
}
|
||||
|
||||
private int addString(String str, int iCodeTop) {
|
||||
private int addString(String str, int iCodeTop)
|
||||
{
|
||||
int index = itsStrings.get(str, -1);
|
||||
if (index == -1) {
|
||||
index = itsStrings.size();
|
||||
|
@ -1219,31 +1266,30 @@ public class Interpreter
|
|||
return best;
|
||||
}
|
||||
|
||||
static PrintWriter out;
|
||||
static {
|
||||
if (Token.printICode) {
|
||||
try {
|
||||
out = new PrintWriter(new FileOutputStream("icode.txt"));
|
||||
out.close();
|
||||
}
|
||||
catch (IOException x) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String icodeToName(int icode) {
|
||||
private static String icodeToName(int icode)
|
||||
{
|
||||
if (Token.printICode) {
|
||||
if (icode <= Token.LAST_BYTECODE_TOKEN) {
|
||||
return Token.name(icode);
|
||||
} else {
|
||||
switch (icode) {
|
||||
case Icode_DUP: return "dup";
|
||||
case Icode_NAMEINC: return "nameinc";
|
||||
case Icode_PROPINC: return "propinc";
|
||||
case Icode_ELEMINC: return "eleminc";
|
||||
case Icode_VARINC: return "varinc";
|
||||
case Icode_NAMEDEC: return "namedec";
|
||||
case Icode_PROPDEC: return "propdec";
|
||||
case Icode_ELEMDEC: return "elemdec";
|
||||
case Icode_VARDEC: return "vardec";
|
||||
case Icode_SCOPE: return "scope";
|
||||
case Icode_TYPEOFNAME: return "typeofname";
|
||||
case Icode_GETPROTO: return "getproto";
|
||||
case Icode_GETPARENT: return "getparent";
|
||||
case Icode_GETSCOPEPARENT: return "getscopeparent";
|
||||
case Icode_SETPROTO: return "setproto";
|
||||
case Icode_SETPARENT: return "setparent";
|
||||
case Icode_CLOSURE: return "closure";
|
||||
case Icode_CALLSPECIAL: return "callspecial";
|
||||
case Icode_RETUNDEF: return "retundef";
|
||||
case Icode_CATCH: return "catch";
|
||||
|
@ -1260,6 +1306,18 @@ public class Interpreter
|
|||
return "";
|
||||
}
|
||||
|
||||
static PrintWriter out;
|
||||
static {
|
||||
if (Token.printICode) {
|
||||
try {
|
||||
out = new PrintWriter(new FileOutputStream("icode.txt"));
|
||||
out.close();
|
||||
}
|
||||
catch (IOException x) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void dumpICode(InterpreterData idata) {
|
||||
if (Token.printICode) {
|
||||
try {
|
||||
|
@ -1298,8 +1356,8 @@ public class Interpreter
|
|||
case Icode_RETSUB :
|
||||
case Token.ENUMINIT :
|
||||
case Token.ENUMNEXT :
|
||||
case Token.VARINC :
|
||||
case Token.VARDEC :
|
||||
case Icode_VARINC :
|
||||
case Icode_VARDEC :
|
||||
case Token.GETVAR :
|
||||
case Token.SETVAR :
|
||||
case Token.NEWTEMP :
|
||||
|
@ -1326,7 +1384,7 @@ public class Interpreter
|
|||
pc += 2;
|
||||
break;
|
||||
}
|
||||
case Token.CLOSURE : {
|
||||
case Icode_CLOSURE : {
|
||||
int i = getIndex(iCode, pc);
|
||||
InterpreterData data2 = idata.itsNestedFunctions[i];
|
||||
out.println(tname + " " + data2);
|
||||
|
@ -1361,13 +1419,13 @@ public class Interpreter
|
|||
pc += 2;
|
||||
break;
|
||||
}
|
||||
case Token.TYPEOFNAME :
|
||||
case Icode_TYPEOFNAME :
|
||||
case Token.GETBASE :
|
||||
case Token.BINDNAME :
|
||||
case Token.SETNAME :
|
||||
case Token.NAME :
|
||||
case Token.NAMEINC :
|
||||
case Token.NAMEDEC :
|
||||
case Icode_NAMEINC :
|
||||
case Icode_NAMEDEC :
|
||||
case Token.STRING : {
|
||||
String str = strings[getIndex(iCode, pc)];
|
||||
out.println(tname + " \"" + str + '"');
|
||||
|
@ -1429,10 +1487,10 @@ public class Interpreter
|
|||
case Token.GETELEM :
|
||||
case Token.SETPROP :
|
||||
case Token.GETPROP :
|
||||
case Token.PROPINC :
|
||||
case Token.PROPDEC :
|
||||
case Token.ELEMINC :
|
||||
case Token.ELEMDEC :
|
||||
case Icode_PROPINC :
|
||||
case Icode_PROPDEC :
|
||||
case Icode_ELEMINC :
|
||||
case Icode_ELEMDEC :
|
||||
case Token.BITNOT :
|
||||
case Token.BITAND :
|
||||
case Token.BITOR :
|
||||
|
@ -1483,8 +1541,8 @@ public class Interpreter
|
|||
case Icode_RETSUB :
|
||||
case Token.ENUMINIT :
|
||||
case Token.ENUMNEXT :
|
||||
case Token.VARINC :
|
||||
case Token.VARDEC :
|
||||
case Icode_VARINC :
|
||||
case Icode_VARDEC :
|
||||
case Token.GETVAR :
|
||||
case Token.SETVAR :
|
||||
case Token.NEWTEMP :
|
||||
|
@ -1503,7 +1561,7 @@ public class Interpreter
|
|||
// regexp index
|
||||
return 1 + 2;
|
||||
|
||||
case Token.CLOSURE :
|
||||
case Icode_CLOSURE :
|
||||
// index of closure master copy
|
||||
return 1 + 2;
|
||||
|
||||
|
@ -1525,13 +1583,13 @@ public class Interpreter
|
|||
// index of double number
|
||||
return 1 + 2;
|
||||
|
||||
case Token.TYPEOFNAME :
|
||||
case Icode_TYPEOFNAME :
|
||||
case Token.GETBASE :
|
||||
case Token.BINDNAME :
|
||||
case Token.SETNAME :
|
||||
case Token.NAME :
|
||||
case Token.NAMEINC :
|
||||
case Token.NAMEDEC :
|
||||
case Icode_NAMEINC :
|
||||
case Icode_NAMEDEC :
|
||||
case Token.STRING :
|
||||
// string index
|
||||
return 1 + 2;
|
||||
|
@ -2235,7 +2293,7 @@ public class Interpreter
|
|||
do_setElem(cx, stack, sDbl, stackTop, scope);
|
||||
stackTop -= 2;
|
||||
break;
|
||||
case Token.PROPINC : {
|
||||
case Icode_PROPINC : {
|
||||
String name = (String)stack[stackTop];
|
||||
--stackTop;
|
||||
Object lhs = stack[stackTop];
|
||||
|
@ -2243,7 +2301,7 @@ public class Interpreter
|
|||
stack[stackTop] = ScriptRuntime.postIncrement(lhs, name, scope);
|
||||
break;
|
||||
}
|
||||
case Token.PROPDEC : {
|
||||
case Icode_PROPDEC : {
|
||||
String name = (String)stack[stackTop];
|
||||
--stackTop;
|
||||
Object lhs = stack[stackTop];
|
||||
|
@ -2251,7 +2309,7 @@ public class Interpreter
|
|||
stack[stackTop] = ScriptRuntime.postDecrement(lhs, name, scope);
|
||||
break;
|
||||
}
|
||||
case Token.ELEMINC : {
|
||||
case Icode_ELEMINC : {
|
||||
Object rhs = stack[stackTop];
|
||||
if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);
|
||||
--stackTop;
|
||||
|
@ -2260,7 +2318,7 @@ public class Interpreter
|
|||
stack[stackTop] = ScriptRuntime.postIncrementElem(lhs, rhs, scope);
|
||||
break;
|
||||
}
|
||||
case Token.ELEMDEC : {
|
||||
case Icode_ELEMDEC : {
|
||||
Object rhs = stack[stackTop];
|
||||
if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);
|
||||
--stackTop;
|
||||
|
@ -2422,7 +2480,7 @@ public class Interpreter
|
|||
stack[stackTop] = ScriptRuntime.typeof(lhs);
|
||||
break;
|
||||
}
|
||||
case Token.TYPEOFNAME : {
|
||||
case Icode_TYPEOFNAME : {
|
||||
String name = strings[getIndex(iCode, pc + 1)];
|
||||
stack[++stackTop] = ScriptRuntime.typeofName(scope, name);
|
||||
pc += 2;
|
||||
|
@ -2456,13 +2514,13 @@ public class Interpreter
|
|||
pc += 2;
|
||||
break;
|
||||
}
|
||||
case Token.NAMEINC : {
|
||||
case Icode_NAMEINC : {
|
||||
String name = strings[getIndex(iCode, pc + 1)];
|
||||
stack[++stackTop] = ScriptRuntime.postIncrement(scope, name);
|
||||
pc += 2;
|
||||
break;
|
||||
}
|
||||
case Token.NAMEDEC : {
|
||||
case Icode_NAMEDEC : {
|
||||
String name = strings[getIndex(iCode, pc + 1)];
|
||||
stack[++stackTop] = ScriptRuntime.postDecrement(scope, name);
|
||||
pc += 2;
|
||||
|
@ -2491,7 +2549,7 @@ public class Interpreter
|
|||
}
|
||||
break;
|
||||
}
|
||||
case Token.VARINC : {
|
||||
case Icode_VARINC : {
|
||||
int slot = (iCode[++pc] & 0xFF);
|
||||
++stackTop;
|
||||
if (!useActivationVars) {
|
||||
|
@ -2507,7 +2565,7 @@ public class Interpreter
|
|||
}
|
||||
break;
|
||||
}
|
||||
case Token.VARDEC : {
|
||||
case Icode_VARDEC : {
|
||||
int slot = (iCode[++pc] & 0xFF);
|
||||
++stackTop;
|
||||
if (!useActivationVars) {
|
||||
|
@ -2620,7 +2678,7 @@ public class Interpreter
|
|||
case Icode_SCOPE :
|
||||
stack[++stackTop] = scope;
|
||||
break;
|
||||
case Token.CLOSURE : {
|
||||
case Icode_CLOSURE : {
|
||||
int i = getIndex(iCode, pc + 1);
|
||||
InterpreterData closureData = idata.itsNestedFunctions[i];
|
||||
stack[++stackTop] = createFunction(cx, scope, closureData,
|
||||
|
@ -2705,7 +2763,8 @@ public class Interpreter
|
|||
return result;
|
||||
}
|
||||
|
||||
private static Object doubleWrap(double x) {
|
||||
private static Object doubleWrap(double x)
|
||||
{
|
||||
return new Double(x);
|
||||
}
|
||||
|
||||
|
@ -2812,7 +2871,8 @@ public class Interpreter
|
|||
}
|
||||
|
||||
// Optimized version of ScriptRuntime.eq if x is a Number
|
||||
private static boolean do_eq(double x, Object y) {
|
||||
private static boolean do_eq(double x, Object y)
|
||||
{
|
||||
for (;;) {
|
||||
if (y instanceof Number) {
|
||||
return x == ((Number) y).doubleValue();
|
||||
|
|
|
@ -72,6 +72,8 @@ public class Token
|
|||
EOL = 1, // end of line
|
||||
|
||||
// Interpreter reuses the following as bytecodes
|
||||
FIRST_BYTECODE_TOKEN = 2,
|
||||
|
||||
POPV = 2,
|
||||
ENTERWITH = 3,
|
||||
LEAVEWITH = 4,
|
||||
|
@ -102,94 +104,84 @@ public class Token
|
|||
NEW = 29,
|
||||
DELPROP = 30,
|
||||
TYPEOF = 31,
|
||||
NAMEINC = 32,
|
||||
PROPINC = 33,
|
||||
ELEMINC = 34,
|
||||
NAMEDEC = 35,
|
||||
PROPDEC = 36,
|
||||
ELEMDEC = 37,
|
||||
GETPROP = 38,
|
||||
SETPROP = 39,
|
||||
GETELEM = 40,
|
||||
SETELEM = 41,
|
||||
CALL = 42,
|
||||
NAME = 43,
|
||||
NUMBER = 44,
|
||||
STRING = 45,
|
||||
ZERO = 46,
|
||||
ONE = 47,
|
||||
NULL = 48,
|
||||
THIS = 49,
|
||||
FALSE = 50,
|
||||
TRUE = 51,
|
||||
SHEQ = 52, // shallow equality (===)
|
||||
SHNE = 53, // shallow inequality (!==)
|
||||
CLOSURE = 54,
|
||||
REGEXP = 55,
|
||||
POP = 56,
|
||||
POS = 57,
|
||||
VARINC = 58,
|
||||
VARDEC = 59,
|
||||
BINDNAME = 60,
|
||||
THROW = 61,
|
||||
IN = 62,
|
||||
INSTANCEOF = 63,
|
||||
GETTHIS = 64,
|
||||
NEWTEMP = 65,
|
||||
USETEMP = 66,
|
||||
GETBASE = 67,
|
||||
GETVAR = 68,
|
||||
SETVAR = 69,
|
||||
UNDEFINED = 70,
|
||||
TRY = 71,
|
||||
NEWSCOPE = 72,
|
||||
TYPEOFNAME = 73,
|
||||
ENUMINIT = 74,
|
||||
ENUMNEXT = 75,
|
||||
THISFN = 76,
|
||||
GETPROP = 32,
|
||||
SETPROP = 33,
|
||||
GETELEM = 34,
|
||||
SETELEM = 35,
|
||||
CALL = 36,
|
||||
NAME = 37,
|
||||
NUMBER = 38,
|
||||
STRING = 39,
|
||||
ZERO = 40,
|
||||
ONE = 41,
|
||||
NULL = 42,
|
||||
THIS = 43,
|
||||
FALSE = 44,
|
||||
TRUE = 45,
|
||||
SHEQ = 46, // shallow equality (===)
|
||||
SHNE = 47, // shallow inequality (!==)
|
||||
REGEXP = 48,
|
||||
POP = 49,
|
||||
POS = 50,
|
||||
BINDNAME = 51,
|
||||
THROW = 52,
|
||||
IN = 53,
|
||||
INSTANCEOF = 54,
|
||||
GETTHIS = 55,
|
||||
NEWTEMP = 56,
|
||||
USETEMP = 57,
|
||||
GETBASE = 58,
|
||||
GETVAR = 59,
|
||||
SETVAR = 60,
|
||||
UNDEFINED = 61,
|
||||
NEWSCOPE = 62,
|
||||
ENUMINIT = 63,
|
||||
ENUMNEXT = 64,
|
||||
THISFN = 65,
|
||||
|
||||
LAST_BYTECODE_TOKEN = 76,
|
||||
LAST_BYTECODE_TOKEN = 65,
|
||||
// End of interpreter bytecodes
|
||||
|
||||
SEMI = 77, // semicolon
|
||||
LB = 78, // left and right brackets
|
||||
RB = 79,
|
||||
LC = 80, // left and right curlies (braces)
|
||||
RC = 81,
|
||||
LP = 82, // left and right parentheses
|
||||
RP = 83,
|
||||
COMMA = 84, // comma operator
|
||||
ASSIGN = 85, // assignment ops (= += -= etc.)
|
||||
HOOK = 86, // conditional (?:)
|
||||
COLON = 87,
|
||||
OR = 88, // logical or (||)
|
||||
AND = 89, // logical and (&&)
|
||||
EQOP = 90, // equality ops (== !=)
|
||||
RELOP = 91, // relational ops (< <= > >=)
|
||||
SHOP = 92, // shift ops (<< >> >>>)
|
||||
UNARYOP = 93, // unary prefix operator
|
||||
INC = 94, // increment/decrement (++ --)
|
||||
DEC = 95,
|
||||
DOT = 96, // member operator (.)
|
||||
PRIMARY = 97, // true, false, null, this
|
||||
FUNCTION = 98, // function keyword
|
||||
EXPORT = 99, // export keyword
|
||||
IMPORT = 100, // import keyword
|
||||
IF = 101, // if keyword
|
||||
ELSE = 102, // else keyword
|
||||
SWITCH = 103, // switch keyword
|
||||
CASE = 104, // case keyword
|
||||
DEFAULT = 105, // default keyword
|
||||
WHILE = 106, // while keyword
|
||||
DO = 107, // do keyword
|
||||
FOR = 108, // for keyword
|
||||
BREAK = 109, // break keyword
|
||||
CONTINUE = 110, // continue keyword
|
||||
VAR = 111, // var keyword
|
||||
WITH = 112, // with keyword
|
||||
CATCH = 113, // catch keyword
|
||||
FINALLY = 114, // finally keyword
|
||||
RESERVED = 115, // reserved keywords
|
||||
TRY = 66,
|
||||
SEMI = 67, // semicolon
|
||||
LB = 68, // left and right brackets
|
||||
RB = 69,
|
||||
LC = 70, // left and right curlies (braces)
|
||||
RC = 71,
|
||||
LP = 72, // left and right parentheses
|
||||
RP = 73,
|
||||
COMMA = 74, // comma operator
|
||||
ASSIGN = 75, // assignment ops (= += -= etc.)
|
||||
HOOK = 76, // conditional (?:)
|
||||
COLON = 77,
|
||||
OR = 78, // logical or (||)
|
||||
AND = 79, // logical and (&&)
|
||||
EQOP = 80, // equality ops (== !=)
|
||||
RELOP = 81, // relational ops (< <= > >=)
|
||||
SHOP = 82, // shift ops (<< >> >>>)
|
||||
UNARYOP = 83, // unary prefix operator
|
||||
INC = 84, // increment/decrement (++ --)
|
||||
DEC = 85,
|
||||
DOT = 86, // member operator (.)
|
||||
PRIMARY = 87, // true, false, null, this
|
||||
FUNCTION = 88, // function keyword
|
||||
EXPORT = 89, // export keyword
|
||||
IMPORT = 90, // import keyword
|
||||
IF = 91, // if keyword
|
||||
ELSE = 92, // else keyword
|
||||
SWITCH = 93, // switch keyword
|
||||
CASE = 94, // case keyword
|
||||
DEFAULT = 95, // default keyword
|
||||
WHILE = 96, // while keyword
|
||||
DO = 97, // do keyword
|
||||
FOR = 98, // for keyword
|
||||
BREAK = 99, // break keyword
|
||||
CONTINUE = 100, // continue keyword
|
||||
VAR = 101, // var keyword
|
||||
WITH = 102, // with keyword
|
||||
CATCH = 103, // catch keyword
|
||||
FINALLY = 104, // finally keyword
|
||||
RESERVED = 105, // reserved keywords
|
||||
|
||||
/** Added by Mike - these are JSOPs in the jsref, but I
|
||||
* don't have them yet in the java implementation...
|
||||
|
@ -198,37 +190,37 @@ public class Token
|
|||
* Most of these go in the 'op' field when returning
|
||||
* more general token types, eg. 'DIV' as the op of 'ASSIGN'.
|
||||
*/
|
||||
NOP = 116, // NOP
|
||||
NOT = 117, // etc.
|
||||
PRE = 118, // for INC, DEC nodes.
|
||||
POST = 119,
|
||||
NOP = 106, // NOP
|
||||
NOT = 107, // etc.
|
||||
PRE = 108, // for INC, DEC nodes.
|
||||
POST = 109,
|
||||
|
||||
/**
|
||||
* For JSOPs associated with keywords...
|
||||
* eg. op = THIS; token = PRIMARY
|
||||
*/
|
||||
|
||||
VOID = 120,
|
||||
VOID = 110,
|
||||
|
||||
/* types used for the parse tree - these never get returned
|
||||
* by the scanner.
|
||||
*/
|
||||
BLOCK = 121, // statement block
|
||||
ARRAYLIT = 122, // array literal
|
||||
OBJLIT = 123, // object literal
|
||||
LABEL = 124, // label
|
||||
TARGET = 125,
|
||||
LOOP = 126,
|
||||
ENUMDONE = 127,
|
||||
EXPRSTMT = 128,
|
||||
PARENT = 129,
|
||||
CONVERT = 130,
|
||||
JSR = 131,
|
||||
NEWLOCAL = 132,
|
||||
USELOCAL = 133,
|
||||
SCRIPT = 134, // top-level node for entire script
|
||||
BLOCK = 111, // statement block
|
||||
ARRAYLIT = 112, // array literal
|
||||
OBJLIT = 113, // object literal
|
||||
LABEL = 114, // label
|
||||
TARGET = 115,
|
||||
LOOP = 116,
|
||||
ENUMDONE = 117,
|
||||
EXPRSTMT = 118,
|
||||
PARENT = 119,
|
||||
CONVERT = 120,
|
||||
JSR = 121,
|
||||
NEWLOCAL = 122,
|
||||
USELOCAL = 123,
|
||||
SCRIPT = 124, // top-level node for entire script
|
||||
|
||||
LAST_TOKEN = 134;
|
||||
LAST_TOKEN = 124;
|
||||
|
||||
public static String name(int token)
|
||||
{
|
||||
|
@ -267,12 +259,6 @@ public class Token
|
|||
case NEW: return "new";
|
||||
case DELPROP: return "delprop";
|
||||
case TYPEOF: return "typeof";
|
||||
case NAMEINC: return "nameinc";
|
||||
case PROPINC: return "propinc";
|
||||
case ELEMINC: return "eleminc";
|
||||
case NAMEDEC: return "namedec";
|
||||
case PROPDEC: return "propdec";
|
||||
case ELEMDEC: return "elemdec";
|
||||
case GETPROP: return "getprop";
|
||||
case SETPROP: return "setprop";
|
||||
case GETELEM: return "getelem";
|
||||
|
@ -289,12 +275,9 @@ public class Token
|
|||
case TRUE: return "true";
|
||||
case SHEQ: return "sheq";
|
||||
case SHNE: return "shne";
|
||||
case CLOSURE: return "closure";
|
||||
case REGEXP: return "object";
|
||||
case POP: return "pop";
|
||||
case POS: return "pos";
|
||||
case VARINC: return "varinc";
|
||||
case VARDEC: return "vardec";
|
||||
case BINDNAME: return "bindname";
|
||||
case THROW: return "throw";
|
||||
case IN: return "in";
|
||||
|
@ -308,7 +291,6 @@ public class Token
|
|||
case UNDEFINED: return "undefined";
|
||||
case TRY: return "try";
|
||||
case NEWSCOPE: return "newscope";
|
||||
case TYPEOFNAME: return "typeofname";
|
||||
case ENUMINIT: return "enuminit";
|
||||
case ENUMNEXT: return "enumnext";
|
||||
case THISFN: return "thisfn";
|
||||
|
|
Загрузка…
Ссылка в новой задаче