From d29f6cb477144ea88d7869255d3a498b529537fc Mon Sep 17 00:00:00 2001 From: "igor%mir2.org" Date: Tue, 7 Sep 2004 09:08:31 +0000 Subject: [PATCH] Inline small functions used for code generation to produce intepreter or JVM bytecode for particular parser tree node: they just add to jar file size without readability benefits. --- .../org/mozilla/javascript/Interpreter.java | 670 +++++++++--------- .../org/mozilla/javascript/ScriptRuntime.java | 173 +++-- .../mozilla/javascript/optimizer/Codegen.java | 498 ++++++------- 3 files changed, 632 insertions(+), 709 deletions(-) diff --git a/js/rhino/src/org/mozilla/javascript/Interpreter.java b/js/rhino/src/org/mozilla/javascript/Interpreter.java index 3032fbc84cf3..f229614c8e3a 100644 --- a/js/rhino/src/org/mozilla/javascript/Interpreter.java +++ b/js/rhino/src/org/mozilla/javascript/Interpreter.java @@ -535,24 +535,26 @@ public class Interpreter Node child = node.getFirstChild(); switch (type) { - case Token.FUNCTION: { - int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); - int fnType = scriptOrFn.getFunctionNode(fnIndex).getFunctionType(); - // Only function expressions or function expression - // statements needs closure code creating new function - // object on stack as function statements are initialized - // at script/function start - // In addition function expression can not present here - // at statement level, they must only present as expressions. - if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) { - addIndexOp(Icode_CLOSURE_STMT, fnIndex); - } else { - if (fnType != FunctionNode.FUNCTION_STATEMENT) { - throw Kit.codeBug(); + case Token.FUNCTION: + { + int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); + int fnType = scriptOrFn.getFunctionNode(fnIndex). + getFunctionType(); + // Only function expressions or function expression + // statements needs closure code creating new function + // object on stack as function statements are initialized + // at script/function start + // In addition function expression can not present here + // at statement level, they must only present as expressions. + if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) { + addIndexOp(Icode_CLOSURE_STMT, fnIndex); + } else { + if (fnType != FunctionNode.FUNCTION_STATEMENT) { + throw Kit.codeBug(); + } } } break; - } case Token.SCRIPT: case Token.LABEL: @@ -600,7 +602,32 @@ public class Interpreter break; case Token.SWITCH: - visitSwitch((Node.Jump)node); + updateLineNumber(node); + // See comments in IRFactory.createSwitch() for description + // of SWITCH node + { + Node switchNode = (Node.Jump)node; + visitExpression(child, 0); + for (Node.Jump caseNode = (Node.Jump)child.getNext(); + caseNode != null; + caseNode = (Node.Jump)caseNode.getNext()) + { + if (caseNode.getType() != Token.CASE) + throw badTree(caseNode); + Node test = caseNode.getFirstChild(); + addIcode(Icode_DUP); + stackChange(1); + visitExpression(test, 0); + addToken(Token.SHEQ); + stackChange(-1); + // If true, Icode_IFEQ_POP will jump and remove case + // value from stack + addGoto(caseNode.target, Icode_IFEQ_POP); + stackChange(-1); + } + addIcode(Icode_POP); + stackChange(-1); + } break; case Token.TARGET: @@ -608,25 +635,28 @@ public class Interpreter break; case Token.IFEQ : - case Token.IFNE : { - Node.Target target = ((Node.Jump)node).target; - visitExpression(child, 0); - addGoto(target, type); - stackChange(-1); + case Token.IFNE : + { + Node.Target target = ((Node.Jump)node).target; + visitExpression(child, 0); + addGoto(target, type); + stackChange(-1); + } break; - } - case Token.GOTO: { - Node.Target target = ((Node.Jump)node).target; - addGoto(target, type); + case Token.GOTO: + { + Node.Target target = ((Node.Jump)node).target; + addGoto(target, type); + } break; - } - case Token.JSR: { - Node.Target target = ((Node.Jump)node).target; - addGoto(target, Icode_GOSUB); + case Token.JSR: + { + Node.Target target = ((Node.Jump)node).target; + addGoto(target, Icode_GOSUB); + } break; - } case Token.FINALLY: { @@ -652,7 +682,33 @@ public class Interpreter break; case Token.TRY: - visitTry((Node.Jump)node, child); + { + Node.Jump tryNode = (Node.Jump)node; + int exceptionObjectLocal = getLocalBlockRef(tryNode); + int tryStart = itsICodeTop; + + while (child != null) { + visitStatement(child); + child = child.getNext(); + } + + Node.Target catchTarget = tryNode.target; + if (catchTarget != null) { + int catchStartPC + = itsLabelTable[getTargetLabel(catchTarget)]; + addExceptionHandler( + tryStart, catchStartPC, catchStartPC, + false, itsWithDepth, exceptionObjectLocal); + } + Node.Target finallyTarget = tryNode.getFinally(); + if (finallyTarget != null) { + int finallyStartPC + = itsLabelTable[getTargetLabel(finallyTarget)]; + addExceptionHandler( + tryStart, finallyStartPC, finallyStartPC, + true, itsWithDepth, exceptionObjectLocal); + } + } break; case Token.CATCH_SCOPE: @@ -722,37 +778,40 @@ public class Interpreter int savedStackDepth = itsStackDepth; switch (type) { - case Token.FUNCTION: { - int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); - FunctionNode fn = scriptOrFn.getFunctionNode(fnIndex); - // See comments in visitStatement for Token.FUNCTION case - if (fn.getFunctionType() != FunctionNode.FUNCTION_EXPRESSION) { - throw Kit.codeBug(); + case Token.FUNCTION: + { + int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); + FunctionNode fn = scriptOrFn.getFunctionNode(fnIndex); + // See comments in visitStatement for Token.FUNCTION case + if (fn.getFunctionType() != FunctionNode.FUNCTION_EXPRESSION) { + throw Kit.codeBug(); + } + addIndexOp(Icode_CLOSURE_EXPR, fnIndex); + stackChange(1); } - addIndexOp(Icode_CLOSURE_EXPR, fnIndex); - stackChange(1); break; - } - case Token.LOCAL_LOAD: { - int localIndex = getLocalBlockRef(node); - addIndexOp(Token.LOCAL_LOAD, localIndex); - stackChange(1); - break; - } - - case Token.COMMA: { - Node lastChild = node.getLastChild(); - while (child != lastChild) { - visitExpression(child, 0); - addIcode(Icode_POP); - stackChange(-1); - child = child.getNext(); + case Token.LOCAL_LOAD: + { + int localIndex = getLocalBlockRef(node); + addIndexOp(Token.LOCAL_LOAD, localIndex); + stackChange(1); + } + break; + + case Token.COMMA: + { + Node lastChild = node.getLastChild(); + while (child != lastChild) { + visitExpression(child, 0); + addIcode(Icode_POP); + stackChange(-1); + child = child.getNext(); + } + // Preserve tail context flag if any + visitExpression(child, contextFlags & ECF_TAIL); } - // Preserve tail context flag if any - visitExpression(child, contextFlags & ECF_TAIL); break; - } case Token.USE_STACK: // Indicates that stack was modified externally, @@ -763,56 +822,103 @@ public class Interpreter case Token.CALL: case Token.NEW: case Token.REF_CALL: - visitCall(node, contextFlags); + { + if (type == Token.NEW) { + visitExpression(child, 0); + } else { + generateCallFunAndThis(child); + } + int argCount = 0; + while ((child = child.getNext()) != null) { + visitExpression(child, 0); + ++argCount; + } + int callType = node.getIntProp(Node.SPECIALCALL_PROP, + Node.NON_SPECIALCALL); + if (callType != Node.NON_SPECIALCALL) { + // embed line number and source filename + addIndexOp(Icode_CALLSPECIAL, argCount); + addUint8(callType); + addUint8(type == Token.NEW ? 1 : 0); + addUint16(itsLineNumber & 0xFFFF); + } else { + if (type == Token.CALL) { + if ((contextFlags & ECF_TAIL) != 0) { + type = Icode_TAIL_CALL; + } + } + addIndexOp(type, argCount); + } + // adjust stack + if (type == Token.NEW) { + // f, args -> results + stackChange(-argCount); + } else { + // f, thisObj, args -> results + stackChange(-1 - argCount); + } + if (argCount > itsData.itsMaxCalleeArgs) { + itsData.itsMaxCalleeArgs = argCount; + } + } break; case Token.AND: - case Token.OR: { - visitExpression(child, 0); - addIcode(Icode_DUP); - stackChange(1); - int afterSecondJumpStart = itsICodeTop; - int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ; - addForwardGoto(jump); - stackChange(-1); - addIcode(Icode_POP); - stackChange(-1); - child = child.getNext(); - // Preserve tail context flag if any - visitExpression(child, contextFlags & ECF_TAIL); - resolveForwardGoto(afterSecondJumpStart); + case Token.OR: + { + visitExpression(child, 0); + addIcode(Icode_DUP); + stackChange(1); + int afterSecondJumpStart = itsICodeTop; + int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ; + addForwardGoto(jump); + stackChange(-1); + addIcode(Icode_POP); + stackChange(-1); + child = child.getNext(); + // Preserve tail context flag if any + visitExpression(child, contextFlags & ECF_TAIL); + resolveForwardGoto(afterSecondJumpStart); + } break; - } - case Token.HOOK: { - Node ifThen = child.getNext(); - Node ifElse = ifThen.getNext(); - visitExpression(child, 0); - int elseJumpStart = itsICodeTop; - addForwardGoto(Token.IFNE); - stackChange(-1); - // Preserve tail context flag if any - visitExpression(ifThen, contextFlags & ECF_TAIL); - int afterElseJumpStart = itsICodeTop; - addForwardGoto(Token.GOTO); - resolveForwardGoto(elseJumpStart); - itsStackDepth = savedStackDepth; - // Preserve tail context flag if any - visitExpression(ifElse, contextFlags & ECF_TAIL); - resolveForwardGoto(afterElseJumpStart); + case Token.HOOK: + { + Node ifThen = child.getNext(); + Node ifElse = ifThen.getNext(); + visitExpression(child, 0); + int elseJumpStart = itsICodeTop; + addForwardGoto(Token.IFNE); + stackChange(-1); + // Preserve tail context flag if any + visitExpression(ifThen, contextFlags & ECF_TAIL); + int afterElseJumpStart = itsICodeTop; + addForwardGoto(Token.GOTO); + resolveForwardGoto(elseJumpStart); + itsStackDepth = savedStackDepth; + // Preserve tail context flag if any + visitExpression(ifElse, contextFlags & ECF_TAIL); + resolveForwardGoto(afterElseJumpStart); + } break; - } case Token.GETPROP: - visitGetProp(node, child); + visitExpression(child, 0); + child = child.getNext(); + addStringOp(Token.GETPROP, child.getString()); break; case Token.GETELEM: - visitGetElem(node, child); + visitExpression(child, 0); + child = child.getNext(); + visitExpression(child, 0); + addToken(Token.GETELEM); + stackChange(-1); break; case Token.GET_REF: - visitGetRef(node, child); + visitExpression(child, 0); + addToken(Token.GET_REF); break; case Token.DELPROP: @@ -860,24 +966,25 @@ public class Interpreter } break; - case Token.SETPROP: - case Token.SETPROP_OP: { - visitExpression(child, 0); - child = child.getNext(); - String property = child.getString(); - child = child.getNext(); - if (type == Token.SETPROP_OP) { - addIcode(Icode_DUP); - stackChange(1); - addStringOp(Token.GETPROP, property); - // Compensate for the following USE_STACK + case Token.SETPROP: + case Token.SETPROP_OP: + { + visitExpression(child, 0); + child = child.getNext(); + String property = child.getString(); + child = child.getNext(); + if (type == Token.SETPROP_OP) { + addIcode(Icode_DUP); + stackChange(1); + addStringOp(Token.GETPROP, property); + // Compensate for the following USE_STACK + stackChange(-1); + } + visitExpression(child, 0); + addStringOp(Token.SETPROP, property); stackChange(-1); } - visitExpression(child, 0); - addStringOp(Token.SETPROP, property); - stackChange(-1); break; - } case Token.SETELEM: case Token.SETELEM_OP: @@ -914,33 +1021,35 @@ public class Interpreter stackChange(-1); break; - case Token.SETNAME: { - String name = child.getString(); - visitExpression(child, 0); - child = child.getNext(); - visitExpression(child, 0); - addStringOp(Token.SETNAME, name); - stackChange(-1); - break; - } - - case Token.TYPEOFNAME: { - String name = node.getString(); - int index = -1; - // use typeofname if an activation frame exists - // since the vars all exist there instead of in jregs - if (itsInFunctionFlag && !itsData.itsNeedsActivation) - index = scriptOrFn.getParamOrVarIndex(name); - if (index == -1) { - addStringOp(Icode_TYPEOFNAME, name); - stackChange(1); - } else { - addVarOp(Token.GETVAR, index); - stackChange(1); - addToken(Token.TYPEOF); + case Token.SETNAME: + { + String name = child.getString(); + visitExpression(child, 0); + child = child.getNext(); + visitExpression(child, 0); + addStringOp(Token.SETNAME, name); + stackChange(-1); + } + break; + + case Token.TYPEOFNAME: + { + String name = node.getString(); + int index = -1; + // use typeofname if an activation frame exists + // since the vars all exist there instead of in jregs + if (itsInFunctionFlag && !itsData.itsNeedsActivation) + index = scriptOrFn.getParamOrVarIndex(name); + if (index == -1) { + addStringOp(Icode_TYPEOFNAME, name); + stackChange(1); + } else { + addVarOp(Token.GETVAR, index); + stackChange(1); + addToken(Token.TYPEOF); + } } break; - } case Token.BINDNAME: case Token.NAME: @@ -955,41 +1064,68 @@ public class Interpreter break; case Token.NUMBER: - visitNumber(node); - break; - - case Token.GETVAR: { - String name = node.getString(); - if (itsData.itsNeedsActivation) { - // SETVAR handled this by turning into a SETPROP, but - // we can't do that to a GETVAR without manufacturing - // bogus children. Instead we use a special op to - // push the current scope. - addIcode(Icode_SCOPE); - stackChange(1); - addStringOp(Token.GETPROP, name); - } else { - int index = scriptOrFn.getParamOrVarIndex(name); - addVarOp(Token.GETVAR, index); + { + double num = node.getDouble(); + int inum = (int)num; + if (inum == num) { + if (inum == 0) { + addIcode(Icode_ZERO); + // Check for negative zero + if (1.0 / num < 0.0) { + addToken(Token.NEG); + } + } else if (inum == 1) { + addIcode(Icode_ONE); + } else if ((short)inum == inum) { + addIcode(Icode_SHORTNUMBER); + // write short as uin16 bit pattern + addUint16(inum & 0xFFFF); + } else { + addIcode(Icode_INTNUMBER); + addInt(inum); + } + } else { + int index = getDoubleIndex(num); + addIndexOp(Token.NUMBER, index); + } stackChange(1); } break; - } - case Token.SETVAR: { - if (itsData.itsNeedsActivation) { - child.setType(Token.BINDNAME); - node.setType(Token.SETNAME); - visitExpression(node, 0); - } else { - String name = child.getString(); - child = child.getNext(); - visitExpression(child, 0); - int index = scriptOrFn.getParamOrVarIndex(name); - addVarOp(Token.SETVAR, index); + case Token.GETVAR: + { + String name = node.getString(); + if (itsData.itsNeedsActivation) { + // SETVAR handled this by turning into a SETPROP, but + // we can't do that to a GETVAR without manufacturing + // bogus children. Instead we use a special op to + // push the current scope. + addIcode(Icode_SCOPE); + stackChange(1); + addStringOp(Token.GETPROP, name); + } else { + int index = scriptOrFn.getParamOrVarIndex(name); + addVarOp(Token.GETVAR, index); + stackChange(1); + } + } + break; + + case Token.SETVAR: + { + if (itsData.itsNeedsActivation) { + child.setType(Token.BINDNAME); + node.setType(Token.SETNAME); + visitExpression(node, 0); + } else { + String name = child.getString(); + child = child.getNext(); + visitExpression(child, 0); + int index = scriptOrFn.getParamOrVarIndex(name); + addVarOp(Token.SETVAR, index); + } } break; - } case Token.NULL: case Token.THIS: @@ -1006,24 +1142,26 @@ public class Interpreter stackChange(1); break; - case Token.REGEXP: { - int index = node.getExistingIntProp(Node.REGEXP_PROP); - addIndexOp(Token.REGEXP, index); - stackChange(1); + case Token.REGEXP: + { + int index = node.getExistingIntProp(Node.REGEXP_PROP); + addIndexOp(Token.REGEXP, index); + stackChange(1); + } break; - } case Token.ARRAYLIT: case Token.OBJECTLIT: visitLiteral(node, child); break; - case Token.SPECIAL_REF: { - visitExpression(child, 0); - String special = (String)node.getProp(Node.SPECIAL_PROP_PROP); - addStringOp(Token.SPECIAL_REF, special); + case Token.SPECIAL_REF: + { + String special = (String)node.getProp(Node.SPECIAL_PROP_PROP); + visitExpression(child, 0); + addStringOp(Token.SPECIAL_REF, special); + } break; - } case Token.XML_REF: visitExpression(child, 0); @@ -1031,7 +1169,16 @@ public class Interpreter break; case Token.DOTQUERY: - visitDotQery(node, child); + { + int queryPC; + updateLineNumber(node); + visitExpression(child, 0); + addIcode(Icode_ENTERDQ); + stackChange(-1); + queryPC = itsICodeTop; + visitExpression(child.getNext(), 0); + addBackwardGoto(Icode_LEAVEDQ, queryPC); + } break; case Token.DEFAULTNAMESPACE : @@ -1043,16 +1190,16 @@ public class Interpreter addToken(type); break; - case Token.COLONCOLON : { - if (child.getType() != Token.STRING) - throw badTree(child); - String namespace = child.getString(); - child = child.getNext(); - visitExpression(child, 0); - addStringOp(Token.COLONCOLON, namespace); + case Token.COLONCOLON : + { + if (child.getType() != Token.STRING) + throw badTree(child); + String namespace = child.getString(); + child = child.getNext(); + visitExpression(child, 0); + addStringOp(Token.COLONCOLON, namespace); + } break; - } - default: throw badTree(node); @@ -1062,103 +1209,6 @@ public class Interpreter } } - private void visitSwitch(Node.Jump switchNode) - { - // See comments in IRFactory.createSwitch() for description - // of SWITCH node - - updateLineNumber(switchNode); - - Node child = switchNode.getFirstChild(); - visitExpression(child, 0); - for (Node.Jump caseNode = (Node.Jump)child.getNext(); - caseNode != null; - caseNode = (Node.Jump)caseNode.getNext()) - { - if (caseNode.getType() != Token.CASE) - throw badTree(caseNode); - Node test = caseNode.getFirstChild(); - addIcode(Icode_DUP); - stackChange(1); - visitExpression(test, 0); - addToken(Token.SHEQ); - stackChange(-1); - // If true, Icode_IFEQ_POP will jump and remove case value - // from stack - addGoto(caseNode.target, Icode_IFEQ_POP); - stackChange(-1); - } - addIcode(Icode_POP); - stackChange(-1); - } - - private void visitTry(Node.Jump tryNode, Node child) - { - int tryStart = itsICodeTop; - while (child != null) { - visitStatement(child); - child = child.getNext(); - } - - int exceptionObjectLocal = getLocalBlockRef(tryNode); - - Node.Target catchTarget = tryNode.target; - if (catchTarget != null) { - int catchStartPC = itsLabelTable[getTargetLabel(catchTarget)]; - addExceptionHandler(tryStart, catchStartPC, catchStartPC, - false, itsWithDepth, exceptionObjectLocal); - } - Node.Target finallyTarget = tryNode.getFinally(); - if (finallyTarget != null) { - int finallyStartPC = itsLabelTable[getTargetLabel(finallyTarget)]; - addExceptionHandler(tryStart, finallyStartPC, finallyStartPC, - true, itsWithDepth, exceptionObjectLocal); - } - } - - private void visitCall(Node node, int contextFlags) - { - int type = node.getType(); - Node child = node.getFirstChild(); - if (type == Token.NEW) { - visitExpression(child, 0); - } else { - generateCallFunAndThis(child); - } - int argCount = 0; - while ((child = child.getNext()) != null) { - visitExpression(child, 0); - ++argCount; - } - int callType = node.getIntProp(Node.SPECIALCALL_PROP, - Node.NON_SPECIALCALL); - if (callType != Node.NON_SPECIALCALL) { - // embed line number and source filename - addIndexOp(Icode_CALLSPECIAL, argCount); - addUint8(callType); - addUint8(type == Token.NEW ? 1 : 0); - addUint16(itsLineNumber & 0xFFFF); - } else { - if (type == Token.CALL) { - if ((contextFlags & ECF_TAIL) != 0) { - type = Icode_TAIL_CALL; - } - } - addIndexOp(type, argCount); - } - // adjust stack - if (type == Token.NEW) { - // f, args -> results - stackChange(-argCount); - } else { - // f, thisObj, args -> results - stackChange(-1 - argCount); - } - if (argCount > itsData.itsMaxCalleeArgs) - itsData.itsMaxCalleeArgs = argCount; - - } - private void generateCallFunAndThis(Node left) { // Generate code to place on stack function and thisObj @@ -1198,29 +1248,6 @@ public class Interpreter } } - private void visitGetProp(Node node, Node child) - { - visitExpression(child, 0); - child = child.getNext(); - String property = child.getString(); - addStringOp(Token.GETPROP, property); - } - - private void visitGetElem(Node node, Node child) - { - visitExpression(child, 0); - child = child.getNext(); - visitExpression(child, 0); - addToken(Token.GETELEM); - stackChange(-1); - } - - private void visitGetRef(Node node, Node child) - { - visitExpression(child, 0); - addToken(Token.GET_REF); - } - private void visitIncDec(Node node, Node child) { int incrDecrMask = node.getExistingIntProp(Node.INCRDECR_PROP); @@ -1279,34 +1306,6 @@ public class Interpreter } } - private void visitNumber(Node node) - { - double num = node.getDouble(); - int inum = (int)num; - if (inum == num) { - if (inum == 0) { - addIcode(Icode_ZERO); - // Check for negative zero - if (1.0 / num < 0.0) { - addToken(Token.NEG); - } - } else if (inum == 1) { - addIcode(Icode_ONE); - } else if ((short)inum == inum) { - addIcode(Icode_SHORTNUMBER); - // write short as uin16 bit pattern - addUint16(inum & 0xFFFF); - } else { - addIcode(Icode_INTNUMBER); - addInt(inum); - } - } else { - int index = getDoubleIndex(num); - addIndexOp(Token.NUMBER, index); - } - stackChange(1); - } - private void visitLiteral(Node node, Node child) { int type = node.getType(); @@ -1347,17 +1346,6 @@ public class Interpreter } } - private void visitDotQery(Node node, Node child) - { - updateLineNumber(node); - visitExpression(child, 0); - addIcode(Icode_ENTERDQ); - stackChange(-1); - int queryPC = itsICodeTop; - visitExpression(child.getNext(), 0); - addBackwardGoto(Icode_LEAVEDQ, queryPC); - } - private int getLocalBlockRef(Node node) { Node localBlock = (Node)node.getProp(Node.LOCAL_BLOCK_PROP); diff --git a/js/rhino/src/org/mozilla/javascript/ScriptRuntime.java b/js/rhino/src/org/mozilla/javascript/ScriptRuntime.java index 5cd91f54e1b9..2cede9a781cb 100644 --- a/js/rhino/src/org/mozilla/javascript/ScriptRuntime.java +++ b/js/rhino/src/org/mozilla/javascript/ScriptRuntime.java @@ -1022,90 +1022,6 @@ public class ScriptRuntime { return (char)i; } - /** - * Converts Java exceptions that JS can catch into an object the script - * will see as the catch argument. - */ - private static Object getCatchObject(Context cx, Scriptable scope, - Throwable t) - throws JavaScriptException - { - EvaluatorException evaluator = null; - if (t instanceof EvaluatorException) { - evaluator = (EvaluatorException)t; - while (t instanceof WrappedException) { - t = ((WrappedException)t).getWrappedException(); - } - } - - if (t instanceof JavaScriptException) { - return ((JavaScriptException)t).getValue(); - - } else if (t instanceof EcmaError) { - EcmaError ee = (EcmaError)t; - String errorName = ee.getName(); - return makeErrorObject(cx, scope, errorName, ee.getErrorMessage(), - ee.sourceName(), ee.lineNumber()); - } else if (evaluator == null) { - // Script can catch only instances of JavaScriptException, - // EcmaError and EvaluatorException - Kit.codeBug(); - } - - if (t != evaluator && t instanceof EvaluatorException) { - // ALERT: it should not happen as throwAsUncheckedException - // takes care about it when exception is propagated through Java - // reflection calls, but for now check for it - evaluator = (EvaluatorException)t; - } - - String errorName; - String message; - if (t == evaluator) { - // Pure evaluator exception - if (evaluator instanceof WrappedException) Kit.codeBug(); - message = evaluator.getMessage(); - errorName = "InternalError"; - } else { - errorName = "JavaException"; - message = t.getClass().getName()+": "+t.getMessage(); - } - - Scriptable errorObject = makeErrorObject(cx, scope, errorName, - message, - evaluator.sourceName(), - evaluator.lineNumber()); - if (t != evaluator) { - Object twrap = cx.getWrapFactory().wrap(cx, scope, t, null); - ScriptableObject.putProperty(errorObject, "javaException", twrap); - } - return errorObject; - - } - - private static Scriptable makeErrorObject(Context cx, Scriptable scope, - String errorName, String message, - String fileName, int lineNumber) - throws JavaScriptException - { - int argLength; - if (lineNumber > 0) { - argLength = 3; - } else { - argLength = 2; - } - Object args[] = new Object[argLength]; - args[0] = message; - args[1] = (fileName != null) ? fileName : ""; - if (lineNumber > 0) { - args[2] = new Integer(lineNumber); - } - - Scriptable errorObject = cx.newObject(scope, errorName, args); - ScriptableObject.putProperty(errorObject, "name", errorName); - return errorObject; - } - // XXX: this is until setDefaultNamespace will learn how to store NS // properly and separates namespace form Scriptable.get etc. private static final String DEFAULT_NS_TAG = "__default_namespace__"; @@ -2982,26 +2898,95 @@ public class ScriptRuntime { return null; } - public static Scriptable newCatchScope(Throwable exception, + public static Scriptable newCatchScope(Throwable t, Scriptable lastCatchScope, String exceptionName, Context cx, Scriptable scope) { Object obj; - if (lastCatchScope == null) { - obj = getCatchObject(cx, scope, exception); + boolean cacheObj; + + getObj: + if (t instanceof JavaScriptException) { + cacheObj = false; + obj = ((JavaScriptException)t).getValue(); } else { - NativeObject last = (NativeObject)lastCatchScope; - obj = last.getAssociatedValue(exception); - if (obj == null) Kit.codeBug(); + cacheObj = true; + + // Create wrapper object unless it was associated with + // the previous scope object + + if (lastCatchScope != null) { + NativeObject last = (NativeObject)lastCatchScope; + obj = last.getAssociatedValue(t); + if (obj == null) Kit.codeBug(); + break getObj; + } + + RhinoException re; + String errorName; + String errorMsg; + Throwable javaException = null; + + if (t instanceof EcmaError) { + EcmaError ee = (EcmaError)t; + re = ee; + errorName = ee.getName(); + errorMsg = ee.getErrorMessage(); + } else if (t instanceof WrappedException) { + WrappedException we = (WrappedException)t; + re = we; + javaException = we.getWrappedException(); + errorName = "JavaException"; + errorMsg = javaException.getClass().getName() + +": "+javaException.getMessage(); + } else if (t instanceof EvaluatorException) { + // Pure evaluator exception, nor WrappedException instance + EvaluatorException ee = (EvaluatorException)t; + re = ee; + errorName = "InternalError"; + errorMsg = ee.getMessage(); + } else { + // Script can catch only instances of JavaScriptException, + // EcmaError and EvaluatorException + throw Kit.codeBug(); + } + + String sourceUri = re.sourceName(); + if (sourceUri == null) { + sourceUri = ""; + } + int line = re.lineNumber(); + Object args[]; + if (line > 0) { + args = new Object[] { errorMsg, sourceUri, new Integer(line) }; + } else { + args = new Object[] { errorMsg, sourceUri }; + } + + Scriptable errorObject = cx.newObject(scope, errorName, args); + ScriptableObject.putProperty(errorObject, "name", errorName); + + if (javaException != null) { + Object wrap = cx.getWrapFactory().wrap(cx, scope, javaException, + null); + ScriptableObject.defineProperty( + errorObject, "javaException", wrap, + ScriptableObject.PERMANENT | ScriptableObject.READONLY); + } + + obj = errorObject; } - NativeObject catchScope = new NativeObject(); + + NativeObject catchScopeObject = new NativeObject(); // See ECMA 12.4 - catchScope.defineProperty( + catchScopeObject.defineProperty( exceptionName, obj, ScriptableObject.PERMANENT); - catchScope.associateValue(exception, obj); - return catchScope; + if (cacheObj) { + catchScopeObject.associateValue(t, obj); + } + return catchScopeObject; } public static Scriptable enterWith(Object value, Scriptable scope) diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java index 00a5d34b30b7..49e5850a7958 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java @@ -1192,7 +1192,7 @@ class BodyCodegen localsMax = firstFreeLocal; if (fnCurrent == null) { - // See comments in visitRegexp + // See comments in case Token.REGEXP if (scriptOrFn.getRegexpCount() != 0) { scriptRegexpLocal = getNewWordLocal(); codegen.pushRegExpArray(cfw, scriptOrFn, contextLocal, @@ -1470,11 +1470,50 @@ class BodyCodegen break; case Token.CATCH_SCOPE: - visitCatchScope(node, child); + { + int local = getLocalBlockRegister(node); + int scopeIndex + = node.getExistingIntProp(Node.CATCH_SCOPE_PROP); + + String name = child.getString(); // name of exception + child = child.getNext(); + generateExpression(child, node); // load expression object + if (scopeIndex == 0) { + cfw.add(ByteCode.ACONST_NULL); + } else { + // Load previous catch scope object + cfw.addALoad(local); + } + cfw.addPush(name); + cfw.addALoad(contextLocal); + cfw.addALoad(variableObjectLocal); + + addScriptRuntimeInvoke( + "newCatchScope", + "(Ljava/lang/Throwable;" + +"Lorg/mozilla/javascript/Scriptable;" + +"Ljava/lang/String;" + +"Lorg/mozilla/javascript/Context;" + +"Lorg/mozilla/javascript/Scriptable;" + +")Lorg/mozilla/javascript/Scriptable;"); + cfw.addAStore(local); + } break; case Token.THROW: - visitThrow(node, child); + generateExpression(child, node); + cfw.add(ByteCode.NEW, + "org/mozilla/javascript/JavaScriptException"); + cfw.add(ByteCode.DUP_X1); + cfw.add(ByteCode.SWAP); + cfw.addPush(scriptOrFn.getSourceName()); + cfw.addPush(itsLineNumber); + cfw.addInvoke( + ByteCode.INVOKESPECIAL, + "org/mozilla/javascript/JavaScriptException", + "", + "(Ljava/lang/Object;Ljava/lang/String;I)V"); + cfw.add(ByteCode.ATHROW); break; case Token.RETHROW: @@ -1504,11 +1543,23 @@ class BodyCodegen break; case Token.ENTERWITH: - visitEnterWith(node, child); + generateExpression(child, node); + cfw.addALoad(variableObjectLocal); + addScriptRuntimeInvoke( + "enterWith", + "(Ljava/lang/Object;" + +"Lorg/mozilla/javascript/Scriptable;" + +")Lorg/mozilla/javascript/Scriptable;"); + cfw.addAStore(variableObjectLocal); break; case Token.LEAVEWITH: - visitLeaveWith(node, child); + cfw.addALoad(variableObjectLocal); + addScriptRuntimeInvoke( + "leaveWith", + "(Lorg/mozilla/javascript/Scriptable;" + +")Lorg/mozilla/javascript/Scriptable;"); + cfw.addAStore(variableObjectLocal); break; case Token.ENUM_INIT_KEYS: @@ -1547,7 +1598,10 @@ class BodyCodegen break; case Token.TARGET: - visitTarget((Node.Target)node); + { + int label = getTargetLabel((Node.Target)node); + cfw.markLabel(label); + } break; case Token.JSR: @@ -1558,7 +1612,17 @@ class BodyCodegen break; case Token.FINALLY: - visitFinally(node, child); + { + //Save return address in a new local where + int finallyRegister = getNewWordLocal(); + cfw.addAStore(finallyRegister); + while (child != null) { + generateStatement(child, node); + child = child.getNext(); + } + cfw.add(ByteCode.RET, finallyRegister); + releaseWordLocal((short)finallyRegister); + } break; default: @@ -1589,27 +1653,68 @@ class BodyCodegen break; case Token.NAME: - visitName(node); + { + cfw.addALoad(contextLocal); + cfw.addALoad(variableObjectLocal); + cfw.addPush(node.getString()); + addScriptRuntimeInvoke( + "name", + "(Lorg/mozilla/javascript/Context;" + +"Lorg/mozilla/javascript/Scriptable;" + +"Ljava/lang/String;" + +")Ljava/lang/Object;"); + } break; case Token.CALL: - case Token.NEW: { - int specialType = node.getIntProp(Node.SPECIALCALL_PROP, - Node.NON_SPECIALCALL); - if (specialType == Node.NON_SPECIALCALL) { - visitCall(node, type, child); - } else { - visitSpecialCall(node, type, specialType, child); + case Token.NEW: + { + int specialType = node.getIntProp(Node.SPECIALCALL_PROP, + Node.NON_SPECIALCALL); + if (specialType == Node.NON_SPECIALCALL) { + OptFunctionNode target; + target = (OptFunctionNode)node.getProp( + Node.DIRECTCALL_PROP); + + if (target != null) { + visitOptimizedCall(node, target, type, child); + } else if (type == Token.CALL) { + visitStandardCall(node, child); + } else { + visitStandardNew(node, child); + } + } else { + visitSpecialCall(node, type, specialType, child); + } } break; - } case Token.REF_CALL: - visitRefCall(node, type, child); + generateFunctionAndThisObj(child, node); + // stack: ... functionObj thisObj + child = child.getNext(); + generateCallArgArray(node, child, false); + cfw.addALoad(contextLocal); + cfw.addALoad(variableObjectLocal); + addScriptRuntimeInvoke( + "referenceCall", + "(Lorg/mozilla/javascript/Function;" + +"Lorg/mozilla/javascript/Scriptable;" + +"[Ljava/lang/Object;" + +"Lorg/mozilla/javascript/Context;" + +"Lorg/mozilla/javascript/Scriptable;" + +")Ljava/lang/Object;"); break; case Token.NUMBER: - visitNumber(node); + { + double num = node.getDouble(); + if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { + cfw.addPush(num); + } else { + codegen.pushNumberAsObject(cfw, num); + } + } break; case Token.STRING: @@ -1639,7 +1744,24 @@ class BodyCodegen break; case Token.REGEXP: - visitRegexp(node); + { + int i = node.getExistingIntProp(Node.REGEXP_PROP); + // Scripts can not use REGEXP_ARRAY_FIELD_NAME since + // it it will make script.exec non-reentrant so they + // store regexp array in a local variable while + // functions always access precomputed + // REGEXP_ARRAY_FIELD_NAME not to consume locals + if (fnCurrent == null) { + cfw.addALoad(scriptRegexpLocal); + } else { + cfw.addALoad(funObjLocal); + cfw.add(ByteCode.GETFIELD, codegen.mainClassName, + Codegen.REGEXP_ARRAY_FIELD_NAME, + Codegen.REGEXP_ARRAY_FIELD_TYPE); + } + cfw.addPush(i); + cfw.add(ByteCode.AALOAD); + } break; case Token.COMMA: { @@ -1875,11 +1997,35 @@ class BodyCodegen break; case Token.GETELEM: - visitGetElem(node, child); + generateExpression(child, node); // object + generateExpression(child.getNext(), node); // id + cfw.addALoad(contextLocal); + cfw.addALoad(variableObjectLocal); + if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { + addOptRuntimeInvoke( + "getObjectIndex", + "(Ljava/lang/Object;D" + +"Lorg/mozilla/javascript/Context;" + +"Lorg/mozilla/javascript/Scriptable;" + +")Ljava/lang/Object;"); + } + else { + addScriptRuntimeInvoke( + "getObjectElem", + "(Ljava/lang/Object;" + +"Ljava/lang/Object;" + +"Lorg/mozilla/javascript/Context;" + +"Lorg/mozilla/javascript/Scriptable;" + +")Ljava/lang/Object;"); + } break; case Token.GET_REF: - visitGetRef(node, child); + generateExpression(child, node); // reference + addScriptRuntimeInvoke( + "getReference", + "(Ljava/lang/Object;" + +")Ljava/lang/Object;"); break; case Token.GETVAR: @@ -1906,7 +2052,23 @@ class BodyCodegen case Token.SET_REF: case Token.SET_REF_OP: - visitSetRef(type, node, child); + { + generateExpression(child, node); + child = child.getNext(); + if (type == Token.SET_REF_OP) { + cfw.add(ByteCode.DUP); + addScriptRuntimeInvoke( + "getReference", + "(Ljava/lang/Object;" + +")Ljava/lang/Object;"); + } + generateExpression(child, node); + addScriptRuntimeInvoke( + "setReference", + "(Ljava/lang/Object;" + +"Ljava/lang/Object;" + +")Ljava/lang/Object;"); + } break; case Token.DEL_REF: @@ -1931,7 +2093,22 @@ class BodyCodegen break; case Token.BINDNAME: - visitBind(node, child); + { + while (child != null) { + generateExpression(child, node); + child = child.getNext(); + } + // Generate code for "ScriptRuntime.bind(varObj, "s")" + cfw.addALoad(contextLocal); + cfw.addALoad(variableObjectLocal); + cfw.addPush(node.getString()); + addScriptRuntimeInvoke( + "bind", + "(Lorg/mozilla/javascript/Context;" + +"Lorg/mozilla/javascript/Scriptable;" + +"Ljava/lang/String;" + +")Lorg/mozilla/javascript/Scriptable;"); + } break; case Token.LOCAL_LOAD: @@ -1939,11 +2116,33 @@ class BodyCodegen break; case Token.SPECIAL_REF: - visitSpecialRef(node, child); + { + String special + = (String)node.getProp(Node.SPECIAL_PROP_PROP); + generateExpression(child, node); + cfw.addPush(special); + cfw.addALoad(contextLocal); + cfw.addALoad(variableObjectLocal); + addScriptRuntimeInvoke("specialReference", + "(Ljava/lang/Object;" + +"Ljava/lang/String;" + +"Lorg/mozilla/javascript/Context;" + +"Lorg/mozilla/javascript/Scriptable;" + +")Ljava/lang/Object;"); + } break; case Token.XML_REF: - visitXMLRef(node, child); + { + generateExpression(child, node); + cfw.addALoad(contextLocal); + cfw.addALoad(variableObjectLocal); + addScriptRuntimeInvoke("xmlReference", + "(Ljava/lang/Object;" + +"Lorg/mozilla/javascript/Context;" + +"Lorg/mozilla/javascript/Scriptable;" + +")Ljava/lang/Object;"); + } break; case Token.DOTQUERY: @@ -2142,12 +2341,6 @@ class BodyCodegen return target.labelId; } - private void visitTarget(Node.Target target) - { - int label = getTargetLabel(target); - cfw.markLabel(label); - } - private void visitGOTO(Node.Jump node, int type, Node child) { Node.Target target = node.target; @@ -2168,39 +2361,6 @@ class BodyCodegen } } - private void visitFinally(Node node, Node child) - { - //Save return address in a new local where - int finallyRegister = getNewWordLocal(); - cfw.addAStore(finallyRegister); - while (child != null) { - generateStatement(child, node); - child = child.getNext(); - } - cfw.add(ByteCode.RET, finallyRegister); - releaseWordLocal((short)finallyRegister); - } - - private void visitEnterWith(Node node, Node child) - { - generateExpression(child, node); - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke("enterWith", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(variableObjectLocal); - } - - private void visitLeaveWith(Node node, Node child) - { - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke("leaveWith", - "(Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(variableObjectLocal); - } - private void visitArrayLiteral(Node node, Node child) { int count = 0; @@ -2274,20 +2434,6 @@ class BodyCodegen +")Lorg/mozilla/javascript/Scriptable;"); } - private void visitCall(Node node, int type, Node child) - { - OptFunctionNode - target = (OptFunctionNode)node.getProp(Node.DIRECTCALL_PROP); - - if (target != null) { - visitOptimizedCall(node, target, type, child); - } else if (type == Token.CALL) { - visitStandardCall(node, child); - } else { - visitStandardNew(node, child); - } - } - private void visitSpecialCall(Node node, int type, int specialType, Node child) { @@ -2341,23 +2487,6 @@ class BodyCodegen addOptRuntimeInvoke(methodName, callSignature); } - private void visitRefCall(Node node, int type, Node child) - { - generateFunctionAndThisObj(child, node); - // stack: ... functionObj thisObj - child = child.getNext(); - generateCallArgArray(node, child, false); - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke("referenceCall", - "(Lorg/mozilla/javascript/Function;" - +"Lorg/mozilla/javascript/Scriptable;" - +"[Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"); - } - private void visitStandardCall(Node node, Node child) { if (node.getType() != Token.CALL) throw Codegen.badTree(); @@ -2867,23 +2996,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg. cfw.add(ByteCode.GOTO, catchLabel); } - private void visitThrow(Node node, Node child) - { - generateExpression(child, node); - cfw.add(ByteCode.NEW, - "org/mozilla/javascript/JavaScriptException"); - cfw.add(ByteCode.DUP_X1); - cfw.add(ByteCode.SWAP); - cfw.addPush(scriptOrFn.getSourceName()); - cfw.addPush(itsLineNumber); - cfw.addInvoke(ByteCode.INVOKESPECIAL, - "org/mozilla/javascript/JavaScriptException", - "", - "(Ljava/lang/Object;Ljava/lang/String;I)V"); - - cfw.add(ByteCode.ATHROW); - } - private void visitSwitch(Node.Jump switchNode, Node child) { // See comments in IRFactory.createSwitch() for description @@ -3397,77 +3509,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg. if (stackInitial != cfw.getStackTop()) throw Codegen.badTree(); } - private void visitNumber(Node node) - { - double num = node.getDouble(); - if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { - cfw.addPush(num); - } else { - codegen.pushNumberAsObject(cfw, num); - } - } - - private void visitRegexp(Node node) - { - int i = node.getExistingIntProp(Node.REGEXP_PROP); - // Scripts can not use REGEXP_ARRAY_FIELD_NAME since - // it it will make script.exec non-reentrant so they - // store regexp array in a local variable while - // functions always access precomputed REGEXP_ARRAY_FIELD_NAME - // not to consume locals - if (fnCurrent == null) { - cfw.addALoad(scriptRegexpLocal); - } else { - cfw.addALoad(funObjLocal); - cfw.add(ByteCode.GETFIELD, codegen.mainClassName, - Codegen.REGEXP_ARRAY_FIELD_NAME, - Codegen.REGEXP_ARRAY_FIELD_TYPE); - } - cfw.addPush(i); - cfw.add(ByteCode.AALOAD); - } - - private void visitCatchScope(Node node, Node child) - { - int local = getLocalBlockRegister(node); - int scopeIndex = node.getExistingIntProp(Node.CATCH_SCOPE_PROP); - - String name = child.getString(); // name of exception variable - child = child.getNext(); - generateExpression(child, node); // load expression object - if (scopeIndex == 0) { - cfw.add(ByteCode.ACONST_NULL); - } else { - // Load previous catch scope object - cfw.addALoad(local); - } - cfw.addPush(name); - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - - addScriptRuntimeInvoke("newCatchScope", - "(Ljava/lang/Throwable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(local); - } - - private void visitName(Node node) - { - cfw.addALoad(contextLocal); // push cx - cfw.addALoad(variableObjectLocal); // get variable object - cfw.addPush(node.getString()); // push name - addScriptRuntimeInvoke( - "name", - "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +")Ljava/lang/Object;"); - } - private void visitSetName(Node node, Node child) { String name = node.getFirstChild().getString(); @@ -3609,38 +3650,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg. } } - private void visitGetElem(Node node, Node child) - { - generateExpression(child, node); // object - generateExpression(child.getNext(), node); // id - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { - addOptRuntimeInvoke( - "getObjectIndex", - "(Ljava/lang/Object;D" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"); - } - else { - addScriptRuntimeInvoke( - "getObjectElem", - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"); - } - } - - private void visitGetRef(Node node, Node child) - { - generateExpression(child, node); // reference - addScriptRuntimeInvoke( - "getReference", "(Ljava/lang/Object;)Ljava/lang/Object;"); - } - private void visitSetProp(int type, Node node, Node child) { Node objectChild = child; @@ -3754,65 +3763,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg. } } - private void visitSetRef(int type, Node node, Node child) - { - generateExpression(child, node); - child = child.getNext(); - if (type == Token.SET_REF_OP) { - cfw.add(ByteCode.DUP); - addScriptRuntimeInvoke( - "getReference", "(Ljava/lang/Object;)Ljava/lang/Object;"); - } - generateExpression(child, node); - addScriptRuntimeInvoke( - "setReference", - "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - } - - private void visitBind(Node node, Node child) - { - while (child != null) { - generateExpression(child, node); - child = child.getNext(); - } - // Generate code for "ScriptRuntime.bind(varObj, "s")" - cfw.addALoad(contextLocal); // push cx - cfw.addALoad(variableObjectLocal); // push variable object - cfw.addPush(node.getString()); // push name - addScriptRuntimeInvoke("bind", - "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +")Lorg/mozilla/javascript/Scriptable;"); - } - - private void visitSpecialRef(Node node, Node child) - { - String special = (String)node.getProp(Node.SPECIAL_PROP_PROP); - generateExpression(child, node); - cfw.addPush(special); - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke("specialReference", - "(Ljava/lang/Object;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"); - } - - private void visitXMLRef(Node node, Node child) - { - generateExpression(child, node); - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke("xmlReference", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"); - } - private void visitDotQuery(Node node, Node child) { updateLineNumber(node);