From 508aa98e622c54c7a4f5f819536f2356dc0fb015 Mon Sep 17 00:00:00 2001 From: "igor%mir2.org" Date: Sun, 22 Dec 2002 22:39:10 +0000 Subject: [PATCH] Eliminate double creation of Function objects representing nested functions in scripts/functions and use ScriptRutime.putFunction to bind function objects with activation scope. --- .../mozilla/javascript/optimizer/Codegen.java | 132 ++++++------------ .../javascript/optimizer/OptRuntime.java | 21 +-- 2 files changed, 42 insertions(+), 111 deletions(-) diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java index 79a55de83630..e11b173cf7ac 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java @@ -70,12 +70,14 @@ public class Codegen extends Interpreter { public Object compile(Context cx, Scriptable scope, Node tree, Object securityDomain, SecurityController securityController, - ClassNameHelper nameHelper) + ClassNameHelper cnh) { ObjArray classFiles = new ObjArray(); ObjArray names = new ObjArray(); String generatedName = null; + OptClassNameHelper nameHelper = (OptClassNameHelper) cnh; + Exception e = null; Class result = null; DefiningClassLoader classLoader = null; @@ -134,29 +136,28 @@ public class Codegen extends Interpreter { if (e != null) throw new RuntimeException("Malformed optimizer package " + e); - OptClassNameHelper onh = (OptClassNameHelper) nameHelper; - if (onh.getTargetImplements() != null || - onh.getTargetExtends() != null) - { - String name = onh.getJavaScriptClassName(null, true); + Class[] interfaces = nameHelper.getTargetImplements(); + Class superClass = nameHelper.getTargetExtends(); + if (interfaces != null || superClass != null) { + String name = nameHelper.getJavaScriptClassName(null, true); ScriptableObject obj = new NativeObject(); for (Node cursor = tree.getFirstChild(); cursor != null; cursor = cursor.getNext()) { if (cursor.getType() == TokenStream.FUNCTION) { - obj.put(cursor.getString(), obj, - cursor.getProp(Node.FUNCTION_PROP)); + OptFunctionNode fnNode + = (OptFunctionNode)cursor.getProp(Node.FUNCTION_PROP); + obj.put(fnNode.getFunctionName(), obj, fnNode); } } + if (superClass == null) + superClass = Object.class; try { - Class superClass = onh.getTargetExtends(); - if (superClass == null) - superClass = Object.class; JavaAdapter.createAdapterClass(cx, obj, name, superClass, - onh.getTargetImplements(), + interfaces, generatedName, - onh); + nameHelper); } catch (ClassNotFoundException exn) { // should never happen throw new Error(exn.toString()); @@ -174,7 +175,8 @@ public class Codegen extends Interpreter { throw new RuntimeException ("Unable to instantiate compiled class:"+ex.toString()); } - OptRuntime.setupFunction(f, scope, true); + OptFunctionNode fnNode = (OptFunctionNode)tree; + OptRuntime.setupFunction(f, scope, fnNode.getFunctionType()); return f; } else { NativeScript script; @@ -374,11 +376,17 @@ public class Codegen extends Interpreter { } public String generateCode(Node tree, ObjArray names, ObjArray classFiles, - ClassNameHelper nameHelper) + OptClassNameHelper nameHelper) { - this.itsNameHelper = (OptClassNameHelper) nameHelper; - this.namesVector = names; - this.classFilesVector = classFiles; + ObjArray fns = (ObjArray) tree.getProp(Node.FUNCTION_PROP); + if (fns != null) { + for (int i = 0; i != fns.size(); ++i) { + OptFunctionNode fn = (OptFunctionNode) fns.get(i); + Codegen codegen = new Codegen(); + codegen.generateCode(fn, names, classFiles, nameHelper); + } + } + Context cx = Context.getCurrentContext(); itsUseDynamicScope = cx.hasCompileFunctionsWithDynamicScope(); @@ -411,7 +419,7 @@ public class Codegen extends Interpreter { "Lorg/mozilla/javascript/Scriptable;" + "[Ljava/lang/Object;)Ljava/lang/Object;", (short)(ClassFileWriter.ACC_PUBLIC - + ClassFileWriter.ACC_FINAL)); + | ClassFileWriter.ACC_FINAL)); addByteCode(ByteCode.ALOAD_0); addByteCode(ByteCode.ALOAD_1); addByteCode(ByteCode.ALOAD_2); @@ -485,9 +493,9 @@ public class Codegen extends Interpreter { if (tree.getType() != TokenStream.SCRIPT) badTree(); vars = (VariableTable) tree.getProp(Node.VARS_PROP); - boolean isPrimary = itsNameHelper.getTargetExtends() == null && - itsNameHelper.getTargetImplements() == null; - this.name = itsNameHelper.getJavaScriptClassName(null, isPrimary); + boolean isPrimary = nameHelper.getTargetExtends() == null && + nameHelper.getTargetImplements() == null; + this.name = nameHelper.getJavaScriptClassName(null, isPrimary); classFile = new ClassFileWriter(name, superClassName, itsSourceFile); classFile.addInterface("org/mozilla/javascript/Script"); generateScriptCtor(cx, tree); @@ -518,12 +526,10 @@ public class Codegen extends Interpreter { byte[] bytes = classFile.toByteArray(); - namesVector.add(name); - classFilesVector.add(bytes); + names.add(name); + classFiles.add(bytes); classFile = null; - namesVector = null; - classFilesVector = null; return name; } @@ -582,7 +588,7 @@ public class Codegen extends Interpreter { = (OptFunctionNode) node.getProp(Node.FUNCTION_PROP); int t = fn.getFunctionType(); if (t != FunctionNode.FUNCTION_STATEMENT) { - visitFunction(fn, t == FunctionNode.FUNCTION_EXPRESSION_STATEMENT); + visitFunction(fn, t); } } break; @@ -1185,18 +1191,6 @@ public class Codegen extends Interpreter { generateRegExpLiterals(regexps, inCtor); } - ObjArray fns = (ObjArray) tree.getProp(Node.FUNCTION_PROP); - if (fns != null) { - setNonTrivialInit(methodName); - for (int i = 0; i != fns.size(); ++i) { - OptFunctionNode fn = (OptFunctionNode) fns.get(i); - Codegen codegen = new Codegen(); - codegen.generateCode(fn, namesVector, classFilesVector, - itsNameHelper); - generateCreateFunction(fn); - } - } - if (tree instanceof OptFunctionNode) { OptFunctionNode fnNode = (OptFunctionNode)tree; @@ -1237,6 +1231,7 @@ public class Codegen extends Interpreter { classFile.startMethod(getSourceMethodStr, "()Ljava/lang/Object;", (short)flags); + ObjArray fns = (ObjArray) tree.getProp(Node.FUNCTION_PROP); if (fns == null) { // generate return ; push(source); @@ -1316,52 +1311,6 @@ public class Codegen extends Interpreter { } } - // On exit it leaves on stack new function - private void generateCreateFunction(OptFunctionNode fn) { - String fnClassName = fn.getClassName(); - addByteCode(ByteCode.NEW, fnClassName); - addByteCode(ByteCode.DUP); - if (inFunction) { - addByteCode(ByteCode.ALOAD_0); // load "this" argument - } else { - aload(variableObjectLocal); - } - aload(contextLocal); // load 'cx' - addSpecialInvoke(fnClassName, "", - "(Lorg/mozilla/javascript/Scriptable;" + - "Lorg/mozilla/javascript/Context;)", - "V"); - - // 'fn' still on stack, dup it to use later - addByteCode(ByteCode.DUP); - // load 'scope' - if (inFunction) { - addByteCode(ByteCode.ALOAD_0); // load "this" argument - } else { - aload(variableObjectLocal); - } - // load 'fnName' - String str = fn.getFunctionName(); - if (str != null) { - push(str); - } else { - addByteCode(ByteCode.ACONST_NULL); - } - // load boolean indicating whether fn name should be set in scope - boolean setFnName = str != null && str.length() > 0 && - fn.getFunctionType() == - FunctionNode.FUNCTION_STATEMENT; - addByteCode(setFnName ? ByteCode.ICONST_1 : ByteCode.ICONST_0); - - addOptRuntimeInvoke("initFunction", - "(Lorg/mozilla/javascript/NativeFunction;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +"Z)", - "V"); - } - - /** * Generate the prologue for a function or script. * @@ -1537,11 +1486,11 @@ public class Codegen extends Interpreter { astore(variableObjectLocal); ObjArray fns = (ObjArray) tree.getProp(Node.FUNCTION_PROP); - if (inFunction && fns != null) { + if (fns != null) { for (int i=0; i < fns.size(); i++) { OptFunctionNode fn = (OptFunctionNode) fns.get(i); if (fn.getFunctionType() == FunctionNode.FUNCTION_STATEMENT) { - visitFunction(fn, true); + visitFunction(fn, FunctionNode.FUNCTION_STATEMENT); addByteCode(ByteCode.POP); } } @@ -1597,7 +1546,7 @@ public class Codegen extends Interpreter { addByteCode(ByteCode.ARETURN); } - private void visitFunction(OptFunctionNode fn, boolean setName) { + private void visitFunction(OptFunctionNode fn, int functionType) { String fnClassName = fn.getClassName(); addByteCode(ByteCode.NEW, fnClassName); // Call function constructor @@ -1610,11 +1559,11 @@ public class Codegen extends Interpreter { "V"); addByteCode(ByteCode.DUP); // copy of function aload(variableObjectLocal); - push(setName ? 1 : 0); + push(functionType); addOptRuntimeInvoke("setupFunction", "(Lorg/mozilla/javascript/NativeFunction;" +"Lorg/mozilla/javascript/Scriptable;" - +"Z)", + +"I)", "V"); // leave on stack new function instance } @@ -3777,11 +3726,8 @@ public class Codegen extends Interpreter { boolean inFunction; boolean inDirectCallFunction; private ClassFileWriter classFile; - private ObjArray namesVector; - private ObjArray classFilesVector; private short scriptRuntimeIndex; private int version; - private OptClassNameHelper itsNameHelper; private String itsSourceFile; private int itsLineNumber; diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/OptRuntime.java b/js/rhino/src/org/mozilla/javascript/optimizer/OptRuntime.java index 40f8f6e30155..49caa9a6a050 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/OptRuntime.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/OptRuntime.java @@ -304,27 +304,12 @@ public final class OptRuntime extends ScriptRuntime { return result; } - public static void initFunction(NativeFunction fn, - Scriptable scope, - String fnName, - boolean setName) - { - initFunction(scope, fn); - if (setName) { - ScriptableObject.defineProperty(scope, fnName, fn, - ScriptableObject.PERMANENT); - } - } - public static void setupFunction(NativeFunction fn, Scriptable scope, - boolean setName) + int functionType) { ScriptRuntime.initFunction(scope, fn); - - String fnName = fn.getFunctionName(); - if (setName && fnName != null && fnName.length() != 0) { - ScriptableObject.putProperty(scope, fnName, fn); - } + ScriptRuntime.putFunction(scope, fn.getFunctionName(), fn, + functionType, false); } }