public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { // DEBUG = // clazz.getName().equals("abc/Def") && // method.getName(clazz).equals("abc"); // TODO: Remove this when the code has stabilized. // Catch any unexpected exceptions from the actual visiting method. try { // Process the code. visitCodeAttribute0(clazz, method, codeAttribute); } catch (RuntimeException ex) { System.err.println("Unexpected error while computing stack sizes:"); System.err.println(" Class = [" + clazz.getName() + "]"); System.err.println( " Method = [" + method.getName(clazz) + method.getDescriptor(clazz) + "]"); System.err.println( " Exception = [" + ex.getClass().getName() + "] (" + ex.getMessage() + ")"); if (DEBUG) { method.accept(clazz, new ClassPrinter()); } throw ex; } }
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { // Get the original parameter size that was saved. int oldParameterSize = ParameterUsageMarker.getParameterSize(method); // Compute the new parameter size from the shrunk descriptor. int newParameterSize = ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz), method.getAccessFlags()); if (oldParameterSize > newParameterSize) { // Get the total size of the local variable frame. int maxLocals = codeAttribute.u2maxLocals; if (DEBUG) { System.out.println( "ParameterShrinker: " + clazz.getName() + "." + method.getName(clazz) + method.getDescriptor(clazz)); System.out.println(" Old parameter size = " + oldParameterSize); System.out.println(" New parameter size = " + newParameterSize); System.out.println(" Max locals = " + maxLocals); } // Create a variable map. int[] variableMap = new int[maxLocals]; // Move unused parameters right after the parameter block. int usedParameterIndex = 0; int unusedParameterIndex = newParameterSize; for (int parameterIndex = 0; parameterIndex < oldParameterSize; parameterIndex++) { // Is the variable required as a parameter? if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) { // Keep the variable as a parameter. variableMap[parameterIndex] = usedParameterIndex++; } else { if (DEBUG) { System.out.println(" Deleting parameter #" + parameterIndex); } // Shift the variable to the unused parameter block, // in case it is still used as a variable. variableMap[parameterIndex] = unusedParameterIndex++; // Visit the method, if required. if (extraVariableMemberVisitor != null) { method.accept(clazz, extraVariableMemberVisitor); } } } // Fill out the remainder of the map. for (int variableIndex = oldParameterSize; variableIndex < maxLocals; variableIndex++) { variableMap[variableIndex] = variableIndex; } // Set the map. variableRemapper.setVariableMap(variableMap); // Remap the variables. variableRemapper.visitCodeAttribute(clazz, method, codeAttribute); } }
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { // DEBUG = // clazz.getName().equals("abc/Def") && // method.getName(clazz).equals("abc"); if (DEBUG) { method.accept(clazz, new ClassPrinter()); } branchTargetFinder.visitCodeAttribute(clazz, method, codeAttribute); // Don't bother if there aren't any subroutines anyway. if (!containsSubroutines(codeAttribute)) { return; } if (DEBUG) { System.out.println( "SubroutineInliner: processing [" + clazz.getName() + "." + method.getName(clazz) + method.getDescriptor(clazz) + "]"); } // Append the body of the code. codeAttributeComposer.reset(); codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength); // Copy the non-subroutine instructions. int offset = 0; while (offset < codeAttribute.u4codeLength) { Instruction instruction = InstructionFactory.create(codeAttribute.code, offset); int instructionLength = instruction.length(offset); // Is this returning subroutine? if (branchTargetFinder.isSubroutine(offset) && branchTargetFinder.isSubroutineReturning(offset)) { // Skip the subroutine. if (DEBUG) { System.out.println( " Skipping original subroutine instruction " + instruction.toString(offset)); } // Append a label at this offset instead. codeAttributeComposer.appendLabel(offset); } else { // Copy the instruction, inlining any subroutine call recursively. instruction.accept(clazz, method, codeAttribute, offset, this); } offset += instructionLength; } // Copy the exceptions. Note that exceptions with empty try blocks // are automatically removed. codeAttribute.exceptionsAccept(clazz, method, subroutineExceptionInliner); if (DEBUG) { System.out.println(" Appending label after code at [" + offset + "]"); } // Append a label just after the code. codeAttributeComposer.appendLabel(codeAttribute.u4codeLength); // End and update the code attribute. codeAttributeComposer.endCodeFragment(); codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute); if (DEBUG) { method.accept(clazz, new ClassPrinter()); } }
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { if (codeAttribute.u4codeLength > 1) { method.accept(clazz, UsageMarker.this); } }