// Generated method, skip
continue;
}
// Signatures names
CodeAttribute codeAttribute = (CodeAttribute) method.getMethodInfo().getAttribute("Code");
if (codeAttribute == null || javassist.Modifier.isAbstract(method.getModifiers())) {
continue;
}
LocalVariableAttribute localVariableAttribute = (LocalVariableAttribute) codeAttribute.getAttribute("LocalVariableTable");
List<T2<Integer, String>> parameterNames = new ArrayList<T2<Integer, String>>();
if (localVariableAttribute == null) {
if (method.getParameterTypes().length > 0)
continue;
} else {
if (localVariableAttribute.tableLength() < method.getParameterTypes().length + (Modifier.isStatic(method.getModifiers()) ? 0 : 1)) {
Logger.warn("weird: skipping method %s %s as its number of local variables is incorrect (lv=%s || lv.length=%s || params.length=%s || (isStatic? %s)", method.getReturnType().getName(), method.getLongName(), localVariableAttribute, localVariableAttribute != null ? localVariableAttribute.tableLength() : -1, method.getParameterTypes().length, Modifier.isStatic(method.getModifiers()));
}
for (int i = 0; i < localVariableAttribute.tableLength(); i++) {
if (!localVariableAttribute.variableName(i).equals("__stackRecorder")) {
parameterNames.add(new T2<Integer, String>(localVariableAttribute.startPc(i) + localVariableAttribute.index(i), localVariableAttribute.variableName(i)));
}
}
Collections.sort(parameterNames, new Comparator<T2<Integer, String>>() {
public int compare(T2<Integer, String> o1, T2<Integer, String> o2) {
return o1._1.compareTo(o2._1);
}
});
}
List<String> names = new ArrayList<String>();
for (int i = 0; i < method.getParameterTypes().length + (Modifier.isStatic(method.getModifiers()) ? 0 : 1); i++) {
if (localVariableAttribute == null) {
continue;
}
try {
String name = parameterNames.get(i)._2;
if (!name.equals("this")) {
names.add(name);
}
} catch (Exception e) {
Logger.warn(e, "While applying localvariables to %s.%s, param %s", ctClass.getName(), method.getName(), i);
}
}
StringBuilder iv = new StringBuilder();
if (names.isEmpty()) {
iv.append("new String[0];");
} else {
iv.append("new String[] {");
for (Iterator<String> i = names.iterator(); i.hasNext(); ) {
iv.append("\"");
String aliasedName = i.next();
if (aliasedName.contains("$")) {
aliasedName = aliasedName.substring(0, aliasedName.indexOf("$"));
}
iv.append(aliasedName);
iv.append("\"");
if (i.hasNext()) {
iv.append(",");
}
}
iv.append("};");
}
String sigField = "$" + method.getName() + LocalVariablesNamesTracer.computeMethodHash(method.getParameterTypes());
try { // #1198
ctClass.getDeclaredField(sigField);
} catch (NotFoundException nfe) {
CtField signature = CtField.make("public static String[] " + sigField + " = " + iv.toString(), ctClass);
ctClass.addField(signature);
}
if (localVariableAttribute == null || isScala(applicationClass)) {
continue;
}
// OK.
// Here after each local variable creation instruction,
// we insert a call to yalp.utils.LocalVariables.addVariable('var', var)
// without breaking everything...
for (int i = 0; i < localVariableAttribute.tableLength(); i++) {
// name of the local variable
String name = localVariableAttribute.getConstPool().getUtf8Info(localVariableAttribute.nameIndex(i));
// Normalize the variable name
// For several reasons, both variables name and name$1 will be aliased to name
String aliasedName = name;
if (aliasedName.contains("$")) {
aliasedName = aliasedName.substring(0, aliasedName.indexOf("$"));
}
if (name.equals("this")) {
continue;
}
/* DEBUG
IO.write(ctClass.toBytecode(), new File("/tmp/lv_"+applicationClass.name+".class"));
ctClass.defrost();
*/
try {
// The instruction at which this local variable has been created
Integer pc = localVariableAttribute.startPc(i);
// Move to the next instruction (insertionPc)
CodeIterator codeIterator = codeAttribute.iterator();
codeIterator.move(pc);
pc = codeIterator.next();
Bytecode b = makeBytecodeForLVStore(method, localVariableAttribute.signature(i), name, localVariableAttribute.index(i));
codeIterator.insert(pc, b.get());
codeAttribute.setMaxStack(codeAttribute.computeMaxStack());
// Bon chaque instruction de cette méthode
while (codeIterator.hasNext()) {
int index = codeIterator.next();
int op = codeIterator.byteAt(index);
// DEBUG
// printOp(op);
int varNumber = -1;
// The variable changes
if (storeByCode.containsKey(op)) {
varNumber = storeByCode.get(op);
if (varNumber == -2) {
varNumber = codeIterator.byteAt(index + 1);
}
}
// Si c'est un store de la variable en cours d'examination
// et que c'est dans la frame d'utilisation de cette variable on trace l'affectation.
// (en fait la frame commence à localVariableAttribute.startPc(i)-1 qui est la première affectation
// mais aussi l'initialisation de la variable qui est deja tracé plus haut, donc on commence à localVariableAttribute.startPc(i))
if (varNumber == localVariableAttribute.index(i) && index < localVariableAttribute.startPc(i) + localVariableAttribute.codeLength(i)) {
b = makeBytecodeForLVStore(method, localVariableAttribute.signature(i), aliasedName, varNumber);
codeIterator.insertEx(b.get());
codeAttribute.setMaxStack(codeAttribute.computeMaxStack());
}
}
} catch (Exception e) {
// Well probably a compiled optimizer (I hope so)
}