зеркало из https://github.com/mozilla/gecko-dev.git
Move all logic regarding establishing type of variable into Block.java
This commit is contained in:
Родитель
98b0af3853
Коммит
5a48e9dc3a
|
@ -88,6 +88,19 @@ class Block
|
||||||
|
|
||||||
static void runFlowAnalyzes(OptFunctionNode fn, Node[] statementNodes)
|
static void runFlowAnalyzes(OptFunctionNode fn, Node[] statementNodes)
|
||||||
{
|
{
|
||||||
|
int paramCount = fn.fnode.getParamCount();
|
||||||
|
int varCount = fn.fnode.getParamAndVarCount();
|
||||||
|
int[] varTypes = new int[varCount];
|
||||||
|
// If the variable is a parameter, it could have any type.
|
||||||
|
for (int i = 0; i != paramCount; ++i) {
|
||||||
|
varTypes[i] = Optimizer.AnyType;
|
||||||
|
}
|
||||||
|
// If the variable is from a "var" statement, its typeEvent will be set
|
||||||
|
// when we see the setVar node.
|
||||||
|
for (int i = paramCount; i != varCount; ++i) {
|
||||||
|
varTypes[i] = Optimizer.NoType;
|
||||||
|
}
|
||||||
|
|
||||||
Block[] theBlocks = buildBlocks(statementNodes);
|
Block[] theBlocks = buildBlocks(statementNodes);
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -96,19 +109,23 @@ class Block
|
||||||
System.out.println(toString(theBlocks, statementNodes));
|
System.out.println(toString(theBlocks, statementNodes));
|
||||||
}
|
}
|
||||||
|
|
||||||
reachingDefDataFlow(fn, statementNodes, theBlocks);
|
reachingDefDataFlow(fn, statementNodes, theBlocks, varTypes);
|
||||||
typeFlow(fn, statementNodes, theBlocks);
|
typeFlow(fn, statementNodes, theBlocks, varTypes);
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
for (int i = 0; i < theBlocks.length; i++) {
|
for (int i = 0; i < theBlocks.length; i++) {
|
||||||
System.out.println("For block " + theBlocks[i].itsBlockID);
|
System.out.println("For block " + theBlocks[i].itsBlockID);
|
||||||
theBlocks[i].printLiveOnEntrySet(fn);
|
theBlocks[i].printLiveOnEntrySet(fn);
|
||||||
}
|
}
|
||||||
int N = fn.getVarCount();
|
System.out.println("Variable Table, size = " + varCount);
|
||||||
System.out.println("Variable Table, size = " + N);
|
for (int i = 0; i != varCount; i++) {
|
||||||
for (int i = 0; i != N; i++) {
|
System.out.println("["+i+"] type: "+varTypes[i]);
|
||||||
OptLocalVariable lVar = fn.getVar(i);
|
}
|
||||||
System.out.println(lVar.toString());
|
}
|
||||||
|
|
||||||
|
for (int i = paramCount; i != varCount; i++) {
|
||||||
|
if (varTypes[i] == Optimizer.NumberType) {
|
||||||
|
fn.getVar(i).setIsNumber();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +265,7 @@ class Block
|
||||||
return sw.toString();
|
return sw.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void reachingDefDataFlow(OptFunctionNode fn, Node[] statementNodes, Block theBlocks[])
|
private static void reachingDefDataFlow(OptFunctionNode fn, Node[] statementNodes, Block theBlocks[], int[] varTypes)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
initialize the liveOnEntry and liveOnExit sets, then discover the variables
|
initialize the liveOnEntry and liveOnExit sets, then discover the variables
|
||||||
|
@ -300,10 +317,10 @@ class Block
|
||||||
'undefined'-ness of that variable.
|
'undefined'-ness of that variable.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
theBlocks[0].markAnyTypeVariables(fn);
|
theBlocks[0].markAnyTypeVariables(varTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void typeFlow(OptFunctionNode fn, Node[] statementNodes, Block theBlocks[])
|
private static void typeFlow(OptFunctionNode fn, Node[] statementNodes, Block theBlocks[], int[] varTypes)
|
||||||
{
|
{
|
||||||
boolean visit[] = new boolean[theBlocks.length];
|
boolean visit[] = new boolean[theBlocks.length];
|
||||||
boolean doneOnce[] = new boolean[theBlocks.length];
|
boolean doneOnce[] = new boolean[theBlocks.length];
|
||||||
|
@ -314,7 +331,7 @@ class Block
|
||||||
if (visit[vIndex] || !doneOnce[vIndex]) {
|
if (visit[vIndex] || !doneOnce[vIndex]) {
|
||||||
doneOnce[vIndex] = true;
|
doneOnce[vIndex] = true;
|
||||||
visit[vIndex] = false;
|
visit[vIndex] = false;
|
||||||
if (theBlocks[vIndex].doTypeFlow(statementNodes)) {
|
if (theBlocks[vIndex].doTypeFlow(statementNodes, varTypes)) {
|
||||||
Block succ[] = theBlocks[vIndex].itsSuccessors;
|
Block succ[] = theBlocks[vIndex].itsSuccessors;
|
||||||
if (succ != null) {
|
if (succ != null) {
|
||||||
for (int i = 0; i < succ.length; i++) {
|
for (int i = 0; i < succ.length; i++) {
|
||||||
|
@ -336,23 +353,25 @@ class Block
|
||||||
else
|
else
|
||||||
vIndex++;
|
vIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < fn.getVarCount(); i++) {
|
|
||||||
OptLocalVariable lVar = fn.getVar(i);
|
|
||||||
if (!lVar.isParameter()) {
|
|
||||||
int theType = lVar.getTypeUnion();
|
|
||||||
if (theType == Optimizer.NumberType) {
|
|
||||||
lVar.setIsNumber();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markAnyTypeVariables(OptFunctionNode fn)
|
private static int getVarIndex(Node n)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < fn.getVarCount(); i++)
|
return OptLocalVariable.get(n).getIndex();
|
||||||
if (itsLiveOnEntrySet.test(i))
|
}
|
||||||
fn.getVar(i).assignType(Optimizer.AnyType);
|
|
||||||
|
private static boolean assignType(int[] varTypes, int index, int type)
|
||||||
|
{
|
||||||
|
return type != (varTypes[index] |= type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markAnyTypeVariables(int[] varTypes)
|
||||||
|
{
|
||||||
|
for (int i = 0; i != varTypes.length; i++) {
|
||||||
|
if (itsLiveOnEntrySet.test(i)) {
|
||||||
|
assignType(varTypes, i, Optimizer.AnyType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,10 +391,10 @@ class Block
|
||||||
{
|
{
|
||||||
Node child = n.getFirstChild();
|
Node child = n.getFirstChild();
|
||||||
if (child.getType() == Token.GETVAR) {
|
if (child.getType() == Token.GETVAR) {
|
||||||
int theVarIndex = OptLocalVariable.get(child).getIndex();
|
int varIndex = getVarIndex(child);
|
||||||
if (!itsNotDefSet.test(theVarIndex))
|
if (!itsNotDefSet.test(varIndex))
|
||||||
itsUseBeforeDefSet.set(theVarIndex);
|
itsUseBeforeDefSet.set(varIndex);
|
||||||
itsNotDefSet.set(theVarIndex);
|
itsNotDefSet.set(varIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -384,16 +403,14 @@ class Block
|
||||||
Node lhs = n.getFirstChild();
|
Node lhs = n.getFirstChild();
|
||||||
Node rhs = lhs.getNext();
|
Node rhs = lhs.getNext();
|
||||||
lookForVariableAccess(rhs);
|
lookForVariableAccess(rhs);
|
||||||
OptLocalVariable theVar = OptLocalVariable.get(n);
|
itsNotDefSet.set(getVarIndex(n));
|
||||||
int theVarIndex = theVar.getIndex();
|
|
||||||
itsNotDefSet.set(theVarIndex);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Token.GETVAR :
|
case Token.GETVAR :
|
||||||
{
|
{
|
||||||
int theVarIndex = OptLocalVariable.get(n).getIndex();
|
int varIndex = getVarIndex(n);
|
||||||
if (!itsNotDefSet.test(theVarIndex))
|
if (!itsNotDefSet.test(varIndex))
|
||||||
itsUseBeforeDefSet.set(theVarIndex);
|
itsUseBeforeDefSet.set(varIndex);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
|
@ -447,7 +464,7 @@ class Block
|
||||||
Literals,
|
Literals,
|
||||||
Arithmetic operations - always return a Number
|
Arithmetic operations - always return a Number
|
||||||
*/
|
*/
|
||||||
private static int findExpressionType(Node n)
|
private static int findExpressionType(Node n, int[] varTypes)
|
||||||
{
|
{
|
||||||
switch (n.getType()) {
|
switch (n.getType()) {
|
||||||
case Token.NUMBER :
|
case Token.NUMBER :
|
||||||
|
@ -461,7 +478,7 @@ class Block
|
||||||
return Optimizer.AnyType;
|
return Optimizer.AnyType;
|
||||||
|
|
||||||
case Token.GETVAR :
|
case Token.GETVAR :
|
||||||
return OptLocalVariable.get(n).getTypeUnion();
|
return varTypes[getVarIndex(n)];
|
||||||
|
|
||||||
case Token.INC :
|
case Token.INC :
|
||||||
case Token.DEC :
|
case Token.DEC :
|
||||||
|
@ -480,8 +497,8 @@ class Block
|
||||||
// if the lhs & rhs are known to be numbers, we can be sure that's
|
// if the lhs & rhs are known to be numbers, we can be sure that's
|
||||||
// the result, otherwise it could be a string.
|
// the result, otherwise it could be a string.
|
||||||
Node child = n.getFirstChild();
|
Node child = n.getFirstChild();
|
||||||
int lType = findExpressionType(child);
|
int lType = findExpressionType(child, varTypes);
|
||||||
int rType = findExpressionType(child.getNext());
|
int rType = findExpressionType(child.getNext(), varTypes);
|
||||||
return lType | rType; // we're not distinguishng strings yet
|
return lType | rType; // we're not distinguishng strings yet
|
||||||
}
|
}
|
||||||
default : {
|
default : {
|
||||||
|
@ -491,7 +508,7 @@ class Block
|
||||||
else {
|
else {
|
||||||
int result = Optimizer.NoType;
|
int result = Optimizer.NoType;
|
||||||
while (child != null) {
|
while (child != null) {
|
||||||
result |= findExpressionType(child);
|
result |= findExpressionType(child, varTypes);
|
||||||
child = child.getNext();
|
child = child.getNext();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -500,66 +517,60 @@ class Block
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean findDefPoints(Node n)
|
private static boolean findDefPoints(Node n, int[] varTypes)
|
||||||
{
|
{
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
Node child = n.getFirstChild();
|
||||||
switch (n.getType()) {
|
switch (n.getType()) {
|
||||||
default : {
|
default : {
|
||||||
Node child = n.getFirstChild();
|
|
||||||
while (child != null) {
|
while (child != null) {
|
||||||
result |= findDefPoints(child);
|
result |= findDefPoints(child, varTypes);
|
||||||
child = child.getNext();
|
child = child.getNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Token.DEC :
|
case Token.DEC :
|
||||||
case Token.INC : {
|
case Token.INC : {
|
||||||
Node firstChild = n.getFirstChild();
|
if (child.getType() == Token.GETVAR) {
|
||||||
if (firstChild.getType() == Token.GETVAR) {
|
|
||||||
// theVar is a Number now
|
// theVar is a Number now
|
||||||
OptLocalVariable theVar = OptLocalVariable.get(firstChild);
|
int i = getVarIndex(child);
|
||||||
result |= theVar.assignType(Optimizer.NumberType);
|
result |= assignType(varTypes, i, Optimizer.NumberType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Token.SETPROP :
|
case Token.SETPROP :
|
||||||
case Token.SETPROP_OP : {
|
case Token.SETPROP_OP : {
|
||||||
Node baseChild = n.getFirstChild();
|
if (child.getType() == Token.GETVAR) {
|
||||||
Node nameChild = baseChild.getNext();
|
int i = getVarIndex(child);
|
||||||
Node rhs = nameChild.getNext();
|
assignType(varTypes, i, Optimizer.AnyType);
|
||||||
if (baseChild != null) {
|
}
|
||||||
if (baseChild.getType() == Token.GETVAR) {
|
while (child != null) {
|
||||||
OptLocalVariable theVar = OptLocalVariable.get(baseChild);
|
result |= findDefPoints(child, varTypes);
|
||||||
theVar.assignType(Optimizer.AnyType);
|
child = child.getNext();
|
||||||
}
|
|
||||||
result |= findDefPoints(baseChild);
|
|
||||||
}
|
}
|
||||||
if (nameChild != null) result |= findDefPoints(nameChild);
|
|
||||||
if (rhs != null) result |= findDefPoints(rhs);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Token.SETVAR : {
|
case Token.SETVAR : {
|
||||||
Node firstChild = n.getFirstChild();
|
Node rValue = child.getNext();
|
||||||
OptLocalVariable theVar = OptLocalVariable.get(n);
|
int theType = findExpressionType(rValue, varTypes);
|
||||||
Node rValue = firstChild.getNext();
|
int i = getVarIndex(n);
|
||||||
int theType = findExpressionType(rValue);
|
result |= assignType(varTypes, i, theType);
|
||||||
result |= theVar.assignType(theType);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doTypeFlow(Node[] statementNodes)
|
private boolean doTypeFlow(Node[] statementNodes, int[] varTypes)
|
||||||
{
|
{
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
||||||
for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) {
|
for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) {
|
||||||
Node n = statementNodes[i];
|
Node n = statementNodes[i];
|
||||||
if (n != null)
|
if (n != null)
|
||||||
changed |= findDefPoints(n);
|
changed |= findDefPoints(n, varTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
|
|
|
@ -46,10 +46,6 @@ final class OptLocalVariable implements JavaVariable
|
||||||
{
|
{
|
||||||
itsName = name;
|
itsName = name;
|
||||||
itsIsParameter = isParameter;
|
itsIsParameter = isParameter;
|
||||||
// If the variable is a parameter, it could have any type.
|
|
||||||
// If it is from a "var" statement, its typeEvent will be set
|
|
||||||
// when we see the setVar node.
|
|
||||||
itsTypeUnion = isParameter ? Optimizer.AnyType : Optimizer.NoType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static OptLocalVariable get(Node n)
|
static OptLocalVariable get(Node n)
|
||||||
|
@ -112,15 +108,6 @@ final class OptLocalVariable implements JavaVariable
|
||||||
|
|
||||||
boolean isParameter() { return itsIsParameter; }
|
boolean isParameter() { return itsIsParameter; }
|
||||||
|
|
||||||
boolean assignType(int aType) {
|
|
||||||
itsTypeUnion |= aType;
|
|
||||||
return itsTypeUnion != aType;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getTypeUnion() {
|
|
||||||
return itsTypeUnion;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String itsName;
|
private String itsName;
|
||||||
private boolean itsIsParameter;
|
private boolean itsIsParameter;
|
||||||
private int itsIndex = -1;
|
private int itsIndex = -1;
|
||||||
|
@ -129,7 +116,5 @@ final class OptLocalVariable implements JavaVariable
|
||||||
|
|
||||||
private boolean itsIsNumber;
|
private boolean itsIsNumber;
|
||||||
|
|
||||||
private int itsTypeUnion; // the union of all assigned types
|
|
||||||
|
|
||||||
private int initPC;
|
private int initPC;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче