private static int FindExpressionType(OptFunctionNode fn, Node n, int[] varTypes) { switch (n.GetType()) { case Token.NUMBER: { return Rhino.Optimizer.Optimizer.NumberType; } case Token.CALL: case Token.NEW: case Token.REF_CALL: { return Rhino.Optimizer.Optimizer.AnyType; } case Token.GETELEM: case Token.GETPROP: case Token.NAME: case Token.THIS: { return Rhino.Optimizer.Optimizer.AnyType; } case Token.GETVAR: { return varTypes[fn.GetVarIndex(n)]; } case Token.INC: case Token.DEC: case Token.MUL: case Token.DIV: case Token.MOD: case Token.BITOR: case Token.BITXOR: case Token.BITAND: case Token.BITNOT: case Token.LSH: case Token.RSH: case Token.URSH: case Token.SUB: case Token.POS: case Token.NEG: { return Rhino.Optimizer.Optimizer.NumberType; } case Token.VOID: { // NYI: undefined type return Rhino.Optimizer.Optimizer.AnyType; } case Token.FALSE: case Token.TRUE: case Token.EQ: case Token.NE: case Token.LT: case Token.LE: case Token.GT: case Token.GE: case Token.SHEQ: case Token.SHNE: case Token.NOT: case Token.INSTANCEOF: case Token.IN: case Token.DEL_REF: case Token.DELPROP: { // NYI: boolean type return Rhino.Optimizer.Optimizer.AnyType; } case Token.STRING: case Token.TYPEOF: case Token.TYPEOFNAME: { // NYI: string type return Rhino.Optimizer.Optimizer.AnyType; } case Token.NULL: case Token.REGEXP: case Token.ARRAYCOMP: case Token.ARRAYLIT: case Token.OBJECTLIT: { return Rhino.Optimizer.Optimizer.AnyType; } case Token.ADD: { // XXX: actually, we know it's not // number, but no type yet for that // 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(fn, child, varTypes); int rType = FindExpressionType(fn, child.GetNext(), varTypes); return lType | rType; } case Token.HOOK: { // we're not distinguishing strings yet Node ifTrue = n.GetFirstChild().GetNext(); Node ifFalse = ifTrue.GetNext(); int ifTrueType = FindExpressionType(fn, ifTrue, varTypes); int ifFalseType = FindExpressionType(fn, ifFalse, varTypes); return ifTrueType | ifFalseType; } case Token.COMMA: case Token.SETVAR: case Token.SETNAME: case Token.SETPROP: case Token.SETELEM: { return FindExpressionType(fn, n.GetLastChild(), varTypes); } case Token.AND: case Token.OR: { Node child = n.GetFirstChild(); int lType = FindExpressionType(fn, child, varTypes); int rType = FindExpressionType(fn, child.GetNext(), varTypes); return lType | rType; } } return Rhino.Optimizer.Optimizer.AnyType; }
private static bool FindDefPoints(OptFunctionNode fn, Node n, int[] varTypes) { bool result = false; Node first = n.GetFirstChild(); for (Node next = first; next != null; next = next.GetNext()) { result |= FindDefPoints(fn, next, varTypes); } switch (n.GetType()) { case Token.DEC: case Token.INC: { if (first.GetType() == Token.GETVAR) { // theVar is a Number now int i = fn.GetVarIndex(first); result |= AssignType(varTypes, i, Rhino.Optimizer.Optimizer.NumberType); } break; } case Token.SETVAR: { Node rValue = first.GetNext(); int theType = FindExpressionType(fn, rValue, varTypes); int i = fn.GetVarIndex(n); result |= AssignType(varTypes, i, theType); break; } } return result; }
private void LookForVariableAccess(OptFunctionNode fn, Node n) { switch (n.GetType()) { case Token.TYPEOFNAME: { // TYPEOFNAME may be used with undefined names, which is why // this is handled separately from GETVAR above. int varIndex = fn.fnode.GetIndexForNameNode(n); if (varIndex > -1 && !itsNotDefSet.Get(varIndex)) { itsUseBeforeDefSet.Set(varIndex); } break; } case Token.DEC: case Token.INC: { Node child = n.GetFirstChild(); if (child.GetType() == Token.GETVAR) { int varIndex = fn.GetVarIndex(child); if (!itsNotDefSet.Get(varIndex)) { itsUseBeforeDefSet.Set(varIndex); } itsNotDefSet.Set(varIndex); } else { LookForVariableAccess(fn, child); } break; } case Token.SETVAR: { Node lhs = n.GetFirstChild(); Node rhs = lhs.GetNext(); LookForVariableAccess(fn, rhs); itsNotDefSet.Set(fn.GetVarIndex(n)); break; } case Token.GETVAR: { int varIndex = fn.GetVarIndex(n); if (!itsNotDefSet.Get(varIndex)) { itsUseBeforeDefSet.Set(varIndex); } break; } default: { Node child_1 = n.GetFirstChild(); while (child_1 != null) { LookForVariableAccess(fn, child_1); child_1 = child_1.GetNext(); } break; } } }