Eliminate double creation of Function objects representing nested functions in scripts/functions and use ScriptRutime.putFunction to bind function objects with activation scope.

This commit is contained in:
igor%mir2.org 2002-12-22 22:39:10 +00:00
Родитель a51906cdd3
Коммит 508aa98e62
2 изменённых файлов: 42 добавлений и 111 удалений

Просмотреть файл

@ -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 <source-literal-string>;
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, "<init>",
"(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;

Просмотреть файл

@ -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);
}
}