| 1063 | } |
| 1064 | |
| 1065 | private static List<LocalVariableNode> createLocalVariables(InsnList il, StateRecorder rec, BitSet entryPoints, Map<AbstractInsnNode, int[]> exitPoints, List<LocalVariableNode> orig) { |
| 1066 | if (rec.locals.length == 0) return Collections.emptyList(); |
| 1067 | |
| 1068 | int[] lvToVar = new int[rec.locals.length]; |
| 1069 | int[] varToLv = new int[rec.locals.length]; |
| 1070 | int[] startIndices = new int[rec.locals.length]; |
| 1071 | int[] endIndices = new int[rec.locals.length]; |
| 1072 | int varCount = 0; |
| 1073 | int firstNonContiguous = Integer.MAX_VALUE; |
| 1074 | int idx = 0; |
| 1075 | |
| 1076 | // determine variables for each linear control flow block |
| 1077 | while ((idx = entryPoints.nextSetBit(idx)) != -1) { |
| 1078 | Arrays.fill(lvToVar, -1); |
| 1079 | |
| 1080 | if (varCount != 0 && firstNonContiguous == Integer.MAX_VALUE) { // not the first iteration and we branched, vars may need merging |
| 1081 | firstNonContiguous = varCount; |
| 1082 | } |
| 1083 | |
| 1084 | // determine variables for the current linear control flow block |
| 1085 | boolean cont; |
| 1086 | |
| 1087 | do { |
| 1088 | ExecState state = rec.getState(idx); |
| 1089 | |
| 1090 | for (int lvi = 0; lvi < state.locals.length; lvi++) { |
| 1091 | ClassInstance vt = state.locals[lvi]; |
| 1092 | |
| 1093 | if (vt == null || vt == rec.common.TOP) { |
| 1094 | lvToVar[lvi] = -1; // var left scope |
| 1095 | continue; |
| 1096 | } |
| 1097 | |
| 1098 | int vi = lvToVar[lvi]; |
| 1099 | |
| 1100 | if (vi == -1 || rec.getState(startIndices[vi]).locals[lvi] != vt) { // no existing variable or incompatible type -> create new variable |
| 1101 | if (varCount >= startIndices.length) { |
| 1102 | varToLv = Arrays.copyOf(varToLv, varToLv.length * 2); |
| 1103 | startIndices = Arrays.copyOf(startIndices, startIndices.length * 2); |
| 1104 | endIndices = Arrays.copyOf(endIndices, endIndices.length * 2); |
| 1105 | } |
| 1106 | |
| 1107 | vi = varCount++; |
| 1108 | lvToVar[lvi] = vi; |
| 1109 | varToLv[vi] = lvi; |
| 1110 | startIndices[vi] = idx; |
| 1111 | } |
| 1112 | |
| 1113 | endIndices[vi] = idx; |
| 1114 | } |
| 1115 | |
| 1116 | AbstractInsnNode ain = il.get(idx); |
| 1117 | idx++; |
| 1118 | |
| 1119 | if (!exitPoints.containsKey(ain)) { // linear control flow |
| 1120 | cont = true; |
| 1121 | } else { // check for linear-like control flow (can continue at the next instruction, same locals at all branch targets) |
| 1122 | cont = false; |