diff --git a/js/rhino/src/org/mozilla/javascript/IRFactory.java b/js/rhino/src/org/mozilla/javascript/IRFactory.java index 908094adf70a..64178037b475 100644 --- a/js/rhino/src/org/mozilla/javascript/IRFactory.java +++ b/js/rhino/src/org/mozilla/javascript/IRFactory.java @@ -93,12 +93,18 @@ final class IRFactory Node createExprStatement(Node expr, int lineno) { - return new Node(Token.EXPRSTMT, expr, lineno); + int type; + if (parser.insideFunction()) { + type = Token.EXPR_VOID; + } else { + type = Token.EXPR_RESULT; + } + return new Node(type, expr, lineno); } Node createExprStatementNoReturn(Node expr, int lineno) { - return new Node(Token.POP, expr, lineno); + return new Node(Token.EXPR_VOID, expr, lineno); } /** @@ -245,7 +251,7 @@ final class IRFactory // function to initialize a local variable of the // function's name to the function value. fnNode.addVar(name); - Node setFn = new Node(Token.POP, + Node setFn = new Node(Token.EXPR_VOID, new Node(Token.SETVAR, Node.newString(name), new Node(Token.THISFN))); statements.addChildrenToFront(setFn); @@ -333,14 +339,14 @@ final class IRFactory if (loopType == LOOP_FOR) { if (init.getType() != Token.EMPTY) { if (init.getType() != Token.VAR) { - init = new Node(Token.POP, init); + init = new Node(Token.EXPR_VOID, init); } result.addChildToFront(init); } Node.Target incrTarget = new Node.Target(); result.addChildAfter(incrTarget, body); if (incr.getType() != Token.EMPTY) { - incr = createUnary(Token.POP, incr); + incr = new Node(Token.EXPR_VOID, incr); result.addChildAfter(incr, incrTarget); } continueTarget = incrTarget; @@ -400,7 +406,7 @@ final class IRFactory Node newBody = new Node(Token.BLOCK); Node assign = createAssignment(lvalue, id); - newBody.addChildToBack(new Node(Token.POP, assign)); + newBody.addChildToBack(new Node(Token.EXPR_VOID, assign)); newBody.addChildToBack(body); Node loop = createWhile(cond, newBody, lineno); diff --git a/js/rhino/src/org/mozilla/javascript/Interpreter.java b/js/rhino/src/org/mozilla/javascript/Interpreter.java index 1ed39bd7ff93..560b88c0dccb 100644 --- a/js/rhino/src/org/mozilla/javascript/Interpreter.java +++ b/js/rhino/src/org/mozilla/javascript/Interpreter.java @@ -131,8 +131,11 @@ public class Interpreter Icode_UNDEF = -45, + Icode_POP = -46, + Icode_POP_RESULT = -47, + // Last icode - MIN_ICODE = -45; + MIN_ICODE = -47; static { // Checks for byte code consistencies, good compiler can eliminate them @@ -149,6 +152,74 @@ public class Interpreter } } + private static String bytecodeName(int bytecode) + { + if (!validBytecode(bytecode)) { + throw new IllegalArgumentException(String.valueOf(bytecode)); + } + + if (!Token.printICode) { + return String.valueOf(bytecode); + } + + if (validTokenCode(bytecode)) { + return Token.name(bytecode); + } + + switch (bytecode) { + case Icode_DUP: return "DUP"; + case Icode_DUP2: return "DUP2"; + case Icode_SWAP: return "SWAP"; + case Icode_IFEQ_POP: return "IFEQ_POP"; + case Icode_VAR_INC_DEC: return "VAR_INC_DEC"; + case Icode_NAME_INC_DEC: return "NAME_INC_DEC"; + case Icode_PROP_INC_DEC: return "PROP_INC_DEC"; + case Icode_ELEM_INC_DEC: return "ELEM_INC_DEC"; + case Icode_REF_INC_DEC: return "REF_INC_DEC"; + case Icode_SCOPE: return "SCOPE"; + case Icode_TYPEOFNAME: return "TYPEOFNAME"; + case Icode_NAME_FAST_THIS: return "NAME_FAST_THIS"; + case Icode_NAME_SLOW_THIS: return "NAME_SLOW_THIS"; + case Icode_PUSH_PARENT: return "PUSH_PARENT"; + case Icode_CLOSURE: return "CLOSURE"; + case Icode_CALLSPECIAL: return "CALLSPECIAL"; + case Icode_RETUNDEF: return "RETUNDEF"; + case Icode_CATCH: return "CATCH"; + case Icode_GOSUB: return "GOSUB"; + case Icode_RETSUB: return "RETSUB"; + case Icode_LINE: return "LINE"; + case Icode_SHORTNUMBER: return "SHORTNUMBER"; + case Icode_INTNUMBER: return "INTNUMBER"; + case Icode_LITERAL_NEW: return "LITERAL_NEW"; + case Icode_LITERAL_SET: return "LITERAL_SET"; + case Icode_SPARE_ARRAYLIT: return "SPARE_ARRAYLIT"; + case Icode_REG_IND_C0: return "REG_IND_C0"; + case Icode_REG_IND_C1: return "REG_IND_C1"; + case Icode_REG_IND_C2: return "REG_IND_C2"; + case Icode_REG_IND_C3: return "REG_IND_C3"; + case Icode_REG_IND_C4: return "REG_IND_C4"; + case Icode_REG_IND_C5: return "REG_IND_C5"; + case Icode_REG_IND1: return "LOAD_IND1"; + case Icode_REG_IND2: return "LOAD_IND2"; + case Icode_REG_IND4: return "LOAD_IND4"; + case Icode_REG_STR_C0: return "REG_STR_C0"; + case Icode_REG_STR_C1: return "REG_STR_C1"; + case Icode_REG_STR_C2: return "REG_STR_C2"; + case Icode_REG_STR_C3: return "REG_STR_C3"; + case Icode_REG_STR1: return "LOAD_STR1"; + case Icode_REG_STR2: return "LOAD_STR2"; + case Icode_REG_STR4: return "LOAD_STR4"; + case Icode_GETVAR1: return "GETVAR1"; + case Icode_SETVAR1: return "SETVAR1"; + case Icode_UNDEF: return "UNDEF"; + case Icode_POP: return "POP"; + case Icode_POP_RESULT: return "POP_RESULT"; + } + + // icode without name + throw new IllegalStateException(String.valueOf(bytecode)); + } + private static boolean validIcode(int icode) { return MIN_ICODE <= icode && icode <= -1; @@ -263,9 +334,9 @@ public class Interpreter int theICodeTop = 0; theICodeTop = generateICode(tree, theICodeTop); fixLabelGotos(); - // add RETURN_POPV only to scripts as function always ends with RETURN + // add RETURN_RESULT only to scripts as function always ends with RETURN if (itsData.itsFunctionType == 0) { - theICodeTop = addToken(Token.RETURN_POPV, theICodeTop); + theICodeTop = addToken(Token.RETURN_RESULT, theICodeTop); } // Add special CATCH to simplify Interpreter.interpret logic // and workaround lack of goto in Java @@ -476,7 +547,7 @@ public class Interpreter iCodeTop = generateICode(child, iCodeTop); while (null != (child = child.getNext())) { if (1 != itsStackDepth - savedStackDepth) Kit.codeBug(); - iCodeTop = addToken(Token.POP, iCodeTop); + iCodeTop = addIcode(Icode_POP, iCodeTop); itsStackDepth--; iCodeTop = generateICode(child, iCodeTop); } @@ -490,7 +561,7 @@ public class Interpreter iCodeTop = addIcode(Icode_DUP, iCodeTop); // No stack adjusting: USE_STACK in subtree will do it iCodeTop = generateICode(child, iCodeTop); - iCodeTop = addToken(Token.POP, iCodeTop); + iCodeTop = addIcode(Icode_POP, iCodeTop); itsStackDepth--; } break; @@ -530,7 +601,7 @@ public class Interpreter iCodeTop = addGoto(target, Icode_IFEQ_POP, iCodeTop); stackChange(-1); } - iCodeTop = addToken(Token.POP, iCodeTop); + iCodeTop = addIcode(Icode_POP, iCodeTop); stackChange(-1); Node defaultNode = (Node) switchNode.getProp(Node.DEFAULT_PROP); @@ -648,7 +719,7 @@ public class Interpreter int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ; iCodeTop = addForwardGoto(jump, iCodeTop); itsStackDepth--; - iCodeTop = addToken(Token.POP, iCodeTop); + iCodeTop = addIcode(Icode_POP, iCodeTop); itsStackDepth--; child = child.getNext(); iCodeTop = generateICode(child, iCodeTop); @@ -728,7 +799,7 @@ public class Interpreter stackDelta = 1; iCodeTop = generateICode(child, iCodeTop); if (type == Token.VOID) { - iCodeTop = addToken(Token.POP, iCodeTop); + iCodeTop = addIcode(Icode_POP, iCodeTop); iCodeTop = addIcode(Icode_UNDEF, iCodeTop); } else { iCodeTop = addToken(type, iCodeTop); @@ -862,13 +933,13 @@ public class Interpreter break; } - case Token.POPV : + case Token.EXPR_VOID : + case Token.EXPR_RESULT : stackShouldBeZero = true; - // fallthrough - case Token.POP : iCodeTop = updateLineNumber(node, iCodeTop); iCodeTop = generateICode(child, iCodeTop); - iCodeTop = addToken(type, iCodeTop); + iCodeTop = addIcode((type == Token.EXPR_VOID) + ? Icode_POP : Icode_POP_RESULT, iCodeTop); itsStackDepth--; break; @@ -964,10 +1035,10 @@ public class Interpreter } break; - case Token.RETURN_POPV : + case Token.RETURN_RESULT : stackShouldBeZero = true; iCodeTop = updateLineNumber(node, iCodeTop); - iCodeTop = addToken(Token.RETURN_POPV, iCodeTop); + iCodeTop = addToken(Token.RETURN_RESULT, iCodeTop); break; case Token.GETVAR : { @@ -1582,72 +1653,6 @@ public class Interpreter return best; } - private static String bytecodeName(int bytecode) - { - if (!validBytecode(bytecode)) { - throw new IllegalArgumentException(String.valueOf(bytecode)); - } - - if (!Token.printICode) { - return String.valueOf(bytecode); - } - - if (validTokenCode(bytecode)) { - return Token.name(bytecode); - } - - switch (bytecode) { - case Icode_DUP: return "DUP"; - case Icode_DUP2: return "DUP2"; - case Icode_SWAP: return "SWAP"; - case Icode_IFEQ_POP: return "IFEQ_POP"; - case Icode_VAR_INC_DEC: return "VAR_INC_DEC"; - case Icode_NAME_INC_DEC: return "NAME_INC_DEC"; - case Icode_PROP_INC_DEC: return "PROP_INC_DEC"; - case Icode_ELEM_INC_DEC: return "ELEM_INC_DEC"; - case Icode_REF_INC_DEC: return "REF_INC_DEC"; - case Icode_SCOPE: return "SCOPE"; - case Icode_TYPEOFNAME: return "TYPEOFNAME"; - case Icode_NAME_FAST_THIS: return "NAME_FAST_THIS"; - case Icode_NAME_SLOW_THIS: return "NAME_SLOW_THIS"; - case Icode_PUSH_PARENT: return "PUSH_PARENT"; - case Icode_CLOSURE: return "CLOSURE"; - case Icode_CALLSPECIAL: return "CALLSPECIAL"; - case Icode_RETUNDEF: return "RETUNDEF"; - case Icode_CATCH: return "CATCH"; - case Icode_GOSUB: return "GOSUB"; - case Icode_RETSUB: return "RETSUB"; - case Icode_LINE: return "LINE"; - case Icode_SHORTNUMBER: return "SHORTNUMBER"; - case Icode_INTNUMBER: return "INTNUMBER"; - case Icode_LITERAL_NEW: return "LITERAL_NEW"; - case Icode_LITERAL_SET: return "LITERAL_SET"; - case Icode_SPARE_ARRAYLIT: return "SPARE_ARRAYLIT"; - case Icode_REG_IND_C0: return "REG_IND_C0"; - case Icode_REG_IND_C1: return "REG_IND_C1"; - case Icode_REG_IND_C2: return "REG_IND_C2"; - case Icode_REG_IND_C3: return "REG_IND_C3"; - case Icode_REG_IND_C4: return "REG_IND_C4"; - case Icode_REG_IND_C5: return "REG_IND_C5"; - case Icode_REG_IND1: return "LOAD_IND1"; - case Icode_REG_IND2: return "LOAD_IND2"; - case Icode_REG_IND4: return "LOAD_IND4"; - case Icode_REG_STR_C0: return "REG_STR_C0"; - case Icode_REG_STR_C1: return "REG_STR_C1"; - case Icode_REG_STR_C2: return "REG_STR_C2"; - case Icode_REG_STR_C3: return "REG_STR_C3"; - case Icode_REG_STR1: return "LOAD_STR1"; - case Icode_REG_STR2: return "LOAD_STR2"; - case Icode_REG_STR4: return "LOAD_STR4"; - case Icode_GETVAR1: return "GETVAR1"; - case Icode_SETVAR1: return "SETVAR1"; - case Icode_UNDEF: return "UNDEF"; - } - - // icode without name - throw new IllegalStateException(String.valueOf(bytecode)); - } - private static void dumpICode(InterpreterData idata) { if (!Token.printICode) { @@ -2296,10 +2301,16 @@ switch (op) { } continue Loop; } - case Token.POP : + case Icode_POP : stack[stackTop] = null; stackTop--; continue Loop; + case Icode_POP_RESULT : + result = stack[stackTop]; + if (result == DBL_MRK) result = doubleWrap(sDbl[stackTop]); + stack[stackTop] = null; + --stackTop; + continue Loop; case Icode_DUP : stack[stackTop + 1] = stack[stackTop]; sDbl[stackTop + 1] = sDbl[stackTop]; @@ -2321,18 +2332,12 @@ switch (op) { sDbl[stackTop - 1] = d; continue Loop; } - case Token.POPV : - result = stack[stackTop]; - if (result == DBL_MRK) result = doubleWrap(sDbl[stackTop]); - stack[stackTop] = null; - --stackTop; - continue Loop; case Token.RETURN : result = stack[stackTop]; if (result == DBL_MRK) result = doubleWrap(sDbl[stackTop]); --stackTop; break Loop; - case Token.RETURN_POPV : + case Token.RETURN_RESULT : break Loop; case Icode_RETUNDEF : result = undefined; diff --git a/js/rhino/src/org/mozilla/javascript/NodeTransformer.java b/js/rhino/src/org/mozilla/javascript/NodeTransformer.java index c136193fcf6e..fafe83c68c63 100644 --- a/js/rhino/src/org/mozilla/javascript/NodeTransformer.java +++ b/js/rhino/src/org/mozilla/javascript/NodeTransformer.java @@ -225,25 +225,11 @@ public class NodeTransformer */ if (!hasFinally) break; // skip the whole mess. - Node child = node.getFirstChild(); - boolean inserted = false; + Node unwindBlock = null; for (int i=loops.size()-1; i >= 0; i--) { Node n = (Node) loops.get(i); int elemtype = n.getType(); if (elemtype == Token.TRY || elemtype == Token.WITH) { - if (!inserted) { - inserted = true; - if (child != null) { - node.setType(Token.POPV); - // process children now as node will be - // changed to point to inserted RETURN_POPV - transformCompilationUnit_r(tree, node); - Node retPopv = new Node(Token.RETURN_POPV); - parent.addChildAfter(retPopv, node); - previous = node; - node = retPopv; - } - } Node unwind; if (elemtype == Token.TRY) { Node.Jump jsrnode = new Node.Jump(Token.JSR); @@ -253,10 +239,30 @@ public class NodeTransformer } else { unwind = new Node(Token.LEAVEWITH); } - previous = addBeforeCurrent(parent, previous, node, - unwind); + if (unwindBlock == null) { + unwindBlock = new Node(Token.BLOCK, + node.getLineno()); + } + unwindBlock.addChildToBack(unwind); } } + if (unwindBlock != null) { + Node returnNode = node; + Node returnExpr = returnNode.getFirstChild(); + node = replaceCurrent(parent, previous, node, unwindBlock); + if (returnExpr == null) { + unwindBlock.addChildToBack(returnNode); + } else { + Node store = new Node(Token.EXPR_RESULT, returnExpr); + unwindBlock.addChildToFront(store); + returnNode = new Node(Token.RETURN_RESULT); + unwindBlock.addChildToBack(returnNode); + // transform return expression + transformCompilationUnit_r(tree, store); + } + // skip transformCompilationUnit_r to avoid infinite loop + continue siblingLoop; + } break; } @@ -347,10 +353,6 @@ public class NodeTransformer break; } - case Token.EXPRSTMT: - node.setType(inFunction ? Token.POP : Token.POPV); - break; - case Token.VAR: { Node result = new Node(Token.BLOCK); @@ -366,7 +368,7 @@ public class NodeTransformer n.removeChild(init); n.setType(Token.BINDNAME); n = new Node(Token.SETNAME, n, init); - Node pop = new Node(Token.POP, n, node.getLineno()); + Node pop = new Node(Token.EXPR_VOID, n, node.getLineno()); result.addChildToBack(pop); } node = replaceCurrent(parent, previous, node, result); diff --git a/js/rhino/src/org/mozilla/javascript/Token.java b/js/rhino/src/org/mozilla/javascript/Token.java index 9d7f23a85c4e..e2612e0d5a4b 100644 --- a/js/rhino/src/org/mozilla/javascript/Token.java +++ b/js/rhino/src/org/mozilla/javascript/Token.java @@ -73,7 +73,7 @@ public class Token // Interpreter reuses the following as bytecodes FIRST_BYTECODE_TOKEN = 2, - POPV = 2, +// XXX removed unused POPV ENTERWITH = 3, LEAVEWITH = 4, RETURN = 5, @@ -122,7 +122,7 @@ public class Token SHEQ = 48, // shallow equality (===) SHNE = 49, // shallow inequality (!==) REGEXP = 50, - POP = 51, +// XXX removed unused POP BINDNAME = 52, THROW = 53, IN = 54, @@ -137,7 +137,7 @@ public class Token ENUM_NEXT = 63, ENUM_ID = 64, THISFN = 65, - RETURN_POPV = 66, // to return result stored as popv in functions + RETURN_RESULT = 66, // to return result stored as popv in functions ARRAYLIT = 67, // array literal OBJECTLIT = 68, // object literal GET_REF = 69, // *reference @@ -197,18 +197,19 @@ public class Token LABEL = 113, // label TARGET = 114, LOOP = 115, - EXPRSTMT = 116, - JSR = 117, - SCRIPT = 118, // top-level node for entire script - TYPEOFNAME = 119, // for typeof(simple-name) - USE_STACK = 120, - SETPROP_OP = 121, // x.y op= something - SETELEM_OP = 122, // x[y] op= something - INIT_LIST = 123, - LOCAL_BLOCK = 124, - SET_REF_OP = 125, // *reference op= something + EXPR_VOID = 116, + EXPR_RESULT = 117, + JSR = 118, + SCRIPT = 119, // top-level node for entire script + TYPEOFNAME = 120, // for typeof(simple-name) + USE_STACK = 121, + SETPROP_OP = 122, // x.y op= something + SETELEM_OP = 123, // x[y] op= something + INIT_LIST = 124, + LOCAL_BLOCK = 125, + SET_REF_OP = 126, // *reference op= something - LAST_TOKEN = 125; + LAST_TOKEN = 126; public static String name(int token) { @@ -224,7 +225,6 @@ public class Token case ERROR: return "ERROR"; case EOF: return "EOF"; case EOL: return "EOL"; - case POPV: return "POPV"; case ENTERWITH: return "ENTERWITH"; case LEAVEWITH: return "LEAVEWITH"; case RETURN: return "RETURN"; @@ -273,7 +273,6 @@ public class Token case SHEQ: return "SHEQ"; case SHNE: return "SHNE"; case REGEXP: return "OBJECT"; - case POP: return "POP"; case BINDNAME: return "BINDNAME"; case THROW: return "THROW"; case IN: return "IN"; @@ -287,7 +286,7 @@ public class Token case ENUM_NEXT: return "ENUM_NEXT"; case ENUM_ID: return "ENUM_ID"; case THISFN: return "THISFN"; - case RETURN_POPV: return "RETURN_POPV"; + case RETURN_RESULT: return "RETURN_RESULT"; case ARRAYLIT: return "ARRAYLIT"; case OBJECTLIT: return "OBJECTLIT"; case GET_REF: return "GET_REF"; @@ -336,7 +335,8 @@ public class Token case LABEL: return "LABEL"; case TARGET: return "TARGET"; case LOOP: return "LOOP"; - case EXPRSTMT: return "EXPRSTMT"; + case EXPR_VOID: return "EXPR_VOID"; + case EXPR_RESULT: return "EXPR_RESULT"; case JSR: return "JSR"; case SCRIPT: return "SCRIPT"; case TYPEOFNAME: return "TYPEOFNAME"; diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java index 95e3dc131c7c..d042813ff44d 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java @@ -1461,7 +1461,7 @@ class BodyCodegen visitThrow(node, child); break; - case Token.RETURN_POPV: + case Token.RETURN_RESULT: if (fnCurrent == null) throw Codegen.badTree(); // fallthrough case Token.RETURN: @@ -1540,7 +1540,7 @@ class BodyCodegen break; } - case Token.POP: + case Token.EXPR_VOID: visitStatement(node); if (child.getType() == Token.SETVAR) { /* special case this so as to avoid unnecessary @@ -1548,10 +1548,7 @@ class BodyCodegen visitSetVar(child, child.getFirstChild(), false); } else { - while (child != null) { - generateCodeFromNode(child, node); - child = child.getNext(); - } + generateCodeFromNode(child, node); if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) cfw.add(ByteCode.POP2); else @@ -1559,7 +1556,7 @@ class BodyCodegen } break; - case Token.POPV: + case Token.EXPR_RESULT: visitStatement(node); generateCodeFromNode(child, node); if (popvLocal < 0) { diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java b/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java index 977fff4a9b13..970722b254e3 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java @@ -152,7 +152,7 @@ class Optimizer private int rewriteForNumberVariables(Node n) { switch (n.getType()) { - case Token.POP : { + case Token.EXPR_VOID : { Node child = n.getFirstChild(); int type = rewriteForNumberVariables(child); if (type == NumberType)