Index: src/main/java/org/apache/harmony/pack200/BcBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/BcBands.java (revision 608803) +++ src/main/java/org/apache/harmony/pack200/BcBands.java (working copy) @@ -25,7 +25,9 @@ import org.apache.harmony.pack200.bytecode.Attribute; import org.apache.harmony.pack200.bytecode.BCIRenumberedAttribute; import org.apache.harmony.pack200.bytecode.ByteCode; +import org.apache.harmony.pack200.bytecode.CPClass; import org.apache.harmony.pack200.bytecode.CodeAttribute; +import org.apache.harmony.pack200.bytecode.ExceptionTableEntry; import org.apache.harmony.pack200.bytecode.OperandManager; /** @@ -365,23 +367,46 @@ int i = 0; ArrayList orderedCodeAttributes = segment.getClassBands().getOrderedCodeAttributes(); + + // Exception table fields + int[] handlerCount = segment.getClassBands().getCodeHandlerCount(); + int[][] handlerStartPCs = segment.getClassBands().getCodeHandlerStartP(); + int[][] handlerEndPCs = segment.getClassBands().getCodeHandlerEndPO(); + int[][] handlerCatchPCs = segment.getClassBands().getCodeHandlerCatchPO(); + String[][] handlerClassTypes = segment.getClassBands().getCodeHandlerClassRCN(); + for (int c = 0; c < classCount; c++) { - int numberOfMethods = methodFlags[c].length; - for (int m = 0; m < numberOfMethods; m++) { - long methodFlag = methodFlags[c][m]; - if (!abstractModifier.matches(methodFlag) - && !nativeModifier.matches(methodFlag)) { - int maxStack = codeMaxStack[i]; - int maxLocal = codeMaxNALocals[i]; - if (!staticModifier.matches(methodFlag)) - maxLocal++; // one for 'this' parameter - maxLocal += SegmentUtils.countArgs(methodDescr[c][m]); - operandManager.setCurrentClass(segment.getClassBands().getClassThis()[c]); - operandManager.setSuperClass(segment.getClassBands().getClassSuper()[c]); - CodeAttribute codeAttr = new CodeAttribute(maxStack, maxLocal, - methodByteCodePacked[c][m], segment, operandManager); - methodAttributes[c][m].add(codeAttr); - // Should I add all the attributes in here? + int numberOfMethods = methodFlags[c].length; + for (int m = 0; m < numberOfMethods; m++) { + long methodFlag = methodFlags[c][m]; + if (!abstractModifier.matches(methodFlag) + && !nativeModifier.matches(methodFlag)) { + int maxStack = codeMaxStack[i]; + int maxLocal = codeMaxNALocals[i]; + if (!staticModifier.matches(methodFlag)) + maxLocal++; // one for 'this' parameter + maxLocal += SegmentUtils.countArgs(methodDescr[c][m]); + operandManager.setCurrentClass(segment.getClassBands() + .getClassThis()[c]); + operandManager.setSuperClass(segment.getClassBands() + .getClassSuper()[c]); + List exceptionTable = new ArrayList(); + if(handlerCount != null) { + for (int j = 0; j < handlerCount[i]; j++) { + String handlerClass = handlerClassTypes[i][j]; + CPClass cpHandlerClass = new CPClass(handlerClass); + ExceptionTableEntry entry = new ExceptionTableEntry( + handlerStartPCs[i][j], handlerEndPCs[i][j], + handlerCatchPCs[i][j], cpHandlerClass); + exceptionTable.add(entry); + } + } + CodeAttribute codeAttr = new CodeAttribute(maxStack, + maxLocal, methodByteCodePacked[c][m], segment, + operandManager, exceptionTable); + methodAttributes[c][m].add(codeAttr); + codeAttr.renumber(codeAttr.byteCodeOffsets); + // Should I add all the attributes in here? ArrayList currentAttributes = (ArrayList)orderedCodeAttributes.get(i); for(int index=0;index < currentAttributes.size(); index++) { Attribute currentAttribute = (Attribute)currentAttributes.get(index); Index: src/main/java/org/apache/harmony/pack200/ClassBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/ClassBands.java (revision 608803) +++ src/main/java/org/apache/harmony/pack200/ClassBands.java (working copy) @@ -92,6 +92,14 @@ private int[] methodAttrCalls; + private int[][] codeHandlerStartP; + + private int[][] codeHandlerEndPO; + + private int[][] codeHandlerCatchPO; + + private String[][] codeHandlerClassRCN; + /** * @param segment */ @@ -667,18 +675,29 @@ throw new IllegalStateException("Shouldn't get here either"); } } - int sumCodeHandlerCount = 0; - for (int i = 0; i < codeHandlerCount.length; i++) { - sumCodeHandlerCount += codeHandlerCount[i]; + codeHandlerStartP = decodeBandInt("code_handler_start_P", in, + Codec.BCI5, codeHandlerCount); + codeHandlerEndPO = decodeBandInt("code_handler_end_PO", in, + Codec.BRANCH5, codeHandlerCount); + codeHandlerCatchPO = decodeBandInt("code_handler_catch_PO", in, + Codec.BRANCH5, codeHandlerCount); + int[][] codeHandlerClassRCNints = decodeBandInt("code_handler_class_RCN", in, + Codec.UNSIGNED5, codeHandlerCount); + // The codeHandlerClassRCN band contains incremented references to + // cp_Class so we can't use parseReferences(..) here. + String[] cpClass = cpBands.getCpClass(); + codeHandlerClassRCN = new String[codeHandlerClassRCNints.length][]; + for (int i = 0; i < codeHandlerClassRCNints.length; i++) { + codeHandlerClassRCN[i] = new String[codeHandlerClassRCNints[i].length]; + for (int j = 0; j < codeHandlerClassRCNints[i].length; j++) { + int handlerClassReference = codeHandlerClassRCNints[i][j]; + if(handlerClassReference == 0) { + codeHandlerClassRCN[i][j] = null; + } else { + codeHandlerClassRCN[i][j] = cpClass[handlerClassReference - 1]; + } + } } - int[] codeHandlerStartP = decodeBandInt("code_handler_start_P", in, - Codec.BCI5, sumCodeHandlerCount); - int[] codeHandlerEndPO = decodeBandInt("code_handler_end_PO", in, - Codec.BRANCH5, sumCodeHandlerCount); - int[] codeHandlerCatchPO = decodeBandInt("code_handler_catch_PO", in, - Codec.BRANCH5, sumCodeHandlerCount); - int[] codeHandlerClassRCN = decodeBandInt("code_handler_class_RCN", in, - Codec.UNSIGNED5, sumCodeHandlerCount); int codeFlagsCount = segment.getSegmentHeader().getOptions() .hasAllCodeFlags() ? codeCount : codeSpecialHeader; @@ -1229,4 +1248,24 @@ return classVersionMinor; } + public int[] getCodeHandlerCount() { + return codeHandlerCount; + } + + public int[][] getCodeHandlerCatchPO() { + return codeHandlerCatchPO; + } + + public String[][] getCodeHandlerClassRCN() { + return codeHandlerClassRCN; + } + + public int[][] getCodeHandlerEndPO() { + return codeHandlerEndPO; + } + + public int[][] getCodeHandlerStartP() { + return codeHandlerStartP; + } + } Index: src/main/java/org/apache/harmony/pack200/bytecode/CodeAttribute.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/CodeAttribute.java (revision 608794) +++ src/main/java/org/apache/harmony/pack200/bytecode/CodeAttribute.java (working copy) @@ -24,7 +24,7 @@ import org.apache.harmony.pack200.Segment; -public class CodeAttribute extends Attribute { +public class CodeAttribute extends BCIRenumberedAttribute { public List attributes = new ArrayList(); // instances public List byteCodeOffsets = new ArrayList(); @@ -30,7 +30,7 @@ public List byteCodeOffsets = new ArrayList(); public List byteCodes = new ArrayList(); public int codeLength; - public List exceptionTable = new ArrayList(); // of ExceptionTableEntry + public List exceptionTable; // of ExceptionTableEntry public int maxLocals; public int maxStack; @@ -35,7 +35,7 @@ public int maxStack; public CodeAttribute(int maxStack, int maxLocals, byte codePacked[], - Segment segment, OperandManager operandManager) { + Segment segment, OperandManager operandManager, List exceptionTable) { super("Code"); //$NON-NLS-1$ this.maxLocals = maxLocals; this.maxStack = maxStack; @@ -40,6 +40,7 @@ this.maxLocals = maxLocals; this.maxStack = maxStack; this.codeLength = 0; + this.exceptionTable = exceptionTable; byteCodeOffsets.add(new Integer(0)); for (int i = 0; i < codePacked.length; i++) { ByteCode byteCode = ByteCode.getByteCode(codePacked[i] & 0xff); @@ -119,6 +120,10 @@ ByteCode byteCode = (ByteCode) it.next(); byteCode.resolve(pool); } + for (Iterator iter = exceptionTable.iterator(); iter.hasNext();) { + ExceptionTableEntry entry = (ExceptionTableEntry) iter.next(); + entry.resolve(pool); + } } public String toString() { @@ -156,4 +161,16 @@ public List attributes() { return attributes; } + + protected int[] getStartPCs() { + // Do nothing here as we've overriden renumber + return null; + } + + public void renumber(List byteCodeOffsets) { + for (Iterator iter = exceptionTable.iterator(); iter.hasNext();) { + ExceptionTableEntry entry = (ExceptionTableEntry) iter.next(); + entry.renumber(byteCodeOffsets); + } + } } Index: src/main/java/org/apache/harmony/pack200/bytecode/ExceptionTableEntry.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/ExceptionTableEntry.java (revision 596578) +++ src/main/java/org/apache/harmony/pack200/bytecode/ExceptionTableEntry.java (working copy) @@ -18,18 +18,44 @@ import java.io.DataOutputStream; import java.io.IOException; +import java.util.List; public class ExceptionTableEntry { - public int catchType; - public int endPC; - public int handlerPC; - public int startPC; + private int startPC; + private int endPC; + private int handlerPC; + private CPClass catchType; + + private int startPcRenumbered; + private int endPcRenumbered; + private int handlerPcRenumbered; + private int catchTypeIndex; + + public ExceptionTableEntry(int startPC, int endPC, int handlerPC, CPClass catchType) { + this.startPC = startPC; + this.endPC = endPC; + this.handlerPC = handlerPC; + this.catchType = catchType; + } public void write(DataOutputStream dos) throws IOException { - dos.writeShort(startPC); - dos.writeShort(endPC); - dos.writeShort(handlerPC); - dos.writeShort(catchType); + dos.writeShort(startPcRenumbered); + dos.writeShort(endPcRenumbered); + dos.writeShort(handlerPcRenumbered); + dos.writeShort(catchTypeIndex); } + + public void renumber(List byteCodeOffsets) { + startPcRenumbered = ((Integer)byteCodeOffsets.get(startPC)).intValue(); + int endPcIndex = startPC + endPC; + endPcRenumbered = ((Integer)byteCodeOffsets.get(endPcIndex)).intValue(); + int handlerPcIndex = endPcIndex + handlerPC; + handlerPcRenumbered = ((Integer)byteCodeOffsets.get(handlerPcIndex)).intValue(); + } + + public void resolve(ClassConstantPool pool) { + catchType.resolve(pool); + catchTypeIndex = pool.indexOf(catchType); + } } Index: src/test/java/org/apache/harmony/pack200/tests/CodeAttributeTest.java =================================================================== --- src/test/java/org/apache/harmony/pack200/tests/CodeAttributeTest.java (revision 608795) +++ src/test/java/org/apache/harmony/pack200/tests/CodeAttributeTest.java (working copy) @@ -16,6 +16,9 @@ */ package org.apache.harmony.pack200.tests; +import java.util.ArrayList; +import java.util.List; + import junit.framework.TestCase; import org.apache.harmony.pack200.CpBands; @@ -35,9 +38,8 @@ public MockCodeAttribute(int maxStack, int maxLocals, byte[] codePacked, Segment segment, - OperandManager operandManager) { - super(maxStack, maxLocals, codePacked, segment, operandManager); - // TODO Auto-generated constructor stub + OperandManager operandManager, List exceptionTable) { + super(maxStack, maxLocals, codePacked, segment, operandManager, exceptionTable); } public int getLength() { @@ -146,7 +148,8 @@ 2, // maxLocals mixedByteArray, // codePacked segment, // segment - operandManager // operandManager + operandManager, // operandManager + new ArrayList() ); assertEquals(29, attribute.getLength()); @@ -164,7 +167,8 @@ 2, // maxLocals mixedByteArray, // codePacked segment, // segment - operandManager // operandManager + operandManager, // operandManager + new ArrayList() ); assertEquals(2, attribute.maxLocals); assertEquals(3, attribute.maxStack); @@ -187,7 +191,8 @@ 3, // maxLocals singleByteArray, // codePacked segment, // segment - operandManager // operandManager + operandManager, // operandManager + new ArrayList() ); assertEquals(3, attribute.maxLocals); assertEquals(4, attribute.maxStack);