Replace explicit parse tree walk to associate OptLocalVariable with tree nodes by lazy initialization of the association on first OptLocalVariable access. It shrinks code while making optimization to run slightly faster.

This commit is contained in:
igor%mir2.org 2004-09-27 09:33:50 +00:00
parent 3487e65a11
commit 9ca481e40b
5 changed files with 67 additions and 97 deletions

View File

@ -331,7 +331,8 @@ class Block
if (visit[vIndex] || !doneOnce[vIndex]) {
doneOnce[vIndex] = true;
visit[vIndex] = false;
if (theBlocks[vIndex].doTypeFlow(statementNodes, varTypes)) {
if (theBlocks[vIndex].doTypeFlow(fn, statementNodes, varTypes))
{
Block succ[] = theBlocks[vIndex].itsSuccessors;
if (succ != null) {
for (int i = 0; i < succ.length; i++) {
@ -355,11 +356,6 @@ class Block
}
}
private static int getVarIndex(Node n)
{
return OptLocalVariable.get(n).getIndex();
}
private static boolean assignType(int[] varTypes, int index, int type)
{
return type != (varTypes[index] |= type);
@ -383,7 +379,7 @@ class Block
The itsNotDefSet is built reversed then flipped later.
*/
private void lookForVariableAccess(Node n)
private void lookForVariableAccess(OptFunctionNode fn, Node n)
{
switch (n.getType()) {
case Token.DEC :
@ -391,7 +387,7 @@ class Block
{
Node child = n.getFirstChild();
if (child.getType() == Token.GETVAR) {
int varIndex = getVarIndex(child);
int varIndex = fn.getVarIndex(child);
if (!itsNotDefSet.test(varIndex))
itsUseBeforeDefSet.set(varIndex);
itsNotDefSet.set(varIndex);
@ -402,13 +398,13 @@ class Block
{
Node lhs = n.getFirstChild();
Node rhs = lhs.getNext();
lookForVariableAccess(rhs);
itsNotDefSet.set(getVarIndex(n));
lookForVariableAccess(fn, rhs);
itsNotDefSet.set(fn.getVarIndex(n));
}
break;
case Token.GETVAR :
{
int varIndex = getVarIndex(n);
int varIndex = fn.getVarIndex(n);
if (!itsNotDefSet.test(varIndex))
itsUseBeforeDefSet.set(varIndex);
}
@ -416,7 +412,7 @@ class Block
default :
Node child = n.getFirstChild();
while (child != null) {
lookForVariableAccess(child);
lookForVariableAccess(fn, child);
child = child.getNext();
}
break;
@ -437,7 +433,7 @@ class Block
itsLiveOnExitSet = new DataFlowBitSet(listLength);
for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) {
Node n = statementNodes[i];
lookForVariableAccess(n);
lookForVariableAccess(fn, n);
}
itsNotDefSet.not(); // truth in advertising
}
@ -464,7 +460,8 @@ class Block
Literals,
Arithmetic operations - always return a Number
*/
private static int findExpressionType(Node n, int[] varTypes)
private static int findExpressionType(OptFunctionNode fn, Node n,
int[] varTypes)
{
switch (n.getType()) {
case Token.NUMBER :
@ -479,7 +476,7 @@ class Block
return Optimizer.AnyType;
case Token.GETVAR :
return varTypes[getVarIndex(n)];
return varTypes[fn.getVarIndex(n)];
case Token.INC :
case Token.DEC :
@ -498,8 +495,8 @@ class Block
// if the lhs & rhs are known to be numbers, we can be sure that's
// the result, otherwise it could be a string.
Node child = n.getFirstChild();
int lType = findExpressionType(child, varTypes);
int rType = findExpressionType(child.getNext(), varTypes);
int lType = findExpressionType(fn, child, varTypes);
int rType = findExpressionType(fn, child.getNext(), varTypes);
return lType | rType; // we're not distinguishng strings yet
}
}
@ -510,21 +507,22 @@ class Block
} else {
int result = Optimizer.NoType;
while (child != null) {
result |= findExpressionType(child, varTypes);
result |= findExpressionType(fn, child, varTypes);
child = child.getNext();
}
return result;
}
}
private static boolean findDefPoints(Node n, int[] varTypes)
private static boolean findDefPoints(OptFunctionNode fn, Node n,
int[] varTypes)
{
boolean result = false;
Node child = n.getFirstChild();
switch (n.getType()) {
default :
while (child != null) {
result |= findDefPoints(child, varTypes);
result |= findDefPoints(fn, child, varTypes);
child = child.getNext();
}
break;
@ -532,25 +530,25 @@ class Block
case Token.INC :
if (child.getType() == Token.GETVAR) {
// theVar is a Number now
int i = getVarIndex(child);
int i = fn.getVarIndex(child);
result |= assignType(varTypes, i, Optimizer.NumberType);
}
break;
case Token.SETPROP :
case Token.SETPROP_OP :
if (child.getType() == Token.GETVAR) {
int i = getVarIndex(child);
int i = fn.getVarIndex(child);
assignType(varTypes, i, Optimizer.AnyType);
}
while (child != null) {
result |= findDefPoints(child, varTypes);
result |= findDefPoints(fn, child, varTypes);
child = child.getNext();
}
break;
case Token.SETVAR : {
Node rValue = child.getNext();
int theType = findExpressionType(rValue, varTypes);
int i = getVarIndex(n);
int theType = findExpressionType(fn, rValue, varTypes);
int i = fn.getVarIndex(n);
result |= assignType(varTypes, i, theType);
break;
}
@ -558,14 +556,15 @@ class Block
return result;
}
private boolean doTypeFlow(Node[] statementNodes, int[] varTypes)
private boolean doTypeFlow(OptFunctionNode fn, Node[] statementNodes,
int[] varTypes)
{
boolean changed = false;
for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) {
Node n = statementNodes[i];
if (n != null)
changed |= findDefPoints(n, varTypes);
changed |= findDefPoints(fn, n, varTypes);
}
return changed;

View File

@ -1423,21 +1423,7 @@ class BodyCodegen
switch (type) {
case Token.LOOP:
case Token.LABEL:
while (child != null) {
generateStatement(child, node);
child = child.getNext();
}
break;
case Token.WITH:
++withNesting;
while (child != null) {
generateStatement(child, node);
child = child.getNext();
}
--withNesting;
break;
case Token.SCRIPT:
case Token.BLOCK:
case Token.EMPTY:
@ -3085,7 +3071,7 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
case Token.GETVAR:
if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) {
boolean post = ((incrDecrMask & Node.POST_FLAG) != 0);
OptLocalVariable lVar = OptLocalVariable.get(child);
OptLocalVariable lVar = fnCurrent.getVar(child);
short reg = lVar.getJRegister();
cfw.addDLoad(reg);
if (post) {
@ -3104,9 +3090,7 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
break;
} else if (hasVarsInRegs) {
boolean post = ((incrDecrMask & Node.POST_FLAG) != 0);
OptLocalVariable lVar = OptLocalVariable.get(child);
if (lVar == null)
lVar = fnCurrent.getVar(child.getString());
OptLocalVariable lVar = fnCurrent.getVar(child);
short reg = lVar.getJRegister();
cfw.addALoad(reg);
if (post) {
@ -3271,7 +3255,7 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
if (node.getType() == Token.GETVAR
&& inDirectCallFunction && !itsForcedObjectParameters)
{
OptLocalVariable lVar = OptLocalVariable.get(node);
OptLocalVariable lVar = fnCurrent.getVar(node);
if (lVar.isParameter()) {
return lVar.getJRegister();
}
@ -3543,10 +3527,7 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
private void visitGetVar(Node node)
{
if (hasVarsInRegs) {
OptLocalVariable lVar = OptLocalVariable.get(node);
if (lVar == null) {
lVar = fnCurrent.getVar(node.getString());
}
OptLocalVariable lVar = fnCurrent.getVar(node);
short reg = lVar.getJRegister();
if (varIsDirectCallParameter(lVar)) {
// Remember that here the isNumber flag means that we
@ -3579,10 +3560,7 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
private void visitSetVar(Node node, Node child, boolean needValue)
{
if (hasVarsInRegs) {
OptLocalVariable lVar = OptLocalVariable.get(node);
if (lVar == null) {
lVar = fnCurrent.getVar(child.getString());
}
OptLocalVariable lVar = fnCurrent.getVar(node);
generateExpression(child.getNext(), node);
boolean isNumber = (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1);
short reg = lVar.getJRegister();
@ -4003,8 +3981,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
private int enterAreaStartLabel;
private int epilogueLabel;
private int withNesting = 0;
// special known locals. If you add a new local here, be sure
// to initialize it to -1 in initBodyGeneration
private short variableObjectLocal;

View File

@ -48,7 +48,7 @@ final class OptFunctionNode
int parameterCount = fnode.getParamCount();
optVars = new OptLocalVariable[N];
for (int i = 0; i != N; ++i) {
optVars[i] = new OptLocalVariable(i, i < parameterCount);
optVars[i] = new OptLocalVariable(i < parameterCount);
}
fnode.setCompilerData(this);
}
@ -109,6 +109,32 @@ final class OptFunctionNode
return optVars[index];
}
int getVarIndex(Node n)
{
int index = n.getIntProp(Node.VARIABLE_PROP, -1);
if (index == -1) {
String name;
int type = n.getType();
if (type == Token.GETVAR) {
name = n.getString();
} else if (type == Token.SETVAR) {
name = n.getFirstChild().getString();
} else {
throw Kit.codeBug();
}
index = fnode.getParamOrVarIndex(name);
if (index < 0) throw Kit.codeBug();
n.putIntProp(Node.VARIABLE_PROP, index);
}
return index;
}
OptLocalVariable getVar(Node n)
{
int index = getVarIndex(n);
return optVars[index];
}
OptLocalVariable[] getVarsArray()
{
return optVars;

View File

@ -41,19 +41,11 @@ import org.mozilla.javascript.*;
final class OptLocalVariable
{
OptLocalVariable(int index, boolean isParameter)
OptLocalVariable(boolean isParameter)
{
itsIndex = index;
itsIsParameter = isParameter;
}
static OptLocalVariable get(Node n)
{
int type = n.getType();
if (type != Token.GETVAR && type != Token.SETVAR) Kit.codeBug();
return (OptLocalVariable)n.getProp(Node.VARIABLE_PROP);
}
short getJRegister() {
return itsJRegister;
}
@ -62,19 +54,14 @@ final class OptLocalVariable
itsJRegister = aJReg;
}
int getIndex() {
return itsIndex;
}
void setIsNumber() { itsIsNumber = true; }
boolean isNumber() { return itsIsNumber; }
boolean isParameter() { return itsIsParameter; }
private boolean itsIsParameter;
private int itsIndex;
private boolean itsIsNumber;
private short itsJRegister = -1; // unassigned
private boolean itsIsNumber;
}

View File

@ -69,15 +69,13 @@ class Optimizer
if (theFunction.fnode.requiresActivation()) return;
inDirectCallFunction = theFunction.isTargetOfDirectCall();
this.theFunction = theFunction;
ObjArray statementsArray = new ObjArray();
buildStatementList_r(theFunction.fnode, statementsArray);
Node[] theStatementNodes = new Node[statementsArray.size()];
statementsArray.toArray(theStatementNodes);
for (int i = 0; i < theStatementNodes.length; i++)
replaceVariableAccess(theStatementNodes[i], theFunction);
Block.runFlowAnalyzes(theFunction, theStatementNodes);
if (!theFunction.fnode.requiresActivation()) {
@ -132,7 +130,7 @@ class Optimizer
private void markDCPNumberContext(Node n)
{
if (inDirectCallFunction && n.getType() == Token.GETVAR) {
if (OptLocalVariable.get(n).isParameter()) {
if (theFunction.getVar(n).isParameter()) {
parameterUsedInNumberContext = true;
}
}
@ -141,7 +139,7 @@ class Optimizer
private boolean convertParameter(Node n)
{
if (inDirectCallFunction && n.getType() == Token.GETVAR) {
if (OptLocalVariable.get(n).isParameter()) {
if (theFunction.getVar(n).isParameter()) {
n.removeProp(Node.ISNUMBER_PROP);
return true;
}
@ -164,7 +162,7 @@ class Optimizer
return NumberType;
case Token.GETVAR : {
OptLocalVariable theVar = OptLocalVariable.get(n);
OptLocalVariable theVar = theFunction.getVar(n);
if (inDirectCallFunction && theVar.isParameter()) {
n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
return NumberType;
@ -180,7 +178,7 @@ class Optimizer
case Token.DEC : {
Node child = n.getFirstChild(); // will be a GETVAR or GETPROP
if (child.getType() == Token.GETVAR) {
OptLocalVariable theVar = OptLocalVariable.get(child);
OptLocalVariable theVar = theFunction.getVar(child);
if (theVar.isNumber()) {
n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
markDCPNumberContext(child);
@ -196,7 +194,7 @@ class Optimizer
Node lChild = n.getFirstChild();
Node rChild = lChild.getNext();
int rType = rewriteForNumberVariables(rChild);
OptLocalVariable theVar = OptLocalVariable.get(n);
OptLocalVariable theVar = theFunction.getVar(n);
if (inDirectCallFunction && theVar.isParameter()) {
if (rType == NumberType) {
if (!convertParameter(rChild)) {
@ -494,24 +492,8 @@ class Optimizer
}
}
private static void replaceVariableAccess(Node n, OptFunctionNode fn)
{
Node child = n.getFirstChild();
while (child != null) {
replaceVariableAccess(child, fn);
child = child.getNext();
}
int type = n.getType();
if (type == Token.SETVAR) {
String name = n.getFirstChild().getString();
n.putProp(Node.VARIABLE_PROP, fn.getVar(name));
} else if (type == Token.GETVAR) {
String name = n.getString();
n.putProp(Node.VARIABLE_PROP, fn.getVar(name));
}
}
private int itsOptLevel;
private boolean inDirectCallFunction;
OptFunctionNode theFunction;
private boolean parameterUsedInNumberContext;
}