From 8a7aea78a4829021691d0769b2f7d7a33f826bdc Mon Sep 17 00:00:00 2001 From: "igor%mir2.org" Date: Wed, 6 Aug 2003 11:37:14 +0000 Subject: [PATCH] 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. --- .../org/mozilla/javascript/Interpreter.java | 362 +++++++++--------- .../src/org/mozilla/javascript/Token.java | 168 ++++---- 2 files changed, 256 insertions(+), 274 deletions(-) diff --git a/js/rhino/src/org/mozilla/javascript/Interpreter.java b/js/rhino/src/org/mozilla/javascript/Interpreter.java index 86545288ddc..874af833aa4 100644 --- a/js/rhino/src/org/mozilla/javascript/Interpreter.java +++ b/js/rhino/src/org/mozilla/javascript/Interpreter.java @@ -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]; diff --git a/js/rhino/src/org/mozilla/javascript/Token.java b/js/rhino/src/org/mozilla/javascript/Token.java index 573e55d4b1e..a183599f78a 100644 --- a/js/rhino/src/org/mozilla/javascript/Token.java +++ b/js/rhino/src/org/mozilla/javascript/Token.java @@ -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";