private static object[] IterateChildExprent(Exprent exprent, Exprent parent, Exprent next, Dictionary <VarVersionPair, Exprent> mapVarValues, SSAUConstructorSparseEx ssau) { bool changed = false; foreach (Exprent expr in exprent.GetAllExprents()) { var oldExpr = expr; while (true) { object[] arr = IterateChildExprent(oldExpr, parent, next, mapVarValues, ssau); Exprent retexpr = (Exprent)arr[0]; changed |= (bool)arr[1]; bool isReplaceable = (bool)arr[2]; if (retexpr != null) { if (isReplaceable) { ReplaceSingleVar(exprent, (VarExprent)oldExpr, retexpr, ssau); oldExpr = retexpr; } else { exprent.ReplaceExprent(oldExpr, retexpr); } changed = true; } if (!isReplaceable) { break; } } } Exprent dest = IsReplaceableVar(exprent, mapVarValues); if (dest != null) { return(new object[] { dest, true, true }); } VarExprent left = null; Exprent right = null; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)exprent; if (@as.GetLeft().type == Exprent.Exprent_Var) { left = (VarExprent)@as.GetLeft(); right = @as.GetRight(); } } if (left == null) { return(new object[] { null, changed, false }); } bool isHeadSynchronized = false; if (next == null && parent.type == Exprent.Exprent_Monitor) { MonitorExprent monexpr = (MonitorExprent)parent; if (monexpr.GetMonType() == MonitorExprent.Monitor_Enter && exprent.Equals(monexpr .GetValue())) { isHeadSynchronized = true; } } // stack variable or synchronized head exprent if (!left.IsStack() && !isHeadSynchronized) { return(new object[] { null, changed, false }); } VarVersionPair leftpaar = new VarVersionPair(left); List <VarVersionNode> usedVers = new List <VarVersionNode>(); bool notdom = GetUsedVersions(ssau, leftpaar, usedVers); if (!notdom && (usedVers.Count == 0)) { return(new object[] { right, changed, false }); } // stack variables only if (!left.IsStack()) { return(new object[] { null, changed, false }); } int useflags = right.GetExprentUse(); if ((useflags & Exprent.Both_Flags) != Exprent.Both_Flags) { return(new object[] { null, changed, false }); } Dictionary <int, HashSet <VarVersionPair> > mapVars = GetAllVarVersions(leftpaar, right , ssau); if (mapVars.ContainsKey(leftpaar.var) && notdom) { return(new object[] { null, changed, false }); } Sharpen.Collections.Remove(mapVars, leftpaar.var); HashSet <VarVersionPair> setAllowedVars = GetAllVersions(parent); if (next != null) { Sharpen.Collections.AddAll(setAllowedVars, GetAllVersions(next)); } bool vernotreplaced = false; HashSet <VarVersionPair> setTempUsedVers = new HashSet <VarVersionPair>(); foreach (VarVersionNode usedvar in usedVers) { VarVersionPair usedver = new VarVersionPair(usedvar.var, usedvar.version); if (IsVersionToBeReplaced(usedver, mapVars, ssau, leftpaar) && (right.type == Exprent .Exprent_Var || setAllowedVars.Contains(usedver))) { setTempUsedVers.Add(usedver); } else { vernotreplaced = true; } } if (!notdom && !vernotreplaced) { foreach (VarVersionPair usedver in setTempUsedVers) { Exprent copy = right.Copy(); if (right.type == Exprent.Exprent_Field && ssau.GetMapFieldVars().ContainsKey(right .id)) { Sharpen.Collections.Put(ssau.GetMapFieldVars(), copy.id, ssau.GetMapFieldVars().GetOrNullable (right.id)); } Sharpen.Collections.Put(mapVarValues, usedver, copy); } // remove assignment return(new object[] { right, changed, false }); } return(new object[] { null, changed, false }); }
private int[] IterateExprent(List <Exprent> lstExprents, int index, Exprent next, Dictionary <VarVersionPair, Exprent> mapVarValues, SSAUConstructorSparseEx ssau) { Exprent exprent = lstExprents[index]; int changed = 0; foreach (Exprent expr in exprent.GetAllExprents()) { var oldExpr = expr; while (true) { object[] arr = IterateChildExprent(oldExpr, exprent, next, mapVarValues, ssau); Exprent retexpr = (Exprent)arr[0]; changed |= (bool)arr[1] ? 1 : 0; bool isReplaceable = (bool)arr[2]; if (retexpr != null) { if (isReplaceable) { ReplaceSingleVar(exprent, (VarExprent)oldExpr, retexpr, ssau); oldExpr = retexpr; } else { exprent.ReplaceExprent(oldExpr, retexpr); } changed = 1; } if (!isReplaceable) { break; } } } // no var on the highest level, so no replacing VarExprent left = null; Exprent right = null; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)exprent; if (@as.GetLeft().type == Exprent.Exprent_Var) { left = (VarExprent)@as.GetLeft(); right = @as.GetRight(); } } if (left == null) { return(new int[] { -1, changed }); } VarVersionPair leftpaar = new VarVersionPair(left); List <VarVersionNode> usedVers = new List <VarVersionNode>(); bool notdom = GetUsedVersions(ssau, leftpaar, usedVers); if (!notdom && (usedVers.Count == 0)) { if (left.IsStack() && (right.type == Exprent.Exprent_Invocation || right.type == Exprent.Exprent_Assignment || right.type == Exprent.Exprent_New)) { if (right.type == Exprent.Exprent_New) { // new Object(); permitted NewExprent nexpr = (NewExprent)right; if (nexpr.IsAnonymous() || nexpr.GetNewType().arrayDim > 0 || nexpr.GetNewType(). type != ICodeConstants.Type_Object) { return(new int[] { -1, changed }); } } lstExprents[index] = right; return(new int[] { index + 1, 1 }); } else if (right.type == Exprent.Exprent_Var) { lstExprents.RemoveAtReturningValue(index); return(new int[] { index, 1 }); } else { return(new int[] { -1, changed }); } } int useflags = right.GetExprentUse(); // stack variables only if (!left.IsStack() && (right.type != Exprent.Exprent_Var || ((VarExprent)right). IsStack())) { // special case catch(... ex) return(new int[] { -1, changed }); } if ((useflags & Exprent.Multiple_Uses) == 0 && (notdom || usedVers.Count > 1)) { return(new int[] { -1, changed }); } Dictionary <int, HashSet <VarVersionPair> > mapVars = GetAllVarVersions(leftpaar, right , ssau); bool isSelfReference = mapVars.ContainsKey(leftpaar.var); if (isSelfReference && notdom) { return(new int[] { -1, changed }); } HashSet <VarVersionPair> setNextVars = next == null ? null : GetAllVersions(next); // FIXME: fix the entire method! if (right.type != Exprent.Exprent_Const && right.type != Exprent.Exprent_Var && setNextVars != null && mapVars.ContainsKey(leftpaar.var)) { foreach (VarVersionNode usedvar in usedVers) { if (!setNextVars.Contains(new VarVersionPair(usedvar.var, usedvar.version))) { return(new int[] { -1, changed }); } } } Sharpen.Collections.Remove(mapVars, leftpaar.var); bool vernotreplaced = false; bool verreplaced = false; HashSet <VarVersionPair> setTempUsedVers = new HashSet <VarVersionPair>(); foreach (VarVersionNode usedvar in usedVers) { VarVersionPair usedver = new VarVersionPair(usedvar.var, usedvar.version); if (IsVersionToBeReplaced(usedver, mapVars, ssau, leftpaar) && (right.type == Exprent .Exprent_Const || right.type == Exprent.Exprent_Var || right.type == Exprent.Exprent_Field || setNextVars == null || setNextVars.Contains(usedver))) { setTempUsedVers.Add(usedver); verreplaced = true; } else { vernotreplaced = true; } } if (isSelfReference && vernotreplaced) { return(new int[] { -1, changed }); } else { foreach (VarVersionPair usedver in setTempUsedVers) { Exprent copy = right.Copy(); if (right.type == Exprent.Exprent_Field && ssau.GetMapFieldVars().ContainsKey(right .id)) { Sharpen.Collections.Put(ssau.GetMapFieldVars(), copy.id, ssau.GetMapFieldVars().GetOrNullable (right.id)); } Sharpen.Collections.Put(mapVarValues, usedver, copy); } } if (!notdom && !vernotreplaced) { // remove assignment lstExprents.RemoveAtReturningValue(index); return(new int[] { index, 1 }); } else if (verreplaced) { return(new int[] { index + 1, changed }); } else { return(new int[] { -1, changed }); } }