/* the type of an expression is relatively unknown. Cases we can be sure about are - Literals, Arithmetic operations - always return a Number */ private static int findExpressionType(OptFunctionNode fn, Node n, int[] varTypes) { switch (n.getType()) { case Token.NUMBER: return Optimizer.NumberType; case Token.CALL: case Token.NEW: case Token.REF_CALL: return Optimizer.AnyType; case Token.GETELEM: return 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.LSH: case Token.RSH: case Token.URSH: case Token.SUB: case Token.POS: case Token.NEG: return Optimizer.NumberType; case Token.ARRAYLIT: case Token.OBJECTLIT: return Optimizer.AnyType; // XXX: actually, we know it's not // number, but no type yet for that case Token.ADD: { // 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; // we're not distinguishing strings yet } } Node child = n.getFirstChild(); if (child == null) { return Optimizer.AnyType; } else { int result = Optimizer.NoType; while (child != null) { result |= findExpressionType(fn, child, varTypes); child = child.getNext(); } return result; } }
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(fn, child, varTypes); child = child.getNext(); } break; case Token.DEC: case Token.INC: if (child.getType() == Token.GETVAR) { // theVar is a Number now 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 = fn.getVarIndex(child); assignType(varTypes, i, Optimizer.AnyType); } while (child != null) { result |= findDefPoints(fn, child, varTypes); child = child.getNext(); } break; case Token.SETVAR: { Node rValue = child.getNext(); int theType = findExpressionType(fn, rValue, varTypes); int i = fn.getVarIndex(n); result |= assignType(varTypes, i, theType); break; } } return result; }
/* We're tracking uses and defs - in order to build the def set and to identify the last use nodes. The itsNotDefSet is built reversed then flipped later. */ private void lookForVariableAccess(OptFunctionNode fn, Node n) { switch (n.getType()) { case Token.DEC: case Token.INC: { Node child = n.getFirstChild(); if (child.getType() == Token.GETVAR) { int varIndex = fn.getVarIndex(child); if (!itsNotDefSet.test(varIndex)) itsUseBeforeDefSet.set(varIndex); itsNotDefSet.set(varIndex); } } 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.test(varIndex)) itsUseBeforeDefSet.set(varIndex); } break; default: Node child = n.getFirstChild(); while (child != null) { lookForVariableAccess(fn, child); child = child.getNext(); } break; } }