diff --git a/mozilla/js/rhino/src/org/mozilla/javascript/Context.java b/mozilla/js/rhino/src/org/mozilla/javascript/Context.java index b8889cdc7d6..1f69fab30fb 100644 --- a/mozilla/js/rhino/src/org/mozilla/javascript/Context.java +++ b/mozilla/js/rhino/src/org/mozilla/javascript/Context.java @@ -2011,12 +2011,10 @@ public class Context { if (printTrees) { System.out.println(tree.toStringTree()); } if (returnFunction) { - Node first = tree.getFirstChild(); - if (first == null) - return null; - tree = (ScriptOrFnNode)first.getProp(Node.FUNCTION_PROP); - if (tree == null) + int functionCount = tree.getFunctionCount(); + if (functionCount == 0) return null; + tree = tree.getFunctionNode(0); } if (debugger != null) { diff --git a/mozilla/js/rhino/src/org/mozilla/javascript/IRFactory.java b/mozilla/js/rhino/src/org/mozilla/javascript/IRFactory.java index 592e9c66365..c84c57aa300 100644 --- a/mozilla/js/rhino/src/org/mozilla/javascript/IRFactory.java +++ b/mozilla/js/rhino/src/org/mozilla/javascript/IRFactory.java @@ -48,24 +48,25 @@ public class IRFactory { this.compiler = compiler; this.ts = ts; } + + public ScriptOrFnNode createScript() { + return new ScriptOrFnNode(TokenStream.SCRIPT); + } /** * Script (for associating file/url names with toplevel scripts.) */ - public ScriptOrFnNode - createScript(Object body, VariableTable vars, String sourceName, - int baseLineno, int endLineno, String source) + public void + initScript(ScriptOrFnNode scriptNode, Object body, + String sourceName, int baseLineno, int endLineno, String source) { - ScriptOrFnNode result = new ScriptOrFnNode(TokenStream.SCRIPT); - result.variableTable = vars; - result.setEncodedSource(source); - result.setSourceName(sourceName); - result.setBaseLineno(baseLineno); - result.setEndLineno(endLineno); + scriptNode.setEncodedSource(source); + scriptNode.setSourceName(sourceName); + scriptNode.setBaseLineno(baseLineno); + scriptNode.setEndLineno(endLineno); Node children = ((Node) body).getFirstChild(); - if (children != null) { result.addChildrenToBack(children); } - return result; + if (children != null) { scriptNode.addChildrenToBack(children); } } /** @@ -202,25 +203,26 @@ public class IRFactory { return new Node(TokenStream.BLOCK, lineno); } - public Object createFunction(String name, VariableTable vars, - Object statements, - String sourceName, int baseLineno, - int endLineno, String source, - int functionType) + public FunctionNode createFunction(String name) { + return compiler.createFunctionNode(this, name); + } + + public Object initFunction(FunctionNode fnNode, int functionIndex, + Object statements, + String sourceName, int baseLineno, + int endLineno, String source, + int functionType) { - if (name == null) { - name = ""; - } - FunctionNode f = compiler.createFunctionNode(this, name); - f.variableTable = vars; - f.setEncodedSource(source); - f.setSourceName(sourceName); - f.setBaseLineno(baseLineno); - f.setEndLineno(endLineno); - f.setFunctionType(functionType); - f.addChildToBack((Node)statements); - Node result = Node.newString(TokenStream.FUNCTION, name); - result.putProp(Node.FUNCTION_PROP, f); + fnNode.setEncodedSource(source); + fnNode.setSourceName(sourceName); + fnNode.setBaseLineno(baseLineno); + fnNode.setEndLineno(endLineno); + fnNode.setFunctionType(functionType); + fnNode.addChildToBack((Node)statements); + + Node result = Node.newString(TokenStream.FUNCTION, + fnNode.getFunctionName()); + result.putIntProp(Node.FUNCTION_PROP, functionIndex); return result; } diff --git a/mozilla/js/rhino/src/org/mozilla/javascript/Interpreter.java b/mozilla/js/rhino/src/org/mozilla/javascript/Interpreter.java index 3ad7932f1b9..902993c4cd2 100644 --- a/mozilla/js/rhino/src/org/mozilla/javascript/Interpreter.java +++ b/mozilla/js/rhino/src/org/mozilla/javascript/Interpreter.java @@ -81,32 +81,30 @@ public class Interpreter { compile(Context cx, Scriptable scope, ScriptOrFnNode tree, SecurityController securityController, Object securityDomain) { + scriptOrFn = tree; version = cx.getLanguageVersion(); itsData = new InterpreterData(securityDomain); if (tree instanceof FunctionNode) { - FunctionNode f = (FunctionNode) tree; - itsData.itsFunctionType = f.getFunctionType(); - generateFunctionICode(cx, scope, f); + generateFunctionICode(cx, scope); return createFunction(cx, scope, itsData, false); } else { - generateScriptICode(cx, scope, tree); + generateScriptICode(cx, scope); return new InterpretedScript(cx, itsData); } } - private void - generateScriptICode(Context cx, Scriptable scope, ScriptOrFnNode tree) + private void generateScriptICode(Context cx, Scriptable scope) { - itsSourceFile = tree.getSourceName(); + itsSourceFile = scriptOrFn.getSourceName(); itsData.itsSourceFile = itsSourceFile; - debugSource = tree.getOriginalSource(); + debugSource = scriptOrFn.getOriginalSource(); - generateNestedFunctions(cx, scope, tree); + generateNestedFunctions(cx, scope); - generateRegExpLiterals(cx, scope, tree); + generateRegExpLiterals(cx, scope); - itsVariableTable = tree.getVariableTable(); - generateICodeFromTree(tree); + itsVariableTable = scriptOrFn.getVariableTable(); + generateICodeFromTree(scriptOrFn); if (Context.printICode) dumpICode(itsData); if (cx.debugger != null) { @@ -114,9 +112,10 @@ public class Interpreter { } } - private void generateFunctionICode(Context cx, Scriptable scope, - FunctionNode theFunction) + private void generateFunctionICode(Context cx, Scriptable scope) { + FunctionNode theFunction = (FunctionNode)scriptOrFn; + itsData.itsFunctionType = theFunction.getFunctionType(); // check if function has own source, which is the case // with Function(...) String savedSource = debugSource; @@ -124,9 +123,9 @@ public class Interpreter { if (debugSource == null) { debugSource = savedSource; } - generateNestedFunctions(cx, scope, theFunction); + generateNestedFunctions(cx, scope); - generateRegExpLiterals(cx, scope, theFunction); + generateRegExpLiterals(cx, scope); itsData.itsNeedsActivation = theFunction.requiresActivation(); @@ -144,34 +143,30 @@ public class Interpreter { debugSource = savedSource; } - private void generateNestedFunctions(Context cx, Scriptable scope, - ScriptOrFnNode tree) + private void generateNestedFunctions(Context cx, Scriptable scope) { - int functionCount = tree.getFunctionCount(); + int functionCount = scriptOrFn.getFunctionCount(); if (functionCount == 0) return; InterpreterData[] array = new InterpreterData[functionCount]; for (int i = 0; i != functionCount; i++) { - FunctionNode def = tree.getFunctionNode(i); + FunctionNode def = scriptOrFn.getFunctionNode(i); Interpreter jsi = new Interpreter(); + jsi.scriptOrFn = def; jsi.itsSourceFile = itsSourceFile; jsi.itsData = new InterpreterData(itsData.securityDomain); jsi.itsData.itsCheckThis = def.getCheckThis(); - jsi.itsData.itsFunctionType = def.getFunctionType(); jsi.itsInFunctionFlag = true; jsi.debugSource = debugSource; - jsi.generateFunctionICode(cx, scope, def); + jsi.generateFunctionICode(cx, scope); array[i] = jsi.itsData; - def.putIntProp(Node.FUNCTION_PROP, i); } itsData.itsNestedFunctions = array; } - private void generateRegExpLiterals(Context cx, - Scriptable scope, - ScriptOrFnNode tree) + private void generateRegExpLiterals(Context cx, Scriptable scope) { - int N = tree.getRegexpCount(); + int N = scriptOrFn.getRegexpCount(); if (N == 0) return; RegExpProxy rep = cx.getRegExpProxy(); @@ -180,8 +175,8 @@ public class Interpreter { } Object[] array = new Object[N]; for (int i = 0; i != N; i++) { - String string = tree.getRegexpString(i); - String flags = tree.getRegexpFlags(i); + String string = scriptOrFn.getRegexpString(i); + String flags = scriptOrFn.getRegexpFlags(i); array[i] = rep.newRegExp(cx, scope, string, flags, false); } itsData.itsRegExpLiterals = array; @@ -265,16 +260,15 @@ public class Interpreter { switch (type) { case TokenStream.FUNCTION : { - FunctionNode fn - = (FunctionNode) node.getProp(Node.FUNCTION_PROP); + int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); + FunctionNode fn = scriptOrFn.getFunctionNode(fnIndex); if (fn.itsFunctionType != FunctionNode.FUNCTION_STATEMENT) { // 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 - int index = fn.getExistingIntProp(Node.FUNCTION_PROP); iCodeTop = addByte(TokenStream.CLOSURE, iCodeTop); - iCodeTop = addIndex(index, iCodeTop); + iCodeTop = addIndex(fnIndex, iCodeTop); itsStackDepth++; if (itsStackDepth > itsData.itsMaxStack) itsData.itsMaxStack = itsStackDepth; @@ -2891,6 +2885,7 @@ public class Interpreter { private boolean itsInFunctionFlag; private InterpreterData itsData; + private ScriptOrFnNode scriptOrFn; private VariableTable itsVariableTable; private int itsTryDepth = 0; private int itsStackDepth = 0; diff --git a/mozilla/js/rhino/src/org/mozilla/javascript/NodeTransformer.java b/mozilla/js/rhino/src/org/mozilla/javascript/NodeTransformer.java index 0408373644e..838b52cc791 100644 --- a/mozilla/js/rhino/src/org/mozilla/javascript/NodeTransformer.java +++ b/mozilla/js/rhino/src/org/mozilla/javascript/NodeTransformer.java @@ -109,8 +109,8 @@ public class NodeTransformer { case TokenStream.FUNCTION: if (node != tree) { - FunctionNode - fnNode = (FunctionNode)node.getProp(Node.FUNCTION_PROP); + int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); + FunctionNode fnNode = tree.getFunctionNode(fnIndex); if (inFunction) { // Functions containing other functions require // activation objects @@ -123,8 +123,7 @@ public class NodeTransformer { } NodeTransformer inner = newInstance(); fnNode = (FunctionNode)inner.transform(fnNode); - node.putProp(Node.FUNCTION_PROP, fnNode); - tree.addFunction(fnNode); + tree.replaceFunctionNode(fnIndex, fnNode); } break; diff --git a/mozilla/js/rhino/src/org/mozilla/javascript/Parser.java b/mozilla/js/rhino/src/org/mozilla/javascript/Parser.java index 073d7871108..79e27beb51e 100644 --- a/mozilla/js/rhino/src/org/mozilla/javascript/Parser.java +++ b/mozilla/js/rhino/src/org/mozilla/javascript/Parser.java @@ -98,10 +98,10 @@ class Parser { public ScriptOrFnNode parse(TokenStream ts) throws IOException { + currentScriptOrFn = nf.createScript(); + this.ok = true; fn_sourceTop = 0; - fn_functionNumber = 0; - fn_vars = new VariableTable(); fn_funcExprStmNames = null; int tt; // last token from getToken(); @@ -145,8 +145,10 @@ class Parser { String source = sourceToString(0); sourceBuffer = null; // To help GC - return nf.createScript(pn, fn_vars, ts.getSourceName(), - baseLineno, ts.getLineno(), source); + + nf.initScript(currentScriptOrFn, pn, ts.getSourceName(), + baseLineno, ts.getLineno(), source); + return currentScriptOrFn; } /* @@ -203,16 +205,16 @@ class Parser { // by '(', assume starts memberExpr sourceAddString(ts.NAME, name); Object memberExprHead = nf.createName(name); - name = null; + name = ""; memberExprNode = memberExprTail(ts, false, memberExprHead); } mustMatchToken(ts, ts.LP, "msg.no.paren.parms"); } } else if (ts.matchToken(ts.LP)) { // Anonymous function - name = null; + name = ""; } else { - name = null; + name = ""; if (allowMemberExprAsFunctionName) { // Note that memberExpr can not start with '(' like // in function (1+2).toString(), because 'function (' already @@ -229,29 +231,28 @@ class Parser { sourceAdd((char)ts.NOP); } + FunctionNode fnNode = nf.createFunction(name); + int functionIndex = currentScriptOrFn.addFunction(fnNode); + // save a reference to the function in the enclosing source. sourceAdd((char) ts.FUNCTION); - sourceAdd((char)fn_functionNumber); - ++fn_functionNumber; + sourceAdd((char)functionIndex); // Save current source top to restore it on exit not to include // function to parent source int saved_sourceTop = fn_sourceTop; - int saved_functionNumber = fn_functionNumber; - VariableTable saved_vars = fn_vars; - VariableTable new_vars = new VariableTable(); ObjArray saved_funcExprStmNames = fn_funcExprStmNames; + + ScriptOrFnNode savedScriptOrFn = currentScriptOrFn; + currentScriptOrFn = fnNode; Object body; String source; try { - fn_functionNumber = 0; - fn_vars = new_vars; - // FUNCTION as the first token in a Source means it's a function // definition, and not a reference. sourceAdd((char) ts.FUNCTION); - if (name != null) { sourceAddString(ts.NAME, name); } + if (name.length() != 0) { sourceAddString(ts.NAME, name); } sourceAdd((char) ts.LP); if (!ts.matchToken(ts.RP)) { @@ -262,11 +263,11 @@ class Parser { first = false; mustMatchToken(ts, ts.NAME, "msg.no.parm"); String s = ts.getString(); - if (new_vars.hasVariable(s)) { + if (fnNode.hasParameterOrVar(s)) { Object[] msgArgs = { s }; ts.reportCurrentLineWarning("msg.dup.parms", msgArgs); } - new_vars.addParameter(s); + fnNode.addParameter(s); sourceAddString(ts.NAME, s); } while (ts.matchToken(ts.COMMA)); @@ -286,26 +287,25 @@ class Parser { source = sourceToString(saved_sourceTop); // Remove name clashes for nested functions - checkVariables(new_vars, fn_funcExprStmNames); + checkVariables(fnNode, fn_funcExprStmNames); } finally { fn_sourceTop = saved_sourceTop; - fn_functionNumber = saved_functionNumber; - fn_vars = saved_vars; fn_funcExprStmNames = saved_funcExprStmNames; + currentScriptOrFn = savedScriptOrFn; } Object pn; if (memberExprNode == null) { - pn = nf.createFunction(name, new_vars, body, - ts.getSourceName(), - baseLineno, ts.getLineno(), - source, - functionType); + pn = nf.initFunction(fnNode, functionIndex, body, + ts.getSourceName(), + baseLineno, ts.getLineno(), + source, + functionType); if (functionType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) { // Record the name to check for possible var and // function expression statement name clashes - if (name != null && name.length()!= 0) { + if (name.length()!= 0) { if (fn_funcExprStmNames == null) { fn_funcExprStmNames = new ObjArray(); } @@ -323,11 +323,11 @@ class Parser { checkWellTerminatedFunction(ts); } } else { - pn = nf.createFunction(name, new_vars, body, - ts.getSourceName(), - baseLineno, ts.getLineno(), - source, - FunctionNode.FUNCTION_EXPRESSION); + pn = nf.initFunction(fnNode, functionIndex, body, + ts.getSourceName(), + baseLineno, ts.getLineno(), + source, + FunctionNode.FUNCTION_EXPRESSION); pn = nf.createBinary(ts.ASSIGN, ts.NOP, memberExprNode, pn); if (functionType != FunctionNode.FUNCTION_EXPRESSION) { pn = nf.createExprStatement(pn, baseLineno); @@ -342,14 +342,14 @@ class Parser { } private static void - checkVariables(VariableTable vars, ObjArray funcExprStmNames) + checkVariables(ScriptOrFnNode scriptOrFn, ObjArray funcExprStmNames) { // Remove all variables corresponding to function expression statements if (funcExprStmNames != null) { int N = funcExprStmNames.size(); for (int i = 0; i != N; ++i) { String name = (String)funcExprStmNames.get(i); - vars.removeLocal(name); + scriptOrFn.removeParameterOrVar(name); } } } @@ -909,7 +909,7 @@ class Parser { first = false; sourceAddString(ts.NAME, s); - fn_vars.addLocal(s); + currentScriptOrFn.addVar(s); name = nf.createName(s); // omitted check for argument hiding @@ -1810,15 +1810,15 @@ class Parser { */ ++i; - int functionNumber = source.charAt(i); + int functionIndex = source.charAt(i); if (childNodes == null - || functionNumber + 1 > childNodes.length) + || functionIndex + 1 > childNodes.length) { throw Context.reportRuntimeError(Context.getMessage1 ("msg.no.function.ref.found", - new Integer(functionNumber))); + new Integer(functionIndex))); } - decompile_r(childNodes[functionNumber + 1], version, + decompile_r(childNodes[functionIndex + 1], version, indent, NESTED_FUNCTION, false, srcData, result); break; } @@ -2306,13 +2306,10 @@ class Parser { // included in parent. private int fn_sourceTop; -// Nested function number - private int fn_functionNumber; - // Nested function number private ObjArray fn_funcExprStmNames; - private VariableTable fn_vars; + private ScriptOrFnNode currentScriptOrFn; private static final int TOP_LEVEL_SCRIPT_OR_FUNCTION = 0; private static final int CONSTRUCTED_FUNCTION = 1; diff --git a/mozilla/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java b/mozilla/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java index d8854988e8e..bf08e8408b4 100644 --- a/mozilla/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java +++ b/mozilla/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java @@ -41,7 +41,10 @@ public class ScriptOrFnNode extends Node { super(nodeType); } - public final VariableTable getVariableTable() { return variableTable; } + public final VariableTable getVariableTable() { + if (variableTable == null) { variableTable = new VariableTable(); } + return variableTable; + } public final String getSourceName() { return sourceName; } @@ -95,7 +98,7 @@ public class ScriptOrFnNode extends Node { if (fnNode == null) Context.codeBug(); if (functions == null) { functions = new ObjArray(); } functions.add(fnNode); - return functions.size(); + return functions.size() - 1; } public final int getRegexpCount() { @@ -116,7 +119,27 @@ public class ScriptOrFnNode extends Node { if (regexps == null) { regexps = new ObjArray(); } regexps.add(string); regexps.add(flags); - return (regexps.size() - 2) / 2; + return regexps.size() / 2 - 1; + } + + public final boolean hasParameterOrVar(String name) { + if (variableTable == null) { return false; } + return variableTable.hasVariable(name); + } + + public final void addParameter(String name) { + if (variableTable == null) { variableTable = new VariableTable(); } + variableTable.addParameter(name); + } + + public final void addVar(String name) { + if (variableTable == null) { variableTable = new VariableTable(); } + variableTable.addLocal(name); + } + + public final void removeParameterOrVar(String name) { + if (variableTable == null) { return; } + variableTable.removeLocal(name); } public final int getLocalCount() { return localCount; } @@ -125,7 +148,6 @@ public class ScriptOrFnNode extends Node { ++localCount; } - VariableTable variableTable; private String encodedSource; private String originalSource; private String sourceName; @@ -133,6 +155,7 @@ public class ScriptOrFnNode extends Node { private int endLineno = -1; private ObjArray functions; private ObjArray regexps; + private VariableTable variableTable; private int localCount; } diff --git a/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java b/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java index 108ec1a6cb1..3baf798bdfe 100644 --- a/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java +++ b/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java @@ -89,12 +89,12 @@ public class Codegen extends Interpreter { } public Object - compile(Context cx, Scriptable scope, ScriptOrFnNode tree, + compile(Context cx, Scriptable scope, ScriptOrFnNode scriptOrFn, SecurityController securityController, Object securityDomain) { ObjArray classFiles = new ObjArray(); ObjArray names = new ObjArray(); - generateCode(tree, names, classFiles); + generateCode(scriptOrFn, names, classFiles); String generatedName = name; boolean onlySave = false; @@ -120,12 +120,12 @@ public class Codegen extends Interpreter { if (interfaces != null || superClass != null) { String adapterClassName = getScriptClassName(null, true); ScriptableObject obj = new NativeObject(); - for (Node cursor = tree.getFirstChild(); cursor != null; - cursor = cursor.getNext()) - { - if (cursor.getType() == TokenStream.FUNCTION) { - FunctionNode fn - = (FunctionNode)cursor.getProp(Node.FUNCTION_PROP); + int functionCount = scriptOrFn.getFunctionCount(); + for (int i = 0; i != functionCount; ++i) { + OptFunctionNode fn; + fn = (OptFunctionNode)scriptOrFn.getFunctionNode(i); + String name = fn.getFunctionName(); + if (name != null && name.length() != 0) { obj.put(fn.getFunctionName(), obj, fn); } } @@ -184,7 +184,7 @@ public class Codegen extends Interpreter { if (e != null) throw new RuntimeException("Malformed optimizer package " + e); - if (tree instanceof OptFunctionNode) { + if (scriptOrFn instanceof OptFunctionNode) { NativeFunction f; try { Constructor ctor = result.getConstructors()[0]; @@ -383,15 +383,14 @@ public class Codegen extends Interpreter { } private String - generateCode(ScriptOrFnNode tree, ObjArray names, ObjArray classFiles) + generateCode(ScriptOrFnNode scriptOrFn, ObjArray names, ObjArray classFiles) { - int functionCount = tree.getFunctionCount(); - if (functionCount != 0) { - for (int i = 0; i != functionCount; ++i) { - OptFunctionNode fn = (OptFunctionNode)tree.getFunctionNode(i); - Codegen codegen = new Codegen(this); - codegen.generateCode(fn, names, classFiles); - } + this.scriptOrFn = scriptOrFn; + int functionCount = scriptOrFn.getFunctionCount(); + for (int i = 0; i != functionCount; ++i) { + OptFunctionNode fn = (OptFunctionNode)scriptOrFn.getFunctionNode(i); + Codegen codegen = new Codegen(this); + codegen.generateCode(fn, names, classFiles); } Context cx = Context.getCurrentContext(); @@ -400,11 +399,11 @@ public class Codegen extends Interpreter { itsSourceFile = null; // default is to generate debug info if (!cx.isGeneratingDebugChanged() || cx.isGeneratingDebug()) { - itsSourceFile = tree.getSourceName(); + itsSourceFile = scriptOrFn.getSourceName(); } version = cx.getLanguageVersion(); optLevel = cx.getOptimizationLevel(); - inFunction = tree.getType() == TokenStream.FUNCTION; + inFunction = scriptOrFn.getType() == TokenStream.FUNCTION; superClassName = inFunction ? functionSuperClassName : scriptSuperClassName; @@ -412,13 +411,13 @@ public class Codegen extends Interpreter { Node codegenBase; if (inFunction) { - fnCurrent = (OptFunctionNode)tree; + fnCurrent = (OptFunctionNode)scriptOrFn; inDirectCallFunction = fnCurrent.isTargetOfDirectCall(); vars = fnCurrent.getVariableTable(); this.name = fnCurrent.getClassName(); classFile = new ClassFileWriter(name, superClassName, itsSourceFile); String name = fnCurrent.getFunctionName(); - generateInit(cx, "", tree, name); + generateInit(cx, "", name); if (fnCurrent.isTargetOfDirectCall()) { classFile.startMethod("call", "(Lorg/mozilla/javascript/Context;" + @@ -484,7 +483,7 @@ public class Codegen extends Interpreter { markLabel(isObjectLabel); } } - generatePrologue(cx, tree, true, vars.getParameterCount()); + generatePrologue(cx, true, vars.getParameterCount()); } else { startNewMethod("call", "(Lorg/mozilla/javascript/Context;" + @@ -492,22 +491,22 @@ public class Codegen extends Interpreter { "Lorg/mozilla/javascript/Scriptable;" + "[Ljava/lang/Object;)Ljava/lang/Object;", 1, false, true); - generatePrologue(cx, tree, true, -1); + generatePrologue(cx, true, -1); } - codegenBase = tree.getLastChild(); + codegenBase = scriptOrFn.getLastChild(); } else { // better be a script - if (tree.getType() != TokenStream.SCRIPT) + if (scriptOrFn.getType() != TokenStream.SCRIPT) badTree(); - vars = tree.getVariableTable(); + vars = scriptOrFn.getVariableTable(); boolean isPrimary = nameHelper.getTargetExtends() == null && nameHelper.getTargetImplements() == null; this.name = getScriptClassName(null, isPrimary); classFile = new ClassFileWriter(name, superClassName, itsSourceFile); classFile.addInterface("org/mozilla/javascript/Script"); - generateScriptCtor(cx, tree); + generateScriptCtor(cx); generateMain(cx); - generateInit(cx, "initScript", tree, ""); + generateInit(cx, "initScript", ""); generateExecute(cx); startNewMethod("call", "(Lorg/mozilla/javascript/Context;" + @@ -515,12 +514,12 @@ public class Codegen extends Interpreter { "Lorg/mozilla/javascript/Scriptable;" + "[Ljava/lang/Object;)Ljava/lang/Object;", 1, false, true); - generatePrologue(cx, tree, false, -1); - int linenum = tree.getEndLineno(); + generatePrologue(cx, false, -1); + int linenum = scriptOrFn.getEndLineno(); if (linenum != -1) classFile.addLineNumberEntry((short)linenum); - tree.addChildToBack(new Node(TokenStream.RETURN)); - codegenBase = tree; + scriptOrFn.addChildToBack(new Node(TokenStream.RETURN)); + codegenBase = scriptOrFn; } generateCodeFromNode(codegenBase, null, -1, -1); @@ -591,8 +590,9 @@ public class Codegen extends Interpreter { case TokenStream.FUNCTION: if (inFunction || parent.getType() != TokenStream.SCRIPT) { - OptFunctionNode fn - = (OptFunctionNode) node.getProp(Node.FUNCTION_PROP); + int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); + OptFunctionNode fn; + fn = (OptFunctionNode)scriptOrFn.getFunctionNode(fnIndex); int t = fn.getFunctionType(); if (t != FunctionNode.FUNCTION_STATEMENT) { visitFunction(fn, t); @@ -1085,7 +1085,7 @@ public class Codegen extends Interpreter { finishMethod(cx, null); } - private void generateScriptCtor(Context cx, Node tree) { + private void generateScriptCtor(Context cx) { startNewMethod("", "()V", 1, false, false); addByteCode(ByteCode.ALOAD_0); addSpecialInvoke(superClassSlashName, @@ -1114,12 +1114,11 @@ public class Codegen extends Interpreter { contextLocal = reserveWordLocal(2); // reserve 2 for 'context' } - private void generateInit(Context cx, String methodName, - ScriptOrFnNode tree, String name) + private void generateInit(Context cx, String methodName, String name) { trivialInit = true; boolean inCtor = false; - VariableTable vars = tree.getVariableTable(); + VariableTable vars = scriptOrFn.getVariableTable(); if (methodName.equals("")) { inCtor = true; setNonTrivialInit(methodName); @@ -1190,13 +1189,13 @@ public class Codegen extends Interpreter { } // precompile all regexp literals - int regexpCount = tree.getRegexpCount(); + int regexpCount = scriptOrFn.getRegexpCount(); if (regexpCount != 0) { setNonTrivialInit(methodName); - generateRegExpLiterals(tree, inCtor); + generateRegExpLiterals(inCtor); } - if (tree instanceof OptFunctionNode) { + if (scriptOrFn instanceof OptFunctionNode) { if (fnCurrent.isTargetOfDirectCall()) { setNonTrivialInit(methodName); @@ -1227,7 +1226,7 @@ public class Codegen extends Interpreter { // Change Parser if changing ordering. if (cx.isGeneratingSource()) { - String source = tree.getEncodedSource(); + String source = scriptOrFn.getEncodedSource(); if (source != null && source.length() < 65536) { short flags = ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_STATIC; @@ -1235,7 +1234,7 @@ public class Codegen extends Interpreter { classFile.startMethod(getSourceMethodStr, "()Ljava/lang/Object;", (short)flags); - int functionCount = tree.getFunctionCount(); + int functionCount = scriptOrFn.getFunctionCount(); if (functionCount == 0) { // generate return ; push(source); @@ -1257,7 +1256,7 @@ public class Codegen extends Interpreter { OptFunctionNode fn; addByteCode(ByteCode.DUP); // dup array reference push(1 + i); - fn = (OptFunctionNode)tree.getFunctionNode(i); + fn = (OptFunctionNode)scriptOrFn.getFunctionNode(i); classFile.add(ByteCode.INVOKESTATIC, fn.getClassName(), getSourceMethodStr, @@ -1272,8 +1271,8 @@ public class Codegen extends Interpreter { } } - private void generateRegExpLiterals(ScriptOrFnNode tree, boolean inCtor) { - int regexpCount = tree.getRegexpCount(); + private void generateRegExpLiterals(boolean inCtor) { + int regexpCount = scriptOrFn.getRegexpCount(); for (int i=0; i < regexpCount; i++) { String fieldName = getRegexpFieldName(i); short flags = ClassFileWriter.ACC_PRIVATE; @@ -1289,8 +1288,8 @@ public class Codegen extends Interpreter { aload(contextLocal); // load 'context' aload(variableObjectLocal); // load 'scope' - push(tree.getRegexpString(i)); - String regexpFlags = tree.getRegexpFlags(i); + push(scriptOrFn.getRegexpString(i)); + String regexpFlags = scriptOrFn.getRegexpFlags(i); if (regexpFlags == null) { addByteCode(ByteCode.ACONST_NULL); } else { @@ -1318,15 +1317,13 @@ public class Codegen extends Interpreter { * Generate the prologue for a function or script. * * @param cx the context - * @param tree the tree to generate code for * @param inFunction true if generating the prologue for a function * (as opposed to a script) * @param directParameterCount number of parameters for direct call, * or -1 if not direct call */ private void - generatePrologue(Context cx, ScriptOrFnNode tree, boolean inFunction, - int directParameterCount) + generatePrologue(Context cx, boolean inFunction, int directParameterCount) { funObjLocal = reserveWordLocal(0); contextLocal = reserveWordLocal(1); @@ -1358,7 +1355,7 @@ public class Codegen extends Interpreter { // These locals are to be pre-allocated since they need function scope. // They are primarily used by the exception handling mechanism - int localCount = tree.getLocalCount(); + int localCount = scriptOrFn.getLocalCount(); if (localCount != 0) { itsLocalAllocationBase = (short)(argsLocal + 1); for (int i = 0; i < localCount; i++) { @@ -1366,7 +1363,7 @@ public class Codegen extends Interpreter { } } - if (inFunction && ((OptFunctionNode)tree).getCheckThis()) { + if (inFunction && ((OptFunctionNode)scriptOrFn).getCheckThis()) { // Nested functions must check their 'this' value to // insure it is not an activation object: // see 10.1.6 Activation Object @@ -1378,7 +1375,7 @@ public class Codegen extends Interpreter { } hasVarsInRegs = inFunction && - !((OptFunctionNode)tree).requiresActivation(); + !((OptFunctionNode)scriptOrFn).requiresActivation(); if (hasVarsInRegs) { // No need to create activation. Pad arguments if need be. int parmCount = vars.getParameterCount(); @@ -1489,18 +1486,15 @@ public class Codegen extends Interpreter { } astore(variableObjectLocal); - int functionCount = tree.getFunctionCount(); - if (functionCount != 0) { - for (int i=0; i < functionCount; i++) { - OptFunctionNode fn = (OptFunctionNode)tree.getFunctionNode(i); - if (fn.getFunctionType() == FunctionNode.FUNCTION_STATEMENT) { - visitFunction(fn, FunctionNode.FUNCTION_STATEMENT); - addByteCode(ByteCode.POP); - } + int functionCount = scriptOrFn.getFunctionCount(); + for (int i = 0; i != functionCount; i++) { + OptFunctionNode fn = (OptFunctionNode)scriptOrFn.getFunctionNode(i); + if (fn.getFunctionType() == FunctionNode.FUNCTION_STATEMENT) { + visitFunction(fn, FunctionNode.FUNCTION_STATEMENT); + addByteCode(ByteCode.POP); } } - // default is to generate debug info if (!cx.isGeneratingDebugChanged() || cx.isGeneratingDebug()) { OptLocalVariable lv = new OptLocalVariable(debugVariableName, @@ -1519,15 +1513,15 @@ public class Codegen extends Interpreter { astore(scriptResultLocal); } - if (inFunction && ((OptFunctionNode)tree).containsCalls(-1)) { - if (((OptFunctionNode)tree).containsCalls(0)) { + if (inFunction && ((OptFunctionNode)scriptOrFn).containsCalls(-1)) { + if (((OptFunctionNode)scriptOrFn).containsCalls(0)) { itsZeroArgArray = getNewWordLocal(); classFile.add(ByteCode.GETSTATIC, "org/mozilla/javascript/ScriptRuntime", "emptyArgs", "[Ljava/lang/Object;"); astore(itsZeroArgArray); } - if (((OptFunctionNode)tree).containsCalls(1)) { + if (((OptFunctionNode)scriptOrFn).containsCalls(1)) { itsOneArgArray = getNewWordLocal(); push(1); addByteCode(ByteCode.ANEWARRAY, "java/lang/Object"); @@ -3770,6 +3764,7 @@ public class Codegen extends Interpreter { private short itsZeroArgArray; private short itsOneArgArray; + private ScriptOrFnNode scriptOrFn; private OptFunctionNode fnCurrent; private boolean itsUseDynamicScope; private boolean hasVarsInRegs; diff --git a/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java b/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java index 81d337af872..aa71ad868cd 100644 --- a/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java +++ b/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java @@ -59,16 +59,15 @@ class OptTransformer extends NodeTransformer { return new OptTransformer(irFactory, listCopy); } - public ScriptOrFnNode transform(ScriptOrFnNode tree) { + public ScriptOrFnNode transform(ScriptOrFnNode scriptOrFn) { // Collect all of the script contained functions into a hashtable // so that the call optimizer can access the class name & parameter // count for any call it encounters - if (tree.getType() == TokenStream.SCRIPT) { - collectContainedFunctions(tree.getFirstChild()); + if (scriptOrFn.getType() == TokenStream.SCRIPT) { + collectContainedFunctions(scriptOrFn); } - - return super.transform(tree); + return super.transform(scriptOrFn); } private int detectDirectCall(Node node, ScriptOrFnNode tree) @@ -151,21 +150,14 @@ class OptTransformer extends NodeTransformer { * so that the call optimizer can access the class name & parameter * count for any call it encounters */ - private void collectContainedFunctions(Node node) { - for (Node tNode=node; tNode != null; tNode = tNode.getNext()) { - if (tNode.getType() == TokenStream.FUNCTION) { - FunctionNode - fnNode = (FunctionNode)tNode.getProp(Node.FUNCTION_PROP); - if (fnNode.getType() == FunctionNode.FUNCTION_STATEMENT) { - String name = fnNode.getFunctionName(); - if (name.length() != 0) { - Object oldFn = theFnClassNameList.get(name); - if (oldFn == fnNode) { - // already processed this list of functions - return; - } - theFnClassNameList.put(name, fnNode); - } + private void collectContainedFunctions(ScriptOrFnNode scriptOrFn) { + int functionCount = scriptOrFn.getFunctionCount(); + for (int i = 0; i != functionCount; ++i) { + OptFunctionNode f = (OptFunctionNode)scriptOrFn.getFunctionNode(i); + if (f.getType() == FunctionNode.FUNCTION_STATEMENT) { + String name = f.getFunctionName(); + if (name.length() != 0) { + theFnClassNameList.put(name, f); } } } diff --git a/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java b/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java index c3aac64e971..83fcadd4b01 100644 --- a/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java +++ b/mozilla/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java @@ -53,21 +53,14 @@ class Optimizer { this.irFactory = irFactory; } - void optimize(Node tree, int optLevel) + void optimize(ScriptOrFnNode scriptOrFn, int optLevel) { itsOptLevel = optLevel; // run on one function at a time for now - PreorderNodeIterator iter = new PreorderNodeIterator(); - for (iter.start(tree); !iter.done(); iter.next()) { - // should be able to do this more cheaply ? - // - run through initial block children ? - Node node = iter.getCurrent(); - if (node.getType() == TokenStream.FUNCTION) { - OptFunctionNode theFunction = (OptFunctionNode) - node.getProp(Node.FUNCTION_PROP); - if (theFunction != null) - optimizeFunction(theFunction); - } + int functionCount = scriptOrFn.getFunctionCount(); + for (int i = 0; i != functionCount; ++i) { + OptFunctionNode f = (OptFunctionNode)scriptOrFn.getFunctionNode(i); + optimizeFunction(f); } }