private static void SimpleMerge(VarTypeProcessor typeProcessor, DirectGraph graph , StructMethod mt) { Dictionary <VarVersionPair, VarType> mapExprentMaxTypes = typeProcessor.GetMapExprentMaxTypes (); Dictionary <VarVersionPair, VarType> mapExprentMinTypes = typeProcessor.GetMapExprentMinTypes (); Dictionary <int, HashSet <int> > mapVarVersions = new Dictionary <int, HashSet <int> > (); foreach (VarVersionPair pair in mapExprentMinTypes.Keys) { if (pair.version >= 0) { // don't merge constants mapVarVersions.ComputeIfAbsent(pair.var, (int k) => new HashSet <int>()).Add(pair. version); } } bool is_method_static = mt.HasModifier(ICodeConstants.Acc_Static); Dictionary <VarVersionPair, int> mapMergedVersions = new Dictionary <VarVersionPair , int>(); foreach (KeyValuePair <int, HashSet <int> > ent in mapVarVersions) { if (ent.Value.Count > 1) { List <int> lstVersions = new List <int>(ent.Value); lstVersions.Sort(); for (int i = 0; i < lstVersions.Count; i++) { VarVersionPair firstPair = new VarVersionPair(ent.Key, lstVersions[i]); VarType firstType = mapExprentMinTypes.GetOrNull(firstPair); if (firstPair.var == 0 && firstPair.version == 1 && !is_method_static) { continue; } // don't merge 'this' variable for (int j = i + 1; j < lstVersions.Count; j++) { VarVersionPair secondPair = new VarVersionPair(ent.Key, lstVersions[j]); VarType secondType = mapExprentMinTypes.GetOrNull(secondPair); if (firstType.Equals(secondType) || (firstType.Equals(VarType.Vartype_Null) && secondType .type == ICodeConstants.Type_Object) || (secondType.Equals(VarType.Vartype_Null) && firstType.type == ICodeConstants.Type_Object)) { VarType firstMaxType = mapExprentMaxTypes.GetOrNull(firstPair); VarType secondMaxType = mapExprentMaxTypes.GetOrNull(secondPair); VarType type = firstMaxType == null ? secondMaxType : secondMaxType == null ? firstMaxType : VarType.GetCommonMinType(firstMaxType, secondMaxType); Sharpen.Collections.Put(mapExprentMaxTypes, firstPair, type); Sharpen.Collections.Put(mapMergedVersions, secondPair, firstPair.version); Sharpen.Collections.Remove(mapExprentMaxTypes, secondPair); Sharpen.Collections.Remove(mapExprentMinTypes, secondPair); if (firstType.Equals(VarType.Vartype_Null)) { Sharpen.Collections.Put(mapExprentMinTypes, firstPair, secondType); firstType = secondType; } Sharpen.Collections.Put(typeProcessor.GetMapFinalVars(), firstPair, VarTypeProcessor .Var_Non_Final); lstVersions.RemoveAtReturningValue(j); //noinspection AssignmentToForLoopParameter j--; } } } } } if (!(mapMergedVersions.Count == 0)) { UpdateVersions(graph, mapMergedVersions); } }
private bool ChangeExprentType(Exprent exprent, VarType newType, int minMax) { bool res = true; switch (exprent.type) { case Exprent.Exprent_Const: { ConstExprent constExpr = (ConstExprent)exprent; VarType constType = constExpr.GetConstType(); if (newType.typeFamily > ICodeConstants.Type_Family_Integer || constType.typeFamily > ICodeConstants.Type_Family_Integer) { return(true); } else if (newType.typeFamily == ICodeConstants.Type_Family_Integer) { VarType minInteger = new ConstExprent((int)constExpr.GetValue(), false, null).GetConstType (); if (minInteger.IsStrictSuperset(newType)) { newType = minInteger; } } goto case Exprent.Exprent_Var; } case Exprent.Exprent_Var: { VarVersionPair pair = null; if (exprent.type == Exprent.Exprent_Const) { pair = new VarVersionPair(((ConstExprent)exprent).id, -1); } else if (exprent.type == Exprent.Exprent_Var) { pair = new VarVersionPair((VarExprent)exprent); } if (minMax == 0) { // min VarType currentMinType = mapExprentMinTypes.GetOrNull(pair); VarType newMinType; if (currentMinType == null || newType.typeFamily > currentMinType.typeFamily) { newMinType = newType; } else if (newType.typeFamily < currentMinType.typeFamily) { return(true); } else { newMinType = VarType.GetCommonSupertype(currentMinType, newType); } Sharpen.Collections.Put(mapExprentMinTypes, pair, newMinType); if (exprent.type == Exprent.Exprent_Const) { ((ConstExprent)exprent).SetConstType(newMinType); } if (currentMinType != null && (newMinType.typeFamily > currentMinType.typeFamily || newMinType.IsStrictSuperset(currentMinType))) { return(false); } } else { // max VarType currentMaxType = mapExprentMaxTypes.GetOrNull(pair); VarType newMaxType; if (currentMaxType == null || newType.typeFamily < currentMaxType.typeFamily) { newMaxType = newType; } else if (newType.typeFamily > currentMaxType.typeFamily) { return(true); } else { newMaxType = VarType.GetCommonMinType(currentMaxType, newType); } Sharpen.Collections.Put(mapExprentMaxTypes, pair, newMaxType); } break; } case Exprent.Exprent_Assignment: { return(ChangeExprentType(((AssignmentExprent)exprent).GetRight(), newType, minMax )); } case Exprent.Exprent_Function: { FunctionExprent func = (FunctionExprent)exprent; switch (func.GetFuncType()) { case FunctionExprent.Function_Iif: { // FIXME: res = ChangeExprentType(func.GetLstOperands()[1], newType, minMax) & ChangeExprentType (func.GetLstOperands()[2], newType, minMax); break; } case FunctionExprent.Function_And: case FunctionExprent.Function_Or: case FunctionExprent.Function_Xor: { res = ChangeExprentType(func.GetLstOperands()[0], newType, minMax) & ChangeExprentType (func.GetLstOperands()[1], newType, minMax); break; } } break; } } return(res); }