зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
90c8869435
Коммит
aab18156df
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче