mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
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:
parent
3487e65a11
commit
9ca481e40b
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user