VariableTable changes toward removal of a separated NodeTransformer pass over the parser tree for variable initialization: the code to support a table of optimized variables for functions in the optimizer is moved to optimizer/OptFunctionNode and VariableTable holds only parameters/variables names now. It allowed to simplify VariableTable initialization in NodeTransformer.

This commit is contained in:
igor%mir2.org 2003-02-15 21:35:58 +00:00
Родитель 90c8869435
Коммит aab18156df
10 изменённых файлов: 196 добавлений и 206 удалений

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

@ -43,7 +43,6 @@ public class FunctionNode extends Node {
public FunctionNode(String name, Node statements) { public FunctionNode(String name, Node statements) {
super(TokenStream.FUNCTION, statements); super(TokenStream.FUNCTION, statements);
functionName = name; functionName = name;
itsVariableTable = new VariableTable();
} }
public String getFunctionName() { public String getFunctionName() {
@ -54,6 +53,13 @@ public class FunctionNode extends Node {
return itsVariableTable; return itsVariableTable;
} }
public void setVariableTable(VariableTable variableTable) {
// Can do it only once
if (variableTable == null) Context.codeBug();
if (itsVariableTable != null) Context.codeBug();
itsVariableTable = variableTable;
}
public boolean requiresActivation() { public boolean requiresActivation() {
return itsNeedsActivation; return itsNeedsActivation;
} }
@ -97,6 +103,10 @@ public class FunctionNode extends Node {
itsFunctionType = functionType; itsFunctionType = functionType;
} }
public int getParameterCount() {
return argNames.size();
}
protected VariableTable itsVariableTable; protected VariableTable itsVariableTable;
protected boolean itsNeedsActivation; protected boolean itsNeedsActivation;
protected boolean itsCheckThis; protected boolean itsCheckThis;

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

@ -230,8 +230,7 @@ public class Interpreter {
+ itsData.itsMaxTryDepth + itsData.itsMaxTryDepth
+ itsData.itsMaxStack; + itsData.itsMaxStack;
itsData.argNames = new String[itsVariableTable.size()]; itsData.argNames = itsVariableTable.getAllVariables();
itsVariableTable.getAllVariables(itsData.argNames);
itsData.argCount = itsVariableTable.getParameterCount(); itsData.argCount = itsVariableTable.getParameterCount();
} }

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

@ -64,8 +64,15 @@ public class NodeTransformer {
loops = new ObjArray(); loops = new ObjArray();
loopEnds = new ObjArray(); loopEnds = new ObjArray();
inFunction = tree.getType() == TokenStream.FUNCTION; inFunction = tree.getType() == TokenStream.FUNCTION;
VariableTable vars = new VariableTable();
if (!inFunction) { if (!inFunction) {
addVariables(tree, getVariableTable(tree)); addVariables(tree, vars);
tree.putProp(Node.VARS_PROP, vars);
} else {
FunctionNode fnNode = (FunctionNode)tree;
addParameters(fnNode, vars);
addVariables(tree, vars);
fnNode.setVariableTable(vars);
} }
irFactory = createIRFactory(ts, scope); irFactory = createIRFactory(ts, scope);
@ -82,11 +89,6 @@ public class NodeTransformer {
case TokenStream.FUNCTION: case TokenStream.FUNCTION:
if (node == tree) { if (node == tree) {
// Add the variables to variable table, the
// parameters were added earlier.
VariableTable vars = getVariableTable(tree);
addVariables(tree, vars);
// Add return to end if needed. // Add return to end if needed.
Node stmts = node.getLastChild(); Node stmts = node.getLastChild();
Node lastStmt = stmts.getLastChild(); Node lastStmt = stmts.getLastChild();
@ -109,7 +111,6 @@ public class NodeTransformer {
// see 10.1.6 Activation Object // see 10.1.6 Activation Object
fnNode.setCheckThis(true); fnNode.setCheckThis(true);
} }
addParameters(fnNode);
NodeTransformer inner = newInstance(); NodeTransformer inner = newInstance();
fnNode = (FunctionNode) fnNode = (FunctionNode)
inner.transform(fnNode, tree, ts, scope); inner.transform(fnNode, tree, ts, scope);
@ -435,7 +436,6 @@ public class NodeTransformer {
// use of "arguments" requires an activation object. // use of "arguments" requires an activation object.
((FunctionNode) tree).setRequiresActivation(true); ((FunctionNode) tree).setRequiresActivation(true);
} }
VariableTable vars = getVariableTable(tree);
if (vars.hasVariable(name)) { if (vars.hasVariable(name)) {
if (type == TokenStream.SETNAME) { if (type == TokenStream.SETNAME) {
node.setType(TokenStream.SETVAR); node.setType(TokenStream.SETVAR);
@ -477,7 +477,6 @@ public class NodeTransformer {
// Use of "arguments" requires an activation object. // Use of "arguments" requires an activation object.
((FunctionNode) tree).setRequiresActivation(true); ((FunctionNode) tree).setRequiresActivation(true);
} }
VariableTable vars = getVariableTable(tree);
if (vars.hasVariable(name)) { if (vars.hasVariable(name)) {
node.setType(TokenStream.GETVAR); node.setType(TokenStream.GETVAR);
} }
@ -520,7 +519,7 @@ public class NodeTransformer {
{ {
String name = cursor.getString(); String name = cursor.getString();
if (fNames == null || !fNames.has(name)) if (fNames == null || !fNames.has(name))
vars.addLocal(name, createVariableObject(name, false)); vars.addLocal(name);
} }
} }
if (inFunction) { if (inFunction) {
@ -534,7 +533,7 @@ public class NodeTransformer {
// ECMA Ch. 13. We add code to the beginning of the function // ECMA Ch. 13. We add code to the beginning of the function
// to initialize a local variable of the function's name // to initialize a local variable of the function's name
// to the function value. // to the function value.
vars.addLocal(name, createVariableObject(name, false)); vars.addLocal(name);
Node block = tree.getLastChild(); Node block = tree.getLastChild();
Node setFn = new Node(TokenStream.POP, Node setFn = new Node(TokenStream.POP,
new Node(TokenStream.SETVAR, new Node(TokenStream.SETVAR,
@ -546,22 +545,17 @@ public class NodeTransformer {
} }
} }
protected void addParameters(FunctionNode fnNode) { protected void addParameters(FunctionNode fnNode, VariableTable vars) {
VariableTable vars = fnNode.getVariableTable();
if (vars.getParameterCount() == 0) { if (vars.getParameterCount() == 0) {
ObjArray argNames = fnNode.argNames; ObjArray argNames = fnNode.argNames;
// Add parameters // Add parameters
for (int i = 0, N = argNames.size(); i != N; ++i) { for (int i = 0, N = argNames.size(); i != N; ++i) {
String arg = (String)argNames.get(i); String arg = (String)argNames.get(i);
vars.addParameter(arg, createVariableObject(arg, true)); vars.addParameter(arg);
} }
} }
} }
protected Object createVariableObject(String name, boolean isParameter) {
return name;
}
protected void visitNew(Node node, Node tree) { protected void visitNew(Node node, Node tree) {
} }
@ -679,20 +673,12 @@ public class NodeTransformer {
return false; return false;
} }
protected VariableTable createVariableTable() {
return new VariableTable();
}
protected VariableTable getVariableTable(Node tree) { protected VariableTable getVariableTable(Node tree) {
if (inFunction) { if (inFunction) {
return ((FunctionNode)tree).getVariableTable(); return ((FunctionNode)tree).getVariableTable();
} else {
return (VariableTable)(tree.getProp(Node.VARS_PROP));
} }
VariableTable result = (VariableTable)(tree.getProp(Node.VARS_PROP));
if (result == null) {
result = createVariableTable();
tree.putProp(Node.VARS_PROP, result);
}
return result;
} }
protected void reportMessage(Context cx, String msg, Node stmt, protected void reportMessage(Context cx, String msg, Node stmt,

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

@ -48,31 +48,25 @@ public class VariableTable {
return varStart; return varStart;
} }
public Object getVariable(int index) { public String getVariable(int index) {
return itsVariables.get(index); return (String)itsVariables.get(index);
} }
public boolean hasVariable(String name) { public boolean hasVariable(String name) {
return itsVariableNames.has(name); return itsVariableNames.has(name);
} }
public Object getVariable(String name) {
int vIndex = itsVariableNames.get(name, -1);
if (vIndex != -1)
return itsVariables.get(vIndex);
else
return null;
}
public int getOrdinal(String name) { public int getOrdinal(String name) {
return itsVariableNames.get(name, -1); return itsVariableNames.get(name, -1);
} }
public void getAllVariables(Object[] destination) { public String[] getAllVariables() {
itsVariables.toArray(destination); String[] array = new String[itsVariables.size()];
itsVariables.toArray(array);
return array;
} }
public void addParameter(String pName, Object paramObj) { public void addParameter(String pName) {
// Check addParameter is not called after addLocal // Check addParameter is not called after addLocal
if (varStart != itsVariables.size()) Context.codeBug(); if (varStart != itsVariables.size()) Context.codeBug();
int pIndex = itsVariableNames.get(pName, -1); int pIndex = itsVariableNames.get(pName, -1);
@ -81,18 +75,18 @@ public class VariableTable {
Context.reportWarning(message, null, 0, null, 0); Context.reportWarning(message, null, 0, null, 0);
} }
int index = varStart++; int index = varStart++;
itsVariables.add(paramObj); itsVariables.add(pName);
itsVariableNames.put(pName, index); itsVariableNames.put(pName, index);
} }
public void addLocal(String vName, Object varObj) { public void addLocal(String vName) {
int vIndex = itsVariableNames.get(vName, -1); int vIndex = itsVariableNames.get(vName, -1);
if (vIndex != -1) { if (vIndex != -1) {
// There's already a variable or parameter with this name. // There's already a variable or parameter with this name.
return; return;
} }
int index = itsVariables.size(); int index = itsVariables.size();
itsVariables.add(varObj); itsVariables.add(vName);
itsVariableNames.put(vName, index); itsVariableNames.put(vName, index);
} }

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

@ -193,14 +193,14 @@ public class Block {
*/ */
void lookForVariablesAndCalls(Node n, boolean liveSet[], void lookForVariablesAndCalls(Node n, boolean liveSet[],
VariableTable theVariables) OptFunctionNode fn)
{ {
switch (n.getType()) { switch (n.getType()) {
case TokenStream.SETVAR : case TokenStream.SETVAR :
{ {
Node lhs = n.getFirstChild(); Node lhs = n.getFirstChild();
Node rhs = lhs.getNext(); Node rhs = lhs.getNext();
lookForVariablesAndCalls(rhs, liveSet, theVariables); lookForVariablesAndCalls(rhs, liveSet, fn);
Object theVarProp = n.getProp(Node.VARIABLE_PROP); Object theVarProp = n.getProp(Node.VARIABLE_PROP);
if (theVarProp != null) { if (theVarProp != null) {
int theVarIndex = ((OptLocalVariable)theVarProp).getIndex(); int theVarIndex = ((OptLocalVariable)theVarProp).getIndex();
@ -211,12 +211,12 @@ public class Block {
case TokenStream.CALL : { case TokenStream.CALL : {
Node child = n.getFirstChild(); Node child = n.getFirstChild();
while (child != null) { while (child != null) {
lookForVariablesAndCalls(child, liveSet, theVariables); lookForVariablesAndCalls(child, liveSet, fn);
child = child.getNext(); child = child.getNext();
} }
for (int i = 0; i < liveSet.length; i++) { for (int i = 0; i < liveSet.length; i++) {
if (liveSet[i]) if (liveSet[i])
OptLocalVariable.get(theVariables, i).markLiveAcrossCall(); fn.getVar(i).markLiveAcrossCall();
} }
} }
break; break;
@ -234,29 +234,29 @@ public class Block {
default : default :
Node child = n.getFirstChild(); Node child = n.getFirstChild();
while (child != null) { while (child != null) {
lookForVariablesAndCalls(child, liveSet, theVariables); lookForVariablesAndCalls(child, liveSet, fn);
child = child.getNext(); child = child.getNext();
} }
break; break;
} }
} }
void markAnyTypeVariables(VariableTable theVariables) void markAnyTypeVariables(OptFunctionNode fn)
{ {
for (int i = 0; i < theVariables.size(); i++) for (int i = 0; i < fn.getVarCount(); i++)
if (itsLiveOnEntrySet.test(i)) if (itsLiveOnEntrySet.test(i))
OptLocalVariable.get(theVariables, i).assignType(TypeEvent.AnyType); fn.getVar(i).assignType(TypeEvent.AnyType);
} }
void markVolatileVariables(VariableTable theVariables) void markVolatileVariables(OptFunctionNode fn)
{ {
boolean liveSet[] = new boolean[theVariables.size()]; boolean liveSet[] = new boolean[fn.getVarCount()];
for (int i = 0; i < liveSet.length; i++) for (int i = 0; i < liveSet.length; i++)
liveSet[i] = itsLiveOnEntrySet.test(i); liveSet[i] = itsLiveOnEntrySet.test(i);
for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) { for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) {
Node n = itsStatementNodes[i]; Node n = itsStatementNodes[i];
lookForVariablesAndCalls(n, liveSet, theVariables); lookForVariablesAndCalls(n, liveSet, fn);
} }
} }
@ -327,9 +327,9 @@ public class Block {
Then walk the trees looking for defs/uses of variables Then walk the trees looking for defs/uses of variables
and build the def and useBeforeDef sets. and build the def and useBeforeDef sets.
*/ */
public void initLiveOnEntrySets(VariableTable theVariables) void initLiveOnEntrySets(OptFunctionNode fn)
{ {
int listLength = theVariables.size(); int listLength = fn.getVarCount();
Node lastUse[] = new Node[listLength]; Node lastUse[] = new Node[listLength];
itsUseBeforeDefSet = new DataFlowBitSet(listLength); itsUseBeforeDefSet = new DataFlowBitSet(listLength);
itsNotDefSet = new DataFlowBitSet(listLength); itsNotDefSet = new DataFlowBitSet(listLength);
@ -630,7 +630,7 @@ public class Block {
} }
} }
public boolean doTypeFlow() boolean doTypeFlow()
{ {
boolean changed = false; boolean changed = false;
@ -643,15 +643,15 @@ public class Block {
return changed; return changed;
} }
public boolean isLiveOnEntry(int index) boolean isLiveOnEntry(int index)
{ {
return (itsLiveOnEntrySet != null) && (itsLiveOnEntrySet.test(index)); return (itsLiveOnEntrySet != null) && (itsLiveOnEntrySet.test(index));
} }
public void printLiveOnEntrySet(PrintWriter pw, VariableTable theVariables) void printLiveOnEntrySet(PrintWriter pw, OptFunctionNode fn)
{ {
for (int i = 0; i < theVariables.size(); i++) { for (int i = 0; i < fn.getVarCount(); i++) {
String name = OptLocalVariable.get(theVariables, i).getName(); String name = fn.getVar(i).getName();
if (itsUseBeforeDefSet.test(i)) if (itsUseBeforeDefSet.test(i))
pw.println(name + " is used before def'd"); pw.println(name + " is used before def'd");
if (itsNotDefSet.test(i)) if (itsNotDefSet.test(i))

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

@ -115,10 +115,9 @@ public class Codegen extends Interpreter {
cursor = cursor.getNext()) cursor = cursor.getNext())
{ {
if (cursor.getType() == TokenStream.FUNCTION) { if (cursor.getType() == TokenStream.FUNCTION) {
OptFunctionNode fnNode FunctionNode fn
= (OptFunctionNode)cursor. = (FunctionNode)cursor.getProp(Node.FUNCTION_PROP);
getProp(Node.FUNCTION_PROP); obj.put(fn.getFunctionName(), obj, fn);
obj.put(fnNode.getFunctionName(), obj, fnNode);
} }
} }
if (superClass == null) { if (superClass == null) {
@ -186,8 +185,7 @@ public class Codegen extends Interpreter {
throw new RuntimeException throw new RuntimeException
("Unable to instantiate compiled class:"+ex.toString()); ("Unable to instantiate compiled class:"+ex.toString());
} }
OptFunctionNode fnNode = (OptFunctionNode)tree; OptRuntime.initFunction(f, fnCurrent.getFunctionType(), scope, cx);
OptRuntime.initFunction(f, fnNode.getFunctionType(), scope, cx);
return f; return f;
} else { } else {
NativeScript script; NativeScript script;
@ -304,7 +302,7 @@ public class Codegen extends Interpreter {
return classFile.acquireLabel(); return classFile.acquireLabel();
} }
public void emitDirectConstructor(OptFunctionNode fnNode) public void emitDirectConstructor()
{ {
/* /*
we generate .. we generate ..
@ -322,11 +320,11 @@ public class Codegen extends Interpreter {
short flags = (short)(ClassFileWriter.ACC_PUBLIC short flags = (short)(ClassFileWriter.ACC_PUBLIC
| ClassFileWriter.ACC_FINAL); | ClassFileWriter.ACC_FINAL);
classFile.startMethod("constructDirect", classFile.startMethod("constructDirect",
fnNode.getDirectCallParameterSignature() fnCurrent.getDirectCallParameterSignature()
+ "Ljava/lang/Object;", + "Ljava/lang/Object;",
flags); flags);
int argCount = fnNode.getVariableTable().getParameterCount(); int argCount = fnCurrent.getParameterCount();
int firstLocal = (4 + argCount * 3) + 1; int firstLocal = (4 + argCount * 3) + 1;
aload((short)0); // this aload((short)0); // this
@ -350,7 +348,7 @@ public class Codegen extends Interpreter {
aload((short)(4 + argCount * 3)); aload((short)(4 + argCount * 3));
addVirtualInvoke(this.name, addVirtualInvoke(this.name,
"callDirect", "callDirect",
fnNode.getDirectCallParameterSignature(), fnCurrent.getDirectCallParameterSignature(),
"Ljava/lang/Object;"); "Ljava/lang/Object;");
astore((short)(firstLocal + 1)); astore((short)(firstLocal + 1));
@ -403,14 +401,14 @@ public class Codegen extends Interpreter {
Node codegenBase; Node codegenBase;
if (inFunction) { if (inFunction) {
OptFunctionNode fnNode = (OptFunctionNode) tree; fnCurrent = (OptFunctionNode)tree;
inDirectCallFunction = fnNode.isTargetOfDirectCall(); inDirectCallFunction = fnCurrent.isTargetOfDirectCall();
vars = fnNode.getVariableTable(); vars = fnCurrent.getVariableTable();
this.name = fnNode.getClassName(); this.name = fnCurrent.getClassName();
classFile = new ClassFileWriter(name, superClassName, itsSourceFile); classFile = new ClassFileWriter(name, superClassName, itsSourceFile);
String name = fnNode.getFunctionName(); String name = fnCurrent.getFunctionName();
generateInit(cx, "<init>", tree, name); generateInit(cx, "<init>", tree, name);
if (fnNode.isTargetOfDirectCall()) { if (fnCurrent.isTargetOfDirectCall()) {
classFile.startMethod("call", classFile.startMethod("call",
"(Lorg/mozilla/javascript/Context;" + "(Lorg/mozilla/javascript/Context;" +
"Lorg/mozilla/javascript/Scriptable;" + "Lorg/mozilla/javascript/Scriptable;" +
@ -442,24 +440,24 @@ public class Codegen extends Interpreter {
addByteCode(ByteCode.ALOAD, 4); addByteCode(ByteCode.ALOAD, 4);
addVirtualInvoke(this.name, addVirtualInvoke(this.name,
"callDirect", "callDirect",
fnNode.getDirectCallParameterSignature(), fnCurrent.getDirectCallParameterSignature(),
"Ljava/lang/Object;"); "Ljava/lang/Object;");
addByteCode(ByteCode.ARETURN); addByteCode(ByteCode.ARETURN);
classFile.stopMethod((short)5, null); classFile.stopMethod((short)5, null);
// 1 for this, 1 for js this, 1 for args[] // 1 for this, 1 for js this, 1 for args[]
emitDirectConstructor(fnNode); emitDirectConstructor();
startNewMethod("callDirect", startNewMethod("callDirect",
fnNode.getDirectCallParameterSignature() + fnCurrent.getDirectCallParameterSignature() +
"Ljava/lang/Object;", "Ljava/lang/Object;",
1, false, true); 1, false, true);
assignParameterJRegs(vars); assignParameterJRegs(fnCurrent);
if (!fnNode.getParameterNumberContext()) { if (!fnCurrent.getParameterNumberContext()) {
// make sure that all parameters are objects // make sure that all parameters are objects
itsForcedObjectParameters = true; itsForcedObjectParameters = true;
for (int i = 0; i < vars.getParameterCount(); i++) { for (int i = 0; i < fnCurrent.getParameterCount(); i++) {
OptLocalVariable lVar = OptLocalVariable.get(vars, i); OptLocalVariable lVar = fnCurrent.getVar(i);
aload(lVar.getJRegister()); aload(lVar.getJRegister());
classFile.add(ByteCode.GETSTATIC, classFile.add(ByteCode.GETSTATIC,
"java/lang/Void", "java/lang/Void",
@ -532,15 +530,15 @@ public class Codegen extends Interpreter {
return name; return name;
} }
private static void assignParameterJRegs(VariableTable vars) { private static void assignParameterJRegs(OptFunctionNode fnCurrent) {
// 0 is reserved for function Object 'this' // 0 is reserved for function Object 'this'
// 1 is reserved for context // 1 is reserved for context
// 2 is reserved for parentScope // 2 is reserved for parentScope
// 3 is reserved for script 'this' // 3 is reserved for script 'this'
short jReg = 4; short jReg = 4;
int parameterCount = vars.getParameterCount(); int parameterCount = fnCurrent.getParameterCount();
for (int i = 0; i < parameterCount; i++) { for (int i = 0; i < parameterCount; i++) {
OptLocalVariable lVar = OptLocalVariable.get(vars, i); OptLocalVariable lVar = fnCurrent.getVar(i);
lVar.assignJRegister(jReg); lVar.assignJRegister(jReg);
jReg += 3; // 3 is 1 for Object parm and 2 for double parm jReg += 3; // 3 is 1 for Object parm and 2 for double parm
} }
@ -1018,8 +1016,7 @@ public class Codegen extends Interpreter {
classFile.startMethod(methodName, methodDesc, (short) flags); classFile.startMethod(methodName, methodDesc, (short) flags);
} }
private void finishMethod(Context cx, VariableTable vars) { private void finishMethod(Context cx, OptLocalVariable[] array) {
OptLocalVariable[] array = OptLocalVariable.toArray(vars);
classFile.stopMethod((short)(localsMax + 1), array); classFile.stopMethod((short)(localsMax + 1), array);
contextLocal = -1; contextLocal = -1;
} }
@ -1155,7 +1152,7 @@ public class Codegen extends Interpreter {
for (int i = 0; i != N; i++) { for (int i = 0; i != N; i++) {
addByteCode(ByteCode.DUP); addByteCode(ByteCode.DUP);
push(i); push(i);
push(OptLocalVariable.get(vars, i).getName()); push(vars.getVariable(i));
addByteCode(ByteCode.AASTORE); addByteCode(ByteCode.AASTORE);
} }
addByteCode(ByteCode.ALOAD_0); addByteCode(ByteCode.ALOAD_0);
@ -1195,10 +1192,9 @@ public class Codegen extends Interpreter {
if (tree instanceof OptFunctionNode) { if (tree instanceof OptFunctionNode) {
OptFunctionNode fnNode = (OptFunctionNode)tree; if (fnCurrent.isTargetOfDirectCall()) {
if (fnNode.isTargetOfDirectCall()) {
setNonTrivialInit(methodName); setNonTrivialInit(methodName);
String className = fnNode.getClassName(); String className = fnCurrent.getClassName();
String fieldName = className.replace('.', '_'); String fieldName = className.replace('.', '_');
String fieldType = 'L'+classFile.fullyQualifiedForm(className) String fieldType = 'L'+classFile.fullyQualifiedForm(className)
+';'; +';';
@ -1400,8 +1396,8 @@ public class Codegen extends Interpreter {
// REMIND - only need to initialize the vars that don't get a value // REMIND - only need to initialize the vars that don't get a value
// before the next call and are used in the function // before the next call and are used in the function
short firstUndefVar = -1; short firstUndefVar = -1;
for (int i = 0; i < vars.size(); i++) { for (int i = 0; i < fnCurrent.getVarCount(); i++) {
OptLocalVariable lVar = OptLocalVariable.get(vars, i); OptLocalVariable lVar = fnCurrent.getVar(i);
if (lVar.isNumber()) { if (lVar.isNumber()) {
lVar.assignJRegister(getNewWordPairLocal()); lVar.assignJRegister(getNewWordPairLocal());
push(0.0); push(0.0);
@ -1430,7 +1426,7 @@ public class Codegen extends Interpreter {
// Indicate that we should generate debug information for // Indicate that we should generate debug information for
// the variable table. (If we're generating debug info at // the variable table. (If we're generating debug info at
// all.) // all.)
debugVars = vars; debugVars = fnCurrent.getVarsArray();
// Skip creating activation object. // Skip creating activation object.
return; return;
@ -1506,8 +1502,8 @@ public class Codegen extends Interpreter {
lv.assignJRegister(variableObjectLocal); lv.assignJRegister(variableObjectLocal);
lv.setStartPC(classFile.getCurrentCodeOffset()); lv.setStartPC(classFile.getCurrentCodeOffset());
debugVars = new VariableTable(); debugVars = new OptLocalVariable[1];
debugVars.addLocal(debugVariableName, lv); debugVars[0] = lv;
} }
if (!inFunction) { if (!inFunction) {
@ -2399,7 +2395,7 @@ public class Codegen extends Interpreter {
} }
String name = node.getString(); String name = node.getString();
if (hasVarsInRegs) { if (hasVarsInRegs) {
OptLocalVariable lVar = OptLocalVariable.get(vars, name); OptLocalVariable lVar = fnCurrent.getVar(name);
if (lVar != null) { if (lVar != null) {
if (lVar.isNumber()) { if (lVar.isNumber()) {
push("number"); push("number");
@ -2437,7 +2433,7 @@ public class Codegen extends Interpreter {
String routine = (isInc) ? "postIncrement" : "postDecrement"; String routine = (isInc) ? "postIncrement" : "postDecrement";
if (hasVarsInRegs && child.getType() == TokenStream.GETVAR) { if (hasVarsInRegs && child.getType() == TokenStream.GETVAR) {
if (lVar == null) if (lVar == null)
lVar = OptLocalVariable.get(vars, child.getString()); lVar = fnCurrent.getVar(child.getString());
if (lVar.getJRegister() == -1) if (lVar.getJRegister() == -1)
lVar.assignJRegister(getNewWordLocal()); lVar.assignJRegister(getNewWordLocal());
aload(lVar.getJRegister()); aload(lVar.getJRegister());
@ -3201,7 +3197,7 @@ public class Codegen extends Interpreter {
{ {
// TODO: Clean up use of lVar here and in set. // TODO: Clean up use of lVar here and in set.
if (hasVarsInRegs && lVar == null) if (hasVarsInRegs && lVar == null)
lVar = OptLocalVariable.get(vars, name); lVar = fnCurrent.getVar(name);
if (lVar != null) { if (lVar != null) {
if (lVar.getJRegister() == -1) if (lVar.getJRegister() == -1)
if (lVar.isNumber()) if (lVar.isNumber())
@ -3272,7 +3268,7 @@ public class Codegen extends Interpreter {
OptLocalVariable lVar = (OptLocalVariable)(node.getProp(Node.VARIABLE_PROP)); OptLocalVariable lVar = (OptLocalVariable)(node.getProp(Node.VARIABLE_PROP));
// XXX is this right? If so, clean up. // XXX is this right? If so, clean up.
if (hasVarsInRegs && lVar == null) if (hasVarsInRegs && lVar == null)
lVar = OptLocalVariable.get(vars, child.getString()); lVar = fnCurrent.getVar(child.getString());
if (lVar != null) { if (lVar != null) {
generateCodeFromNode(child.getNext(), node, -1, -1); generateCodeFromNode(child.getNext(), node, -1, -1);
if (lVar.getJRegister() == -1) { if (lVar.getJRegister() == -1) {
@ -3768,13 +3764,14 @@ public class Codegen extends Interpreter {
private short itsZeroArgArray; private short itsZeroArgArray;
private short itsOneArgArray; private short itsOneArgArray;
private OptFunctionNode fnCurrent;
private boolean itsUseDynamicScope; private boolean itsUseDynamicScope;
private boolean hasVarsInRegs; private boolean hasVarsInRegs;
private boolean itsForcedObjectParameters; private boolean itsForcedObjectParameters;
private boolean trivialInit; private boolean trivialInit;
private short itsLocalAllocationBase; private short itsLocalAllocationBase;
private VariableTable vars; private VariableTable vars;
private VariableTable debugVars; private OptLocalVariable[] debugVars;
private int epilogueLabel; private int epilogueLabel;
private int optLevel; private int optLevel;
} }

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

@ -39,15 +39,26 @@ package org.mozilla.javascript.optimizer;
import org.mozilla.javascript.*; import org.mozilla.javascript.*;
import java.util.*; import java.util.*;
public class OptFunctionNode extends FunctionNode { class OptFunctionNode extends FunctionNode {
public OptFunctionNode(String name, Node statements, String className) OptFunctionNode(String name, Node statements, String className)
{ {
super(name, statements); super(name, statements);
itsClassName = className; itsClassName = className;
} }
public String getDirectCallParameterSignature() { public void setVariableTable(VariableTable variableTable) {
super.setVariableTable(variableTable);
int N = variableTable.size();
int parameterCount = variableTable.getParameterCount();
optVars = new OptLocalVariable[N];
for (int i = 0; i != N; ++i) {
String name = variableTable.getVariable(i);
optVars[i] = new OptLocalVariable(name, i < parameterCount);
}
}
String getDirectCallParameterSignature() {
int pCount = itsVariableTable.getParameterCount(); int pCount = itsVariableTable.getParameterCount();
switch (pCount) { switch (pCount) {
case 0: return ZERO_PARAM_SIG; case 0: return ZERO_PARAM_SIG;
@ -64,15 +75,15 @@ public class OptFunctionNode extends FunctionNode {
return sb.toString(); return sb.toString();
} }
public String getClassName() { String getClassName() {
return itsClassName; return itsClassName;
} }
public boolean isTargetOfDirectCall() { boolean isTargetOfDirectCall() {
return itsIsTargetOfDirectCall; return itsIsTargetOfDirectCall;
} }
public void addDirectCallTarget(FunctionNode target) { void addDirectCallTarget(FunctionNode target) {
if (itsDirectCallTargets == null) if (itsDirectCallTargets == null)
itsDirectCallTargets = new ObjArray(); itsDirectCallTargets = new ObjArray();
for (int i = 0; i < itsDirectCallTargets.size(); i++) // OPT !! for (int i = 0; i < itsDirectCallTargets.size(); i++) // OPT !!
@ -81,40 +92,65 @@ public class OptFunctionNode extends FunctionNode {
itsDirectCallTargets.add(target); itsDirectCallTargets.add(target);
} }
public ObjArray getDirectCallTargets() { ObjArray getDirectCallTargets() {
return itsDirectCallTargets; return itsDirectCallTargets;
} }
public void setIsTargetOfDirectCall() { void setIsTargetOfDirectCall() {
itsIsTargetOfDirectCall = true; itsIsTargetOfDirectCall = true;
} }
public void setParameterNumberContext(boolean b) { void setParameterNumberContext(boolean b) {
itsParameterNumberContext = b; itsParameterNumberContext = b;
} }
public boolean getParameterNumberContext() { boolean getParameterNumberContext() {
return itsParameterNumberContext; return itsParameterNumberContext;
} }
public boolean containsCalls(int argCount) { boolean containsCalls(int argCount) {
if ((argCount < itsContainsCallsCount.length) && (argCount >= 0)) if ((argCount < itsContainsCallsCount.length) && (argCount >= 0))
return itsContainsCallsCount[argCount]; return itsContainsCallsCount[argCount];
else else
return itsContainsCalls; return itsContainsCalls;
} }
public void setContainsCalls(int argCount) { void setContainsCalls(int argCount) {
if (argCount < itsContainsCallsCount.length) if (argCount < itsContainsCallsCount.length)
itsContainsCallsCount[argCount] = true; itsContainsCallsCount[argCount] = true;
itsContainsCalls = true; itsContainsCalls = true;
} }
public void incrementLocalCount() { void incrementLocalCount() {
int localCount = getIntProp(Node.LOCALCOUNT_PROP, 0); int localCount = getIntProp(Node.LOCALCOUNT_PROP, 0);
putIntProp(Node.LOCALCOUNT_PROP, localCount + 1); putIntProp(Node.LOCALCOUNT_PROP, localCount + 1);
} }
int getVarCount() {
return optVars.length;
}
OptLocalVariable getVar(int index) {
return optVars[index];
}
OptLocalVariable getVar(String name) {
int index = itsVariableTable.getOrdinal(name);
if (index < 0) { return null; }
return optVars[index];
}
void establishVarsIndices() {
int N = optVars.length;
for (int i = 0; i != N; i++) {
optVars[i].setIndex(i);
}
}
OptLocalVariable[] getVarsArray() {
return optVars;
}
private static final String private static final String
BEFORE_DIRECT_SIG = "(Lorg/mozilla/javascript/Context;" BEFORE_DIRECT_SIG = "(Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Scriptable;"
@ -128,6 +164,7 @@ public class OptFunctionNode extends FunctionNode {
TWO_PARAM_SIG = BEFORE_DIRECT_SIG+DIRECT_ARG_SIG+DIRECT_ARG_SIG TWO_PARAM_SIG = BEFORE_DIRECT_SIG+DIRECT_ARG_SIG+DIRECT_ARG_SIG
+AFTER_DIRECT_SIG; +AFTER_DIRECT_SIG;
private OptLocalVariable[] optVars;
private String itsClassName; private String itsClassName;
private boolean itsIsTargetOfDirectCall; private boolean itsIsTargetOfDirectCall;
private boolean itsContainsCalls; private boolean itsContainsCalls;

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

@ -117,30 +117,6 @@ final class OptLocalVariable implements JavaVariable {
return itsTypeUnion.getEvent(); return itsTypeUnion.getEvent();
} }
static OptLocalVariable get(VariableTable vars, int index) {
return (OptLocalVariable)(vars.getVariable(index));
}
static OptLocalVariable get(VariableTable vars, String name) {
return (OptLocalVariable)(vars.getVariable(name));
}
static void establishIndices(VariableTable vars) {
int N = vars.size();
for (int i = 0; i != N; i++) {
get(vars, i).itsIndex = i;
}
}
static OptLocalVariable[] toArray(VariableTable vars) {
OptLocalVariable[] array = null;
if (vars != null) {
array = new OptLocalVariable[vars.size()];
vars.getAllVariables(array);
}
return array;
}
private String itsName; private String itsName;
private boolean itsIsParameter; private boolean itsIsParameter;
private int itsIndex = -1; private int itsIndex = -1;

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

@ -100,10 +100,6 @@ class OptTransformer extends NodeTransformer {
return argCount; return argCount;
} }
protected Object createVariableObject(String name, boolean isParameter) {
return new OptLocalVariable(name, isParameter);
}
protected void visitNew(Node node, Node tree) { protected void visitNew(Node node, Node tree) {
detectDirectCall(node, tree); detectDirectCall(node, tree);
super.visitNew(node, tree); super.visitNew(node, tree);
@ -129,20 +125,20 @@ class OptTransformer extends NodeTransformer {
* else * else
* ScriptRuntime.Call(fn, tmp, b, c) * ScriptRuntime.Call(fn, tmp, b, c)
*/ */
void markDirectCall(Node containingTree, Node callNode, int argCount, private void markDirectCall(Node containingTree, Node callNode,
String targetName) int argCount, String targetName)
{ {
OptFunctionNode theFunction OptFunctionNode theFunction
= (OptFunctionNode)theFnClassNameList.get(targetName); = (OptFunctionNode)theFnClassNameList.get(targetName);
if (theFunction != null) { if (theFunction != null) {
VariableTable varTable = theFunction.getVariableTable(); int N = theFunction.getParameterCount();
// Refuse to directCall any function with more // Refuse to directCall any function with more
// than 32 parameters - prevent code explosion // than 32 parameters - prevent code explosion
// for wacky test cases // for wacky test cases
if (varTable.getParameterCount() > 32) if (N > 32)
return; return;
if (argCount == varTable.getParameterCount()) { if (argCount == N) {
callNode.putProp(Node.DIRECTCALL_PROP, theFunction); callNode.putProp(Node.DIRECTCALL_PROP, theFunction);
((OptFunctionNode)containingTree) ((OptFunctionNode)containingTree)
.addDirectCallTarget(theFunction); .addDirectCallTarget(theFunction);
@ -180,7 +176,6 @@ class OptTransformer extends NodeTransformer {
*/ */
theFnClassNameList.put(name, fnNode); theFnClassNameList.put(name, fnNode);
} }
addParameters(fnNode);
} }
} }
} }

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

@ -86,48 +86,44 @@ class Optimizer {
pw.println(Block.toString(theBlocks, theStatementNodes)); pw.println(Block.toString(theBlocks, theStatementNodes));
} }
VariableTable vars = theFunction.getVariableTable(); theFunction.establishVarsIndices();
if (vars != null) { for (int i = 0; i < theStatementNodes.length; i++)
OptLocalVariable.establishIndices(vars); replaceVariableAccess(theStatementNodes[i], theFunction);
for (int i = 0; i < theStatementNodes.length; i++)
replaceVariableAccess(theStatementNodes[i], vars);
if(DO_CONSTANT_FOLDING){ if(DO_CONSTANT_FOLDING){
foldConstants(theFunction, null); foldConstants(theFunction, null);
} }
reachingDefDataFlow(vars, theBlocks); reachingDefDataFlow(theFunction, theBlocks);
typeFlow(vars, theBlocks); typeFlow(theFunction, theBlocks);
findSinglyTypedVars(vars, theBlocks); findSinglyTypedVars(theFunction, theBlocks);
localCSE(theBlocks, theFunction); localCSE(theBlocks, theFunction);
if (!theFunction.requiresActivation()) { if (!theFunction.requiresActivation()) {
/* /*
* Now that we know which local vars are in fact always * Now that we know which local vars are in fact always
* Numbers, we re-write the tree to take advantage of * Numbers, we re-write the tree to take advantage of
* that. Any arithmetic or assignment op involving just * that. Any arithmetic or assignment op involving just
* Number typed vars is marked so that the codegen will * Number typed vars is marked so that the codegen will
* generate non-object code. * generate non-object code.
*/ */
parameterUsedInNumberContext = false; parameterUsedInNumberContext = false;
for (int i = 0; i < theStatementNodes.length; i++) { for (int i = 0; i < theStatementNodes.length; i++) {
rewriteForNumberVariables(theStatementNodes[i]); rewriteForNumberVariables(theStatementNodes[i]);
}
theFunction.setParameterNumberContext(parameterUsedInNumberContext);
//System.out.println("Function " + theFunction.getFunctionName() + " has parameters in number contexts : " + parameterUsedInNumberContext);
} }
if (DEBUG_OPTIMIZER) { theFunction.setParameterNumberContext(parameterUsedInNumberContext);
for (int i = 0; i < theBlocks.length; i++) { //System.out.println("Function " + theFunction.getFunctionName() + " has parameters in number contexts : " + parameterUsedInNumberContext);
pw.println("For block " + theBlocks[i].getBlockID()); }
theBlocks[i].printLiveOnEntrySet(pw, vars); if (DEBUG_OPTIMIZER) {
} for (int i = 0; i < theBlocks.length; i++) {
int N = vars.size(); pw.println("For block " + theBlocks[i].getBlockID());
System.out.println("Variable Table, size = " + N); theBlocks[i].printLiveOnEntrySet(pw, theFunction);
for (int i = 0; i != N; i++) { }
OptLocalVariable lVar = OptLocalVariable.get(vars, i); int N = theFunction.getVarCount();
pw.println(lVar.toString()); System.out.println("Variable Table, size = " + N);
} for (int i = 0; i != N; i++) {
OptLocalVariable lVar = theFunction.getVar(i);
pw.println(lVar.toString());
} }
} }
if (DEBUG_OPTIMIZER) pw.close(); if (DEBUG_OPTIMIZER) pw.close();
} }
@ -140,7 +136,7 @@ class Optimizer {
} }
private static void private static void
findSinglyTypedVars(VariableTable theVariables, Block theBlocks[]) findSinglyTypedVars(OptFunctionNode fn, Block theBlocks[])
{ {
/* /*
discover the type events for each non-volatile variable (not live discover the type events for each non-volatile variable (not live
@ -158,8 +154,8 @@ class Optimizer {
theBlocks[i].findDefs(); theBlocks[i].findDefs();
} }
} }
for (int i = 0; i < theVariables.size(); i++) { for (int i = 0; i < fn.getVarCount(); i++) {
OptLocalVariable lVar = OptLocalVariable.get(theVariables, i); OptLocalVariable lVar = fn.getVar(i);
if (!lVar.isParameter()) { if (!lVar.isParameter()) {
int theType = lVar.getTypeUnion(); int theType = lVar.getTypeUnion();
if (theType == TypeEvent.NumberType) { if (theType == TypeEvent.NumberType) {
@ -201,7 +197,7 @@ class Optimizer {
} }
private static void private static void
typeFlow(VariableTable theVariables, Block theBlocks[]) typeFlow(OptFunctionNode fn, Block theBlocks[])
{ {
boolean visit[] = new boolean[theBlocks.length]; boolean visit[] = new boolean[theBlocks.length];
boolean doneOnce[] = new boolean[theBlocks.length]; boolean doneOnce[] = new boolean[theBlocks.length];
@ -237,7 +233,7 @@ class Optimizer {
} }
private static void private static void
reachingDefDataFlow(VariableTable theVariables, Block theBlocks[]) reachingDefDataFlow(OptFunctionNode fn, Block theBlocks[])
{ {
/* /*
initialize the liveOnEntry and liveOnExit sets, then discover the variables initialize the liveOnEntry and liveOnExit sets, then discover the variables
@ -245,7 +241,7 @@ class Optimizer {
(hence liveOnEntry) (hence liveOnEntry)
*/ */
for (int i = 0; i < theBlocks.length; i++) { for (int i = 0; i < theBlocks.length; i++) {
theBlocks[i].initLiveOnEntrySets(theVariables); theBlocks[i].initLiveOnEntrySets(fn);
} }
/* /*
this visits every block starting at the last, re-adding the predecessors of this visits every block starting at the last, re-adding the predecessors of
@ -294,10 +290,10 @@ class Optimizer {
*/ */
for (int i = 0; i < theBlocks.length; i++) { for (int i = 0; i < theBlocks.length; i++) {
theBlocks[i].markVolatileVariables(theVariables); theBlocks[i].markVolatileVariables(fn);
} }
theBlocks[0].markAnyTypeVariables(theVariables); theBlocks[0].markAnyTypeVariables(fn);
} }
/* /*
@ -989,23 +985,23 @@ class Optimizer {
} }
private static void private static void
replaceVariableAccess(Node n, VariableTable theVariables) replaceVariableAccess(Node n, OptFunctionNode fn)
{ {
Node child = n.getFirstChild(); Node child = n.getFirstChild();
while (child != null) { while (child != null) {
replaceVariableAccess(child, theVariables); replaceVariableAccess(child, fn);
child = child.getNext(); child = child.getNext();
} }
int type = n.getType(); int type = n.getType();
if (type == TokenStream.SETVAR) { if (type == TokenStream.SETVAR) {
String name = n.getFirstChild().getString(); String name = n.getFirstChild().getString();
OptLocalVariable theVar = OptLocalVariable.get(theVariables, name); OptLocalVariable theVar = fn.getVar(name);
if (theVar != null) { if (theVar != null) {
n.putProp(Node.VARIABLE_PROP, theVar); n.putProp(Node.VARIABLE_PROP, theVar);
} }
} else if (type == TokenStream.GETVAR) { } else if (type == TokenStream.GETVAR) {
String name = n.getString(); String name = n.getString();
OptLocalVariable theVar = OptLocalVariable.get(theVariables, name); OptLocalVariable theVar = fn.getVar(name);
if (theVar != null) { if (theVar != null) {
n.putProp(Node.VARIABLE_PROP, theVar); n.putProp(Node.VARIABLE_PROP, theVar);
} }