1. Add Token.NOT as a byte code instead of generating if code to push false/true as "!" is frequent enough and interpreter does not have optimized mode to remove most of its usage in logical context.

2. When dumping icode, print it to System.out instead of icode.txt file for more convenient development.
This commit is contained in:
igor%mir2.org 2003-08-06 11:37:14 +00:00
Родитель 0fa5242f20
Коммит 8a7aea78a4
2 изменённых файлов: 256 добавлений и 274 удалений

Просмотреть файл

@ -290,14 +290,7 @@ public class Interpreter
private void badTree(Node node)
{
try {
out = new PrintWriter(new FileOutputStream("icode.txt", true));
out.println("Un-handled node : " + node.toString());
out.close();
}
catch (IOException x) {}
throw new RuntimeException("Un-handled node : "
+ node.toString());
throw new RuntimeException("Un-handled node: "+node.toString());
}
private int generateICode(Node node, int iCodeTop)
@ -624,19 +617,9 @@ public class Interpreter
iCodeTop = addToken(Token.POP, iCodeTop);
iCodeTop = addToken(Token.UNDEFINED, iCodeTop);
break;
case Token.NOT : {
int trueJumpStart = iCodeTop;
iCodeTop = addForwardGoto(Token.IFEQ,
iCodeTop);
iCodeTop = addToken(Token.TRUE, iCodeTop);
int beyondJumpStart = iCodeTop;
iCodeTop = addForwardGoto(Token.GOTO,
iCodeTop);
resolveForwardGoto(trueJumpStart, iCodeTop);
iCodeTop = addToken(Token.FALSE, iCodeTop);
resolveForwardGoto(beyondJumpStart, iCodeTop);
case Token.NOT :
iCodeTop = addToken(Token.NOT, iCodeTop);
break;
}
case Token.BITNOT :
iCodeTop = addToken(Token.BITNOT, iCodeTop);
break;
@ -825,12 +808,17 @@ public class Interpreter
case Token.POP :
case Token.POPV :
iCodeTop = updateLineNumber(node, iCodeTop);
case Token.ENTERWITH :
iCodeTop = generateICode(child, iCodeTop);
iCodeTop = addToken(type, iCodeTop);
itsStackDepth--;
break;
case Token.ENTERWITH :
iCodeTop = generateICode(child, iCodeTop);
iCodeTop = addToken(Token.ENTERWITH, iCodeTop);
itsStackDepth--;
break;
case Token.GETTHIS :
iCodeTop = generateICode(child, iCodeTop);
iCodeTop = addToken(Token.GETTHIS, iCodeTop);
@ -1306,164 +1294,147 @@ public class Interpreter
return "";
}
static PrintWriter out;
static {
private static void dumpICode(InterpreterData idata)
{
if (Token.printICode) {
try {
out = new PrintWriter(new FileOutputStream("icode.txt"));
out.close();
}
catch (IOException x) {
}
}
}
int iCodeLength = idata.itsICodeTop;
byte iCode[] = idata.itsICode;
String[] strings = idata.itsStringTable;
PrintStream out = System.out;
out.println("ICode dump, for " + idata.itsName
+ ", length = " + iCodeLength);
out.println("MaxStack = " + idata.itsMaxStack);
private static void dumpICode(InterpreterData idata) {
if (Token.printICode) {
try {
int iCodeLength = idata.itsICodeTop;
byte iCode[] = idata.itsICode;
String[] strings = idata.itsStringTable;
for (int pc = 0; pc < iCodeLength; ) {
out.flush();
out.print(" [" + pc + "] ");
int token = iCode[pc] & 0xff;
String tname = icodeToName(token);
int old_pc = pc;
++pc;
int icodeLength = icodeTokenLength(token);
switch (token) {
default:
if (icodeLength != 1) Context.codeBug();
out.println(tname);
break;
out = new PrintWriter(new FileOutputStream("icode.txt", true));
out.println("ICode dump, for " + idata.itsName
+ ", length = " + iCodeLength);
out.println("MaxStack = " + idata.itsMaxStack);
for (int pc = 0; pc < iCodeLength; ) {
out.flush();
out.print(" [" + pc + "] ");
int token = iCode[pc] & 0xff;
String tname = icodeToName(token);
int old_pc = pc;
++pc;
int icodeLength = icodeTokenLength(token);
switch (token) {
default:
if (icodeLength != 1) Context.codeBug();
out.println(tname);
break;
case Icode_GOSUB :
case Token.GOTO :
case Token.IFEQ :
case Token.IFNE : {
int newPC = getTarget(iCode, pc);
out.println(tname + " " + newPC);
pc += 2;
break;
}
case Icode_RETSUB :
case Token.ENUMINIT :
case Token.ENUMNEXT :
case Icode_VARINC :
case Icode_VARDEC :
case Token.GETVAR :
case Token.SETVAR :
case Token.NEWTEMP :
case Token.USETEMP : {
int slot = (iCode[pc] & 0xFF);
out.println(tname + " " + slot);
pc++;
break;
}
case Icode_CALLSPECIAL : {
int callType = iCode[pc] & 0xFF;
boolean isNew = (iCode[pc + 1] != 0);
int line = getShort(iCode, pc+2);
int count = getIndex(iCode, pc + 4);
out.println(tname + " " + callType + " " + isNew
+ " " + count + " " + line);
pc += 8;
break;
}
case Token.REGEXP : {
int i = getIndex(iCode, pc);
Object regexp = idata.itsRegExpLiterals[i];
out.println(tname + " " + regexp);
pc += 2;
break;
}
case Icode_CLOSURE : {
int i = getIndex(iCode, pc);
InterpreterData data2 = idata.itsNestedFunctions[i];
out.println(tname + " " + data2);
pc += 2;
break;
}
case Token.NEW :
case Token.CALL : {
int count = getIndex(iCode, pc + 2);
String name = strings[getIndex(iCode, pc)];
out.println(tname + " " + count + " \""
+ name + '"');
pc += 4;
break;
}
case Icode_SHORTNUMBER : {
int value = getShort(iCode, pc);
out.println(tname + " " + value);
pc += 2;
break;
}
case Icode_INTNUMBER : {
int value = getInt(iCode, pc);
out.println(tname + " " + value);
pc += 4;
break;
}
case Token.NUMBER : {
int index = getIndex(iCode, pc);
double value = idata.itsDoubleTable[index];
out.println(tname + " " + value);
pc += 2;
break;
}
case Icode_TYPEOFNAME :
case Token.GETBASE :
case Token.BINDNAME :
case Token.SETNAME :
case Token.NAME :
case Icode_NAMEINC :
case Icode_NAMEDEC :
case Token.STRING : {
String str = strings[getIndex(iCode, pc)];
out.println(tname + " \"" + str + '"');
pc += 2;
break;
}
case Icode_LINE : {
int line = getShort(iCode, pc);
out.println(tname + " : " + line);
pc += 2;
break;
}
case Icode_GOSUB :
case Token.GOTO :
case Token.IFEQ :
case Token.IFNE : {
int newPC = getTarget(iCode, pc);
out.println(tname + " " + newPC);
pc += 2;
break;
}
if (old_pc + icodeLength != pc) Context.codeBug();
}
int[] table = idata.itsExceptionTable;
if (table != null) {
out.println("Exception handlers: "
+table.length / EXCEPTION_SLOT_SIZE);
for (int i = 0; i != table.length;
i += EXCEPTION_SLOT_SIZE)
{
int tryStart = table[i + EXCEPTION_TRY_START_SLOT];
int tryEnd = table[i + EXCEPTION_TRY_END_SLOT];
int catchStart = table[i + EXCEPTION_CATCH_SLOT];
int finallyStart = table[i + EXCEPTION_FINALLY_SLOT];
int withDepth = table[i + EXCEPTION_WITH_DEPTH_SLOT];
out.println(" "+tryStart+"\t "+tryEnd+"\t "
+catchStart+"\t "+finallyStart
+"\t "+withDepth);
case Icode_RETSUB :
case Token.ENUMINIT :
case Token.ENUMNEXT :
case Icode_VARINC :
case Icode_VARDEC :
case Token.GETVAR :
case Token.SETVAR :
case Token.NEWTEMP :
case Token.USETEMP : {
int slot = (iCode[pc] & 0xFF);
out.println(tname + " " + slot);
pc++;
break;
}
case Icode_CALLSPECIAL : {
int callType = iCode[pc] & 0xFF;
boolean isNew = (iCode[pc + 1] != 0);
int line = getShort(iCode, pc+2);
int count = getIndex(iCode, pc + 4);
out.println(tname+" "+callType+" "+isNew
+" "+count+" "+line);
pc += 8;
break;
}
case Token.REGEXP : {
int i = getIndex(iCode, pc);
Object regexp = idata.itsRegExpLiterals[i];
out.println(tname + " " + regexp);
pc += 2;
break;
}
case Icode_CLOSURE : {
int i = getIndex(iCode, pc);
InterpreterData data2 = idata.itsNestedFunctions[i];
out.println(tname + " " + data2);
pc += 2;
break;
}
case Token.NEW :
case Token.CALL : {
int count = getIndex(iCode, pc + 2);
String name = strings[getIndex(iCode, pc)];
out.println(tname+' '+count+" \""+name+'"');
pc += 4;
break;
}
case Icode_SHORTNUMBER : {
int value = getShort(iCode, pc);
out.println(tname + " " + value);
pc += 2;
break;
}
case Icode_INTNUMBER : {
int value = getInt(iCode, pc);
out.println(tname + " " + value);
pc += 4;
break;
}
case Token.NUMBER : {
int index = getIndex(iCode, pc);
double value = idata.itsDoubleTable[index];
out.println(tname + " " + value);
pc += 2;
break;
}
case Icode_TYPEOFNAME :
case Token.GETBASE :
case Token.BINDNAME :
case Token.SETNAME :
case Token.NAME :
case Icode_NAMEINC :
case Icode_NAMEDEC :
case Token.STRING : {
String str = strings[getIndex(iCode, pc)];
out.println(tname + " \"" + str + '"');
pc += 2;
break;
}
case Icode_LINE : {
int line = getShort(iCode, pc);
out.println(tname + " : " + line);
pc += 2;
break;
}
}
out.close();
if (old_pc + icodeLength != pc) Context.codeBug();
}
catch (IOException x) {}
int[] table = idata.itsExceptionTable;
if (table != null) {
out.println("Exception handlers: "
+table.length / EXCEPTION_SLOT_SIZE);
for (int i = 0; i != table.length;
i += EXCEPTION_SLOT_SIZE)
{
int tryStart = table[i + EXCEPTION_TRY_START_SLOT];
int tryEnd = table[i + EXCEPTION_TRY_END_SLOT];
int catchStart = table[i + EXCEPTION_CATCH_SLOT];
int finallyStart = table[i + EXCEPTION_FINALLY_SLOT];
int withDepth = table[i + EXCEPTION_WITH_DEPTH_SLOT];
out.println(" "+tryStart+"\t "+tryEnd+"\t "
+catchStart+"\t "+finallyStart
+"\t "+withDepth);
}
}
out.flush();
}
}
@ -1498,8 +1469,9 @@ public class Interpreter
case Token.LSH :
case Token.RSH :
case Token.URSH :
case Token.NEG :
case Token.NOT :
case Token.POS :
case Token.NEG :
case Token.SUB :
case Token.MUL :
case Token.DIV :
@ -2014,16 +1986,9 @@ public class Interpreter
break;
}
case Token.IFNE : {
Object val = stack[stackTop];
boolean valBln;
if (val != DBL_MRK) {
valBln = !ScriptRuntime.toBoolean(val);
} else {
double valDbl = sDbl[stackTop];
valBln = !(valDbl == valDbl && valDbl != 0.0);
}
boolean valBln = stack_boolean(stack, sDbl, stackTop);
--stackTop;
if (valBln) {
if (!valBln) {
if (instructionThreshold != 0) {
instructionCount += pc + 3 - pcPrevBranch;
if (instructionCount > instructionThreshold) {
@ -2038,14 +2003,7 @@ public class Interpreter
break;
}
case Token.IFEQ : {
boolean valBln;
Object val = stack[stackTop];
if (val != DBL_MRK) {
valBln = ScriptRuntime.toBoolean(val);
} else {
double valDbl = sDbl[stackTop];
valBln = (valDbl == valDbl && valDbl != 0.0);
}
boolean valBln = stack_boolean(stack, sDbl, stackTop);
--stackTop;
if (valBln) {
if (instructionThreshold != 0) {
@ -2234,6 +2192,11 @@ public class Interpreter
sDbl[stackTop] = lDbl % rDbl;
break;
}
case Token.NOT : {
stack[stackTop] = stack_boolean(stack, sDbl, stackTop)
? Boolean.FALSE : Boolean.TRUE;
break;
}
case Token.BINDNAME : {
String name = strings[getIndex(iCode, pc + 1)];
stack[++stackTop] = ScriptRuntime.bind(scope, name);
@ -2782,6 +2745,25 @@ public class Interpreter
return (x != DBL_MRK) ? ScriptRuntime.toNumber(x) : stackDbl[i];
}
private static boolean stack_boolean(Object[] stack, double[] stackDbl,
int i)
{
Object x = stack[i];
if (x == DBL_MRK) {
double d = stackDbl[i];
return d == d && d != 0.0;
} else if (x instanceof Boolean) {
return ((Boolean)x).booleanValue();
} else if (x == null || x == Undefined.instance) {
return false;
} else if (x instanceof Number) {
double d = ((Number)x).doubleValue();
return (d == d && d != 0.0);
} else {
return ScriptRuntime.toBoolean(x);
}
}
private static void do_add(Object[] stack, double[] stackDbl, int stackTop)
{
Object rhs = stack[stackTop + 1];

Просмотреть файл

@ -99,89 +99,90 @@ public class Token
MUL = 24,
DIV = 25,
MOD = 26,
BITNOT = 27,
NEG = 28,
NEW = 29,
DELPROP = 30,
TYPEOF = 31,
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,
NOT = 27,
BITNOT = 28,
POS = 29,
NEG = 30,
NEW = 31,
DELPROP = 32,
TYPEOF = 33,
GETPROP = 34,
SETPROP = 35,
GETELEM = 36,
SETELEM = 37,
CALL = 38,
NAME = 39,
NUMBER = 40,
STRING = 41,
ZERO = 42,
ONE = 43,
NULL = 44,
THIS = 45,
FALSE = 46,
TRUE = 47,
SHEQ = 48, // shallow equality (===)
SHNE = 49, // shallow inequality (!==)
REGEXP = 50,
POP = 51,
BINDNAME = 52,
THROW = 53,
IN = 54,
INSTANCEOF = 55,
GETTHIS = 56,
NEWTEMP = 57,
USETEMP = 58,
GETBASE = 59,
GETVAR = 60,
SETVAR = 61,
UNDEFINED = 62,
NEWSCOPE = 63,
ENUMINIT = 64,
ENUMNEXT = 65,
THISFN = 66,
LAST_BYTECODE_TOKEN = 65,
LAST_BYTECODE_TOKEN = 66,
// End of interpreter bytecodes
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
TRY = 67,
SEMI = 68, // semicolon
LB = 69, // left and right brackets
RB = 70,
LC = 71, // left and right curlies (braces)
RC = 72,
LP = 73, // left and right parentheses
RP = 74,
COMMA = 75, // comma operator
ASSIGN = 76, // assignment ops (= += -= etc.)
HOOK = 77, // conditional (?:)
COLON = 78,
OR = 79, // logical or (||)
AND = 80, // logical and (&&)
EQOP = 81, // equality ops (== !=)
RELOP = 82, // relational ops (< <= > >=)
SHOP = 83, // shift ops (<< >> >>>)
UNARYOP = 84, // unary prefix operator
INC = 85, // increment/decrement (++ --)
DEC = 86,
DOT = 87, // member operator (.)
PRIMARY = 88, // true, false, null, this
FUNCTION = 89, // function keyword
EXPORT = 90, // export keyword
IMPORT = 91, // import keyword
IF = 92, // if keyword
ELSE = 93, // else keyword
SWITCH = 94, // switch keyword
CASE = 95, // case keyword
DEFAULT = 96, // default keyword
WHILE = 97, // while keyword
DO = 98, // do keyword
FOR = 99, // for keyword
BREAK = 100, // break keyword
CONTINUE = 101, // continue keyword
VAR = 102, // var keyword
WITH = 103, // with keyword
CATCH = 104, // catch keyword
FINALLY = 105, // finally keyword
RESERVED = 106, // reserved keywords
/** Added by Mike - these are JSOPs in the jsref, but I
* don't have them yet in the java implementation...
@ -190,8 +191,7 @@ 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 = 106, // NOP
NOT = 107, // etc.
NOP = 107, // NOP
PRE = 108, // for INC, DEC nodes.
POST = 109,
@ -254,7 +254,9 @@ public class Token
case MUL: return "mul";
case DIV: return "div";
case MOD: return "mod";
case NOT: return "not";
case BITNOT: return "bitnot";
case POS: return "pos";
case NEG: return "neg";
case NEW: return "new";
case DELPROP: return "delprop";
@ -277,7 +279,6 @@ public class Token
case SHNE: return "shne";
case REGEXP: return "object";
case POP: return "pop";
case POS: return "pos";
case BINDNAME: return "bindname";
case THROW: return "throw";
case IN: return "in";
@ -334,7 +335,6 @@ public class Token
case FINALLY: return "finally";
case RESERVED: return "reserved";
case NOP: return "nop";
case NOT: return "not";
case PRE: return "pre";
case POST: return "post";
case VOID: return "void";