Return-Path: Delivered-To: apmail-harmony-commits-archive@www.apache.org Received: (qmail 39279 invoked from network); 4 Jan 2008 10:11:12 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 4 Jan 2008 10:11:12 -0000 Received: (qmail 78020 invoked by uid 500); 4 Jan 2008 10:11:01 -0000 Delivered-To: apmail-harmony-commits-archive@harmony.apache.org Received: (qmail 77927 invoked by uid 500); 4 Jan 2008 10:11:01 -0000 Mailing-List: contact commits-help@harmony.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@harmony.apache.org Delivered-To: mailing list commits@harmony.apache.org Received: (qmail 77918 invoked by uid 99); 4 Jan 2008 10:11:01 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 04 Jan 2008 02:11:01 -0800 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 04 Jan 2008 10:10:45 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 26B791A9838; Fri, 4 Jan 2008 02:10:50 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r608790 [1/2] - in /harmony/enhanced/classlib/trunk/modules/pack200/src: main/java/org/apache/harmony/pack200/ main/java/org/apache/harmony/pack200/bytecode/ main/java/org/apache/harmony/pack200/bytecode/forms/ test/java/org/apache/harmony/... Date: Fri, 04 Jan 2008 10:10:36 -0000 To: commits@harmony.apache.org From: tellison@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080104101050.26B791A9838@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: tellison Date: Fri Jan 4 02:10:32 2008 New Revision: 608790 URL: http://svn.apache.org/viewvc?rev=608790&view=rev Log: Apply patch HARMONY-5368 ([pack200][classlib] Completed instructions / started sorting / branch5) Added: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/VariableInstructionForm.java (with props) Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentConstantPool.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentUtils.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/Attribute.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPClass.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPDouble.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFieldRef.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFloat.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPInteger.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPInterfaceMethodRef.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPLong.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPMember.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPMethodRef.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPNameAndType.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPRef.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPString.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPUTF8.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CodeAttribute.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ConstantPoolEntry.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/LineNumberTableAttribute.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/LocalVariableTableAttribute.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/OperandManager.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/SourceFileAttribute.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/IMethodRefForm.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/LookupSwitchForm.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/SwitchForm.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/TableSwitchForm.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/WideForm.java harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BcBandsTest.java harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/CodeAttributeTest.java harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/SegmentUtilsTest.java harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/bytecode/ClassFileEntryTest.java harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/bytecode/ConstantPoolTest.java Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java Fri Jan 4 02:10:32 2008 @@ -26,6 +26,7 @@ import org.apache.harmony.pack200.bytecode.CPInteger; import org.apache.harmony.pack200.bytecode.CPLong; import org.apache.harmony.pack200.bytecode.CPUTF8; +import org.apache.harmony.pack200.bytecode.ClassConstantPool; public abstract class BandSet { @@ -451,7 +452,7 @@ if (index < 0 || index >= reference.length) throw new Pack200Exception( "Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length); - result[i1] = new CPUTF8(reference[index]); + result[i1] = new CPUTF8(reference[index], ClassConstantPool.DOMAIN_UNDEFINED); } return result; } @@ -472,7 +473,7 @@ if (index < 0 || index >= reference.length) throw new Pack200Exception( "Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length); - result1[i1] = new CPUTF8(reference[index]); + result1[i1] = new CPUTF8(reference[index], ClassConstantPool.DOMAIN_UNDEFINED); } CPUTF8[] refs = result1; int pos = 0; Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java Fri Jan 4 02:10:32 2008 @@ -21,6 +21,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.List; import org.apache.harmony.pack200.bytecode.Attribute; import org.apache.harmony.pack200.bytecode.BCIRenumberedAttribute; @@ -40,7 +41,7 @@ // The bands // TODO: Haven't resolved references yet. Do we want to? private int[] bcCaseCount; - private int[][] bcCaseValue; + private int[] bcCaseValue; private int[] bcByte; private int[] bcLocal; private int[] bcShort; @@ -126,6 +127,9 @@ AttributeLayout.CONTEXT_METHOD); methodByteCodePacked = new byte[classCount][][]; int bcParsed = 0; + + List switchIsTableSwitch = new ArrayList(); + List wideByteCodes = new ArrayList(); for (int c = 0; c < classCount; c++) { int numberOfMethods = methodFlags[c].length; methodByteCodePacked[c] = new byte[numberOfMethods][]; @@ -200,7 +204,12 @@ bcLabelCount++; break; case 170: // tableswitch + switchIsTableSwitch.add(new Boolean(true)); + bcCaseCountCount++; + bcLabelCount++; + break; case 171: // lookupswitch + switchIsTableSwitch.add(new Boolean(false)); bcCaseCountCount++; bcLabelCount++; break; @@ -260,6 +269,7 @@ break; case 196: // wide int nextInstruction = 0xff & methodByteCodePacked[c][m][i+1]; + wideByteCodes.add(new Integer(nextInstruction)); if (nextInstruction == 132) { // iinc bcLocalCount += 2; bcShortCount++; @@ -299,9 +309,16 @@ // other bytecode bands debug("Parsed *bc_codes (" + bcParsed + ")"); bcCaseCount = decodeBandInt("bc_case_count", in, Codec.UNSIGNED5, bcCaseCountCount); - // TODO HACK HACK: Not sure how this should be done. - // bcCaseValue = decodeBandInt("bc_case_value", in, Codec.DELTA5, new int[]{1} /* to test tableswitch */); - bcCaseValue = decodeBandInt("bc_case_value", in, Codec.DELTA5, bcCaseCount /* to test lookupswitch */); + int bcCaseValueCount = 0; + for (int i = 0; i < bcCaseCount.length; i++) { + boolean isTableSwitch = ((Boolean)switchIsTableSwitch.get(i)).booleanValue(); + if(isTableSwitch) { + bcCaseValueCount += 1; + } else { + bcCaseValueCount += bcCaseCount[i]; + } + } + bcCaseValue = decodeBandInt("bc_case_value", in, Codec.DELTA5, bcCaseValueCount ); // Every case value needs a label. We weren't able to count these // above, because we didn't know how many cases there were. // Have to correct it now. @@ -345,11 +362,15 @@ bcEscSize = decodeBandInt("bc_escsize", in, Codec.UNSIGNED5, bcEscCount); bcEscByte = decodeBandInt("bc_escbyte", in, Codec.BYTE1, bcEscSize); + int[] wideByteCodeArray = new int[wideByteCodes.size()]; + for(int index=0; index < wideByteCodeArray.length; index++) { + wideByteCodeArray[index] = ((Integer)wideByteCodes.get(index)).intValue(); + } OperandManager operandManager = new OperandManager(bcCaseCount, bcCaseValue, bcByte, bcShort, bcLocal, bcLabel, bcIntRef, bcFloatRef, bcLongRef, bcDoubleRef, bcStringRef, bcClassRef, bcFieldRef, bcMethodRef, bcIMethodRef, bcThisField, bcSuperField, bcThisMethod, bcSuperMethod, - bcInitRef); + bcInitRef, wideByteCodeArray); operandManager.setSegment(segment); int i = 0; @@ -365,28 +386,19 @@ if (!staticModifier.matches(methodFlag)) maxLocal++; // one for 'this' parameter maxLocal += SegmentUtils.countArgs(methodDescr[c][m]); - // TODO Move creation of code attribute until after constant - // pool resolved operandManager.setCurrentClass(segment.getClassBands().getClassThis()[c]); operandManager.setSuperClass(segment.getClassBands().getClassSuper()[c]); - CodeAttribute attr = new CodeAttribute(maxStack, maxLocal, + CodeAttribute codeAttr = new CodeAttribute(maxStack, maxLocal, methodByteCodePacked[c][m], segment, operandManager); - methodAttributes[c][m].add(attr); + methodAttributes[c][m].add(codeAttr); // 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); - // TODO: The line below adds the LocalVariableTable - // and LineNumber attributes. Currently things are - // broken because these tables don't get renumbered - // properly. Commenting out the add so the class files - // will verify. - // if(currentAttribute.getClass() == LineNumberTableAttribute.class) { - attr.attributes.add(currentAttribute); - // } + codeAttr.addAttribute(currentAttribute); // Fix up the line numbers if needed if(currentAttribute.hasBCIRenumbering()) { - ((BCIRenumberedAttribute)currentAttribute).renumber(attr.byteCodeOffsets); + ((BCIRenumberedAttribute)currentAttribute).renumber(codeAttr.byteCodeOffsets); } } i++; @@ -417,7 +429,7 @@ return bcCaseCount; } - public int[][] getBcCaseValue() { + public int[] getBcCaseValue() { return bcCaseValue; } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java Fri Jan 4 02:10:32 2008 @@ -26,6 +26,7 @@ import org.apache.harmony.pack200.bytecode.Attribute; import org.apache.harmony.pack200.bytecode.CPClass; import org.apache.harmony.pack200.bytecode.CPUTF8; +import org.apache.harmony.pack200.bytecode.ClassConstantPool; import org.apache.harmony.pack200.bytecode.ConstantValueAttribute; import org.apache.harmony.pack200.bytecode.ExceptionsAttribute; import org.apache.harmony.pack200.bytecode.LineNumberTableAttribute; @@ -199,7 +200,7 @@ int colon = desc.indexOf(':'); String type = desc.substring(colon + 1); CPUTF8 value = new CPUTF8((String) signatureLayout.getValue(result, type, - cpBands.getConstantPool())); + cpBands.getConstantPool()), ClassConstantPool.DOMAIN_SIGNATUREASCIIZ); fieldAttributes[i][j] .add(new SignatureAttribute(value)); signatureIndex++; @@ -651,6 +652,22 @@ "code_LocalVariableTable_slot", in, Codec.UNSIGNED5, localVariableTableN); + // Fix up localVariableTableTypeRS - for some reason, + // native signatures end up in DOMAINNORMALASCIIZ + // while nonnatives end up in DOMAINSIGNATUREASCIIZ. + // TODO: is this the right thing to do? + for(int x=0; x < localVariableTableTypeRS.length; x++) { + for(int y=0; y < localVariableTableTypeRS[x].length; y++) { + CPUTF8 element = localVariableTableTypeRS[x][y]; + // TODO: come up with a better test for native vs nonnative signatures? + if(element.underlyingString().length() > 2) { + element.setDomain(ClassConstantPool.DOMAIN_SIGNATUREASCIIZ); + } else { + element.setDomain(ClassConstantPool.DOMAIN_NORMALASCIIZ); + } + } + } + int lengthLocalVariableTypeTableNBand = SegmentUtils.countMatches( codeFlags, localVariableTypeTableLayout); int[] localVariableTypeTableN = decodeBandInt( @@ -715,7 +732,7 @@ for (int i = 0; i < strings.length; i++) { cpUTF8s[i] = new CPUTF8[strings[i].length]; for (int j = 0; j < strings[i].length; j++) { - cpUTF8s[i][j] = new CPUTF8(strings[i][j]); + cpUTF8s[i][j] = new CPUTF8(strings[i][j], ClassConstantPool.DOMAIN_NORMALASCIIZ); } } return cpUTF8s; @@ -726,7 +743,7 @@ private CPUTF8[] stringsToCPUTF8(String[] strings) { CPUTF8[] cpUTF8s = new CPUTF8[strings.length]; for (int i = 0; i < strings.length; i++) { - cpUTF8s[i] = new CPUTF8(strings[i]); + cpUTF8s[i] = new CPUTF8(strings[i], ClassConstantPool.DOMAIN_UNDEFINED); } return cpUTF8s; } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentConstantPool.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentConstantPool.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentConstantPool.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentConstantPool.java Fri Jan 4 02:10:32 2008 @@ -28,6 +28,7 @@ import org.apache.harmony.pack200.bytecode.CPMethodRef; import org.apache.harmony.pack200.bytecode.CPString; import org.apache.harmony.pack200.bytecode.CPUTF8; +import org.apache.harmony.pack200.bytecode.ClassConstantPool; import org.apache.harmony.pack200.bytecode.ConstantPoolEntry; public class SegmentConstantPool { @@ -230,7 +231,7 @@ } else if (index < 0) { throw new Pack200Exception("Cannot have a negative range"); } else if (cp == UTF_8) { - return new CPUTF8(bands.getCpUTF8()[index]); + return new CPUTF8(bands.getCpUTF8()[index], ClassConstantPool.DOMAIN_NORMALASCIIZ); } else if (cp == CP_INT) { return new CPInteger(new Integer(bands.getCpInt()[index])); } else if (cp == CP_FLOAT) { Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentUtils.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentUtils.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentUtils.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentUtils.java Fri Jan 4 02:10:32 2008 @@ -20,29 +20,81 @@ public final class SegmentUtils { public static int countArgs(String descriptor) { - int bra = descriptor.indexOf("("); - int ket = descriptor.indexOf(")"); - if (bra == -1 || ket == -1 || ket < bra) - throw new IllegalArgumentException("No arguments"); + return countArgs(descriptor, 1); +// int bra = descriptor.indexOf("("); +// int ket = descriptor.indexOf(")"); +// if (bra == -1 || ket == -1 || ket < bra) +// throw new IllegalArgumentException("No arguments"); +// +// boolean inType = false; +// int count = 0; +// for (int i = bra + 1; i < ket; i++) { +// char charAt = descriptor.charAt(i); +// if (inType && charAt == ';') { +// inType = false; +// } else if (!inType && charAt == 'L') { +// inType = true; +// count++; +// } else if (charAt == '[' || inType) { +// // NOP +// } else { +// count++; +// } +// } +// return count; + } - boolean inType = false; - int count = 0; - for (int i = bra + 1; i < ket; i++) { - char charAt = descriptor.charAt(i); - if (inType && charAt == ';') { - inType = false; - } else if (!inType && charAt == 'L') { - inType = true; - count++; - } else if (charAt == '[' || inType) { - // NOP - } else { - count++; - } - } - return count; + public static int countInvokeInterfaceArgs(String descriptor) { + return countArgs(descriptor, 2); } + + /** + * Count the number of arguments in the descriptor. Each + * long or double counts as widthOfLongsAndDoubles; all other + * arguments count as 1. + * @param descriptor String for which arguments are counted + * @param widthOfLongsAndDoubles int increment to apply for longs + * doubles. This is typically 1 when counting arguments alone, + * or 2 when counting arguments for invokeinterface. + * @return integer count + */ + protected static int countArgs(String descriptor, int widthOfLongsAndDoubles) { + int bra = descriptor.indexOf("("); + int ket = descriptor.indexOf(")"); + if (bra == -1 || ket == -1 || ket < bra) + throw new IllegalArgumentException("No arguments"); + boolean inType = false; + boolean consumingNextType = false; + int count = 0; + for (int i = bra + 1; i < ket; i++) { + char charAt = descriptor.charAt(i); + if (inType && charAt == ';') { + inType = false; + consumingNextType = false; + } else if (!inType && charAt == 'L') { + inType = true; + count++; + } else if (charAt == '[') { + consumingNextType = true; + } else if(inType) { + // NOP + } else { + if(consumingNextType) { + count++; + consumingNextType = false; + } else { + if(charAt == 'D' || charAt == 'J') { + count+=widthOfLongsAndDoubles; + } else { + count++; + } + } + } + } + return count; + } + public static int countMatches(long[] flags, IMatcher matcher) { int count = 0; for (int i = 0; i < flags.length; i++) { Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/Attribute.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/Attribute.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/Attribute.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/Attribute.java Fri Jan 4 02:10:32 2008 @@ -25,7 +25,7 @@ private int attributeNameIndex; public Attribute(String attributeName) { - this.attributeName = new CPUTF8(attributeName); + this.attributeName = new CPUTF8(attributeName, ClassConstantPool.DOMAIN_ATTRIBUTEASCIIZ); } protected void doWrite(DataOutputStream dos) throws IOException { Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPClass.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPClass.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPClass.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPClass.java Fri Jan 4 02:10:32 2008 @@ -30,7 +30,8 @@ public CPClass(String name) { super(ConstantPoolEntry.CP_Class); this.name = name; - this.utf8 = new CPUTF8(name); + this.domain = ClassConstantPool.DOMAIN_CLASSREF; + this.utf8 = new CPUTF8(name, ClassConstantPool.DOMAIN_NORMALASCIIZ); } @@ -84,4 +85,9 @@ protected void writeBody(DataOutputStream dos) throws IOException { dos.writeShort(index); } + + public String comparisonString() { + return getName(); + } + } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPDouble.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPDouble.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPDouble.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPDouble.java Fri Jan 4 02:10:32 2008 @@ -22,6 +22,7 @@ public class CPDouble extends CPConstantNumber { public CPDouble(java.lang.Double value) { super(ConstantPoolEntry.CP_Double,value); + this.domain = ClassConstantPool.DOMAIN_DOUBLE; } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFieldRef.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFieldRef.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFieldRef.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFieldRef.java Fri Jan 4 02:10:32 2008 @@ -30,6 +30,7 @@ transient int nameAndTypeIndex; public CPFieldRef(String className, String descriptor) { super(ConstantPoolEntry.CP_Fieldref); + this.domain = ClassConstantPool.DOMAIN_FIELD; this.className = new CPClass(className); this.nameAndType = new CPNameAndType(descriptor); } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFloat.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFloat.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFloat.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFloat.java Fri Jan 4 02:10:32 2008 @@ -22,6 +22,7 @@ public class CPFloat extends CPConstantNumber { public CPFloat(java.lang.Float value) { super(ConstantPoolEntry.CP_Float,value); + this.domain = ClassConstantPool.DOMAIN_FLOAT; } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPInteger.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPInteger.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPInteger.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPInteger.java Fri Jan 4 02:10:32 2008 @@ -23,6 +23,7 @@ public CPInteger(java.lang.Integer value) { super(ConstantPoolEntry.CP_Integer,value); + this.domain = ClassConstantPool.DOMAIN_INTEGER; } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPInterfaceMethodRef.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPInterfaceMethodRef.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPInterfaceMethodRef.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPInterfaceMethodRef.java Fri Jan 4 02:10:32 2008 @@ -20,6 +20,18 @@ public CPInterfaceMethodRef(String className, String descriptor) { super(ConstantPoolEntry.CP_InterfaceMethodref, className, descriptor); + this.domain = ClassConstantPool.DOMAIN_METHOD; } + /** + * This method answers the value this method will use + * for an invokeinterface call. This is equal to 1 + the + * count of all the args, where longs and doubles count for + * 2 and all others count for 1. + * + * @return integer count + */ + public int invokeInterfaceCount() { + return nameAndType.invokeInterfaceCount(); + } } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPLong.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPLong.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPLong.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPLong.java Fri Jan 4 02:10:32 2008 @@ -23,6 +23,7 @@ public CPLong(java.lang.Long value) { super(ConstantPoolEntry.CP_Long,value); + this.domain = ClassConstantPool.DOMAIN_LONG; } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPMember.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPMember.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPMember.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPMember.java Fri Jan 4 02:10:32 2008 @@ -38,8 +38,8 @@ transient int descriptorIndex; public CPMember(String descriptor, long flags, List attributes) { int colon = descriptor.indexOf(':'); - this.name = new CPUTF8(descriptor.substring(0,colon)); - this.descriptor = new CPUTF8(descriptor.substring(colon+1)); + this.name = new CPUTF8(descriptor.substring(0,colon), ClassConstantPool.DOMAIN_NORMALASCIIZ); + this.descriptor = new CPUTF8(descriptor.substring(colon+1), ClassConstantPool.DOMAIN_SIGNATUREASCIIZ); this.flags = (short) flags; this.attributes = (attributes == null ? new ArrayList() : attributes); } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPMethodRef.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPMethodRef.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPMethodRef.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPMethodRef.java Fri Jan 4 02:10:32 2008 @@ -25,6 +25,7 @@ super(ConstantPoolEntry.CP_Methodref, className, descriptor); this.className = new CPClass(className); this.descriptor = new CPNameAndType(descriptor); + this.domain = ClassConstantPool.DOMAIN_METHOD; } protected ClassFileEntry[] getNestedClassFileEntries() { Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPNameAndType.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPNameAndType.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPNameAndType.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPNameAndType.java Fri Jan 4 02:10:32 2008 @@ -19,6 +19,8 @@ import java.io.DataOutputStream; import java.io.IOException; +import org.apache.harmony.pack200.SegmentUtils; + public class CPNameAndType extends ConstantPoolEntry { @@ -32,9 +34,35 @@ public CPNameAndType(String descriptor) { super(ConstantPoolEntry.CP_NameAndType); + int descriptorDomain = ClassConstantPool.DOMAIN_UNDEFINED; int colon = descriptor.indexOf(':'); - this.name = new CPUTF8(descriptor.substring(0,colon)); - this.descriptor = new CPUTF8(descriptor.substring(colon+1)); + String nameString = descriptor.substring(0,colon); + String descriptorString = descriptor.substring(colon+1); + // For some reason, descriptors which have just plain + // native types are stored in DOMAIN_NORMALASCIIZ rather + // than in DOMAIN_SIGNATUREASCIIZ. This might indicate + // that DOMAIN_SIGNATUREASCIIZ is poorly named. + boolean nativeDescriptor = true; + for(int index=0; index < descriptorString.length(); index++) { + char currentChar = descriptorString.charAt(index); + if(Character.isLetter(currentChar)) { + if(currentChar == 'L') { + nativeDescriptor = false; + } + break; + } + } + this.domain = ClassConstantPool.DOMAIN_NAMEANDTYPE; + this.name = new CPUTF8(nameString, ClassConstantPool.DOMAIN_NORMALASCIIZ); + if((nameString.equals("")) || (nameString.equals("")) || nativeDescriptor ) { + // Signatures for init methods are stored with the init methods. + // Not sure why. Similarly, native signatures are stored + // there as well. + descriptorDomain = ClassConstantPool.DOMAIN_NORMALASCIIZ; + } else { + descriptorDomain = ClassConstantPool.DOMAIN_SIGNATUREASCIIZ; + } + this.descriptor = new CPUTF8(descriptorString, descriptorDomain); } protected ClassFileEntry[] getNestedClassFileEntries() { @@ -94,4 +122,14 @@ return true; } + /** + * Answers the invokeinterface count argument when the + * receiver is treated as an invokeinterface target. + * This value is not meaningful if the receiver is not + * an invokeinterface target. + * @return count + */ + public int invokeInterfaceCount() { + return 1 + SegmentUtils.countInvokeInterfaceArgs(descriptor.underlyingString()); + } } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPRef.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPRef.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPRef.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPRef.java Fri Jan 4 02:10:32 2008 @@ -24,7 +24,7 @@ CPClass className; transient int classNameIndex; - private final CPNameAndType nameAndType; + protected final CPNameAndType nameAndType; transient int nameAndTypeIndex; public CPRef(byte type, String className, String descriptor) { Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPString.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPString.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPString.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPString.java Fri Jan 4 02:10:32 2008 @@ -25,7 +25,8 @@ public CPString(java.lang.String value) { super(ConstantPoolEntry.CP_String,value); - this.name = new CPUTF8((String) getValue()); + this.domain = ClassConstantPool.DOMAIN_STRING; + this.name = new CPUTF8((String) getValue(), ClassConstantPool.DOMAIN_NORMALASCIIZ); } @@ -53,4 +54,7 @@ return new ClassFileEntry[] { name }; } + public String comparisonString() { + return (String)getValue(); + } } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPUTF8.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPUTF8.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPUTF8.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPUTF8.java Fri Jan 4 02:10:32 2008 @@ -23,9 +23,10 @@ public class CPUTF8 extends ConstantPoolEntry { private String utf8; - public CPUTF8(String utf8) { + public CPUTF8(String utf8, int domain) { super(ConstantPoolEntry.CP_UTF8); this.utf8 = utf8; + this.domain = domain; } @@ -74,4 +75,25 @@ dos.write(bytes); } + public String underlyingString() { + return utf8; + } + + public String comparisonString() { + String returnValue = utf8; + if(utf8.endsWith(";")) { + StringBuffer alphaChars = new StringBuffer(); + StringBuffer extraChars = new StringBuffer(); + extraChars.append((char)0xFFFF); + for(int index=0; index < utf8.length(); index++) { + if( (utf8.charAt(index) == '(') || (utf8.charAt(index) == ')') || (utf8.charAt(index) == '[') || (utf8.charAt(index) == ']') ) { + extraChars.append(utf8.charAt(index)); + } else { + alphaChars.append(utf8.charAt(index)); + } + } + returnValue = alphaChars.toString() + extraChars.toString(); + } + return returnValue; + } } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java Fri Jan 4 02:10:32 2008 @@ -18,9 +18,13 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; +import org.apache.harmony.pack200.bytecode.ConstantPoolEntry; import org.apache.harmony.pack200.Pack200Exception; import org.apache.harmony.pack200.Segment; @@ -28,6 +32,58 @@ public class ClassConstantPool { + + class PoolComparator implements Comparator { + /* (non-Javadoc) + * Note: this comparator imposes orderings that are inconsistent with equals. + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + public int compare(Object o1, Object o2) { + // If we compare anything other than ConstantPoolEntries + // with this comparator, it is an error. + ConstantPoolEntry cpe1 = (ConstantPoolEntry)o1; + ConstantPoolEntry cpe2 = (ConstantPoolEntry)o2; + + int domain1 = cpe1.getDomain(); + int domain2 = cpe2.getDomain(); + + if(domain1 < domain2) { + return -1; + } + if(domain1 > domain2) { + return 1; + } + + // Domains must be the same, need to compare + // based on name. + // TODO: what means name? + String compare1 = cpe1.comparisonString(); + String compare2 = cpe2.comparisonString(); + return compare1.compareTo(compare2); +// if(cpe1.creationOrder < cpe2.creationOrder) { +// return -1; +// } else { +// return 1; +// } + } + } + // These are the domains in sorted order. + public static int DOMAIN_UNDEFINED = 0; + public static int DOMAIN_INTEGER = 1; + public static int DOMAIN_FLOAT = 2; + public static int DOMAIN_STRING = 3; + public static int DOMAIN_NORMALASCIIZ = 4; + public static int DOMAIN_LONG = 5; + public static int DOMAIN_DOUBLE = 6; + public static int DOMAIN_CLASSREF = 7; + public static int DOMAIN_SIGNATUREASCIIZ = 8; + public static int DOMAIN_NAMEANDTYPE = 9; + public static int DOMAIN_FIELD = 10; + public static int DOMAIN_METHOD = 11; + public static int DOMAIN_ATTRIBUTEASCIIZ = 12; + + protected SortedSet sortedEntries = new TreeSet(new PoolComparator()); + public String toString() { return entries.toString(); } @@ -38,15 +94,50 @@ private boolean resolved; public ClassFileEntry add(ClassFileEntry entry) { - // TODO this should be a set - we don't want duplicates + // We don't want duplicates. // Only add in constant pools, but resolve all types since they may // introduce new constant pool entries +// This is a handy way to see what's adding a ClassFileEntry - set a breakpoint on the print +// if(entry instanceof CPUTF8) { +// System.out.println("AAH:" + ((CPUTF8)entry).comparisonString()); +// if (((CPUTF8)entry).comparisonString().matches("Ljava.*")) { +// System.out.println("Adding"); +// } +// } if (entry instanceof ConstantPoolEntry) { if (!entries.contains(entry)) { entries.add(entry); + sortedEntries.add(entry); // TODO This will be a bugger when they're sorted. if (entry instanceof CPLong ||entry instanceof CPDouble) entries.add(entry); //these get 2 slots because of their size + } else { + // TODO: This is awful. If I'm presented with + // an entry that has a lower domain than the + // current entry but is otherwise the same, + // change its domain and rebalance the tree. + // And by "rebalance" I mean destroy and recreate + // the tree. + Iterator iterator = sortedEntries.iterator(); + boolean replaceTree = false; + SortedSet newSortedSet = new TreeSet(new PoolComparator()); + while(iterator.hasNext()) { + ConstantPoolEntry storedEntry = (ConstantPoolEntry)iterator.next(); + if(storedEntry.equals(entry)) { + if(storedEntry.getDomain() > ((ConstantPoolEntry)entry).getDomain()) { + // need to blow away the tree. + replaceTree = true; + newSortedSet.add(entry); + } else { + newSortedSet.add(storedEntry); + } + } else { + newSortedSet.add(storedEntry); + } + if(replaceTree) { + sortedEntries = newSortedSet; + } + } } } else { if (!others.contains(entry)) @@ -82,34 +173,46 @@ public void resolve(Segment segment) { SegmentUtils.debug("\n\nResolving (Segment.resolve(Segment)"); - HashMap sortMap = new HashMap(); - List cpAll = null; - // TODO: HACK - this is a 1.5 api. - // Need to do the right thing and do it with 1.4 API. - try { - cpAll = Arrays.asList(segment.getConstantPool().getCpAll()); - } catch (Pack200Exception ex) { - ex.printStackTrace(); - } - Iterator it = entries.iterator(); - while(it.hasNext()) { - ClassFileEntry entry = (ClassFileEntry) it.next(); - int indexInCpAll = cpAll.indexOf(entry); - if(indexInCpAll > 0) { - sortMap.put(new Integer(indexInCpAll), entry); - } else { - sortMap.put(new Integer(99999), entry); - } - } - ArrayList sortedList = new ArrayList(); - for(int index=0; index < 99999; index++) { - if(sortMap.containsKey(new Integer(index))) { - sortedList.add((ClassFileEntry)sortMap.get(new Integer(index))); - } - } - for(int xindex=0; xindex < sortedList.size(); xindex++) { - SegmentUtils.debug(sortedList.get(xindex).toString()); - } + // TODO: Be careful here, you're obliterating the original entries. + // In an ideal world, you wouldn't actually add to it unless you're + // sure. + entries = new ArrayList(); +// entries.addAll(sortedEntries); + Iterator sortedIterator = sortedEntries.iterator(); + while(sortedIterator.hasNext()) { + ConstantPoolEntry entry = (ConstantPoolEntry)sortedIterator.next(); + entries.add(entry); + if (entry instanceof CPLong ||entry instanceof CPDouble) + entries.add(entry); //these get 2 slots because of their size + } +// HashMap sortMap = new HashMap(); +// List cpAll = null; +// // TODO: HACK - this is a 1.5 api. +// // Need to do the right thing and do it with 1.4 API. +// try { +// cpAll = Arrays.asList(segment.getConstantPool().getCpAll()); +// } catch (Pack200Exception ex) { +// ex.printStackTrace(); +// } +// Iterator it = entries.iterator(); +// while(it.hasNext()) { +// ClassFileEntry entry = (ClassFileEntry) it.next(); +// int indexInCpAll = cpAll.indexOf(entry); +// if(indexInCpAll > 0) { +// sortMap.put(new Integer(indexInCpAll), entry); +// } else { +// sortMap.put(new Integer(99999), entry); +// } +// } +// ArrayList sortedList = new ArrayList(); +// for(int index=0; index < 99999; index++) { +// if(sortMap.containsKey(new Integer(index))) { +// sortedList.add((ClassFileEntry)sortMap.get(new Integer(index))); +// } +// } +// for(int xindex=0; xindex < sortedList.size(); xindex++) { +// SegmentUtils.debug(sortedList.get(xindex).toString()); +// } resolve(); } @@ -124,7 +227,7 @@ while (it.hasNext()) { ClassFileEntry entry = (ClassFileEntry) it.next(); entry.resolve(this); - } + } } } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CodeAttribute.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CodeAttribute.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CodeAttribute.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CodeAttribute.java Fri Jan 4 02:10:32 2008 @@ -64,13 +64,23 @@ byteCodeOffsets.add(new Integer(lastBytecodePosition + byteCode.getLength())); } + if(byteCode.getOpcode() == 0xC4) { + // Special processing for wide bytecode - it knows what its + // instruction is from the opcode manager, so ignore the + // next instruction + i++; + } } // Now that all the bytecodes know their positions and // sizes, fix up the byte code targets - for (int i = 0; i < codePacked.length; i++) { + // At this point, byteCodes may be a different size than + // codePacked because of wide bytecodes. + for (int i = 0; i < byteCodes.size(); i++) { ByteCode byteCode = (ByteCode)byteCodes.get(i); byteCode.applyByteCodeTargetFixup(this); } + // TODO: By the time I get here, the input stream + // is somehow confused. } protected int getLength() { @@ -88,6 +98,9 @@ ArrayList nestedEntries = new ArrayList(); nestedEntries.add(getAttributeName()); nestedEntries.addAll(byteCodes); + // TODO: Is this the right place to add code attribute + // attributes? + nestedEntries.addAll(attributes); ClassFileEntry[] nestedEntryArray = new ClassFileEntry[nestedEntries .size()]; nestedEntries.toArray(nestedEntryArray); @@ -136,4 +149,11 @@ } } + public void addAttribute(Attribute attribute) { + attributes.add(attribute); + } + + public List attributes() { + return attributes; + } } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ConstantPoolEntry.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ConstantPoolEntry.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ConstantPoolEntry.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ConstantPoolEntry.java Fri Jan 4 02:10:32 2008 @@ -56,8 +56,15 @@ byte tag; + protected int domain = ClassConstantPool.DOMAIN_UNDEFINED; + public static int creationOrderCount = 100; + public String comparisonString() { + return "" + creationOrder; + } + public int creationOrder = -1; ConstantPoolEntry(byte tag) { this.tag = tag; + this.creationOrder = creationOrderCount++; } public abstract boolean equals(Object obj); @@ -66,6 +73,14 @@ return tag; } + public int getDomain() { + return domain; + } + + public void setDomain(int newDomain) { + this.domain = newDomain; + } + public abstract int hashCode(); public void doWrite(DataOutputStream dos) throws IOException { Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/LineNumberTableAttribute.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/LineNumberTableAttribute.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/LineNumberTableAttribute.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/LineNumberTableAttribute.java Fri Jan 4 02:10:32 2008 @@ -52,11 +52,17 @@ return "LineNumberTable: " + line_number_table_length + " lines"; } + /* (non-Javadoc) + * @see org.apache.harmony.pack200.bytecode.Attribute#getNestedClassFileEntries() + */ + protected ClassFileEntry[] getNestedClassFileEntries() { + return new ClassFileEntry[] {getAttributeName()}; + } + /* (non-Javadoc) * @see org.apache.harmony.pack200.bytecode.Attribute#resolve(org.apache.harmony.pack200.bytecode.ClassConstantPool) */ protected void resolve(ClassConstantPool pool) { - pool.add(getAttributeName()); super.resolve(pool); } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/LocalVariableTableAttribute.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/LocalVariableTableAttribute.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/LocalVariableTableAttribute.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/LocalVariableTableAttribute.java Fri Jan 4 02:10:32 2008 @@ -18,6 +18,7 @@ import java.io.DataOutputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.List; public class LocalVariableTableAttribute extends BCIRenumberedAttribute { @@ -58,17 +59,25 @@ } } + + protected ClassFileEntry[] getNestedClassFileEntries() { + ArrayList nestedEntries = new ArrayList(); + nestedEntries.add(getAttributeName()); + for (int i = 0; i < local_variable_table_length; i++) { + nestedEntries.add(names[i]); + nestedEntries.add(descriptors[i]); + } + ClassFileEntry[] nestedEntryArray = new ClassFileEntry[nestedEntries + .size()]; + nestedEntries.toArray(nestedEntryArray); + return nestedEntryArray; + } + protected void resolve(ClassConstantPool pool) { super.resolve(pool); - pool.add(getAttributeName()); name_indexes = new int[local_variable_table_length]; descriptor_indexes = new int[local_variable_table_length]; for (int i = 0; i < local_variable_table_length; i++) { - // TODO: is this the right place to add the names and descriptors? - // Maybe some API to say where they should be added if they're not - // already in the cp? - pool.add(names[i]); - pool.add(descriptors[i]); names[i].resolve(pool); descriptors[i].resolve(pool); name_indexes[i] = pool.indexOf(names[i]); @@ -88,26 +97,47 @@ * @see org.apache.harmony.pack200.bytecode.BCIRenumberedAttribute#renumber(java.util.List) */ public void renumber(List byteCodeOffsets) { - // First fix up the start_pcs + // Remember the unrenumbered start_pcs, since that's used later + // to calculate end position. + int[] unrenumbered_start_pcs = new int[start_pcs.length]; + System.arraycopy(start_pcs, 0, unrenumbered_start_pcs, 0, start_pcs.length); + + // Next renumber start_pcs in place super.renumber(byteCodeOffsets); + // lengths are BRANCH5 encoded, not BCI-encoded. - // In other words - renumber(x) - renumber(x0)? - // Add the offset to the value? - // Next fix up the lengths + // In other words: + // start_pc is BCI5 start_pc + // end_pc is byteCodeOffset[(index of start_pc in byteCodeOffset) + (encoded length)] + // real length = end_pc - start_pc + // special case if end_pc is beyond end of bytecode array + + // First figure out the maximum size of the byteCodeOffsets array int lastInstruction = ((Integer)byteCodeOffsets.get(byteCodeOffsets.size() - 1)).intValue(); - int maxLength = lastInstruction + 1; + int maxSize = lastInstruction + 1; + + // Iterate through the lengths and update each in turn. + // This is done in place in the lengths array. for(int index=0; index < lengths.length; index++) { - // Need to special case when the length is greater than the size + int start_pc = start_pcs[index]; int revisedLength = -1; int encodedLength = lengths[index]; + + // First get the index of the start_pc in the byteCodeOffsets + int indexOfStartPC = unrenumbered_start_pcs[index]; + // Given the index of the start_pc, we can now add + // the encodedLength to it to get the stop index. + int stopIndex = indexOfStartPC + encodedLength; + // Length can either be an index into the byte code offsets, or one beyond the // end of the byte code offsets. Need to determine which this is. - if(encodedLength == byteCodeOffsets.size()) { + if(stopIndex == byteCodeOffsets.size()) { // Pointing to one past the end of the byte code array - revisedLength = maxLength - start_pcs[index]; + revisedLength = maxSize - start_pc; } else { // We're indexed into the byte code array - revisedLength = ((Integer)byteCodeOffsets.get(encodedLength)).intValue(); + int stopValue = ((Integer)byteCodeOffsets.get(stopIndex)).intValue(); + revisedLength = stopValue - start_pc; } lengths[index] = revisedLength; } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/OperandManager.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/OperandManager.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/OperandManager.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/OperandManager.java Fri Jan 4 02:10:32 2008 @@ -29,7 +29,7 @@ public class OperandManager { int[] bcCaseCount; - int[][] bcCaseValue; + int[] bcCaseValue; int[] bcByte; int[] bcShort; int[] bcLocal; @@ -48,6 +48,7 @@ int[] bcThisMethod; int[] bcSuperMethod; int[] bcInitRef; + int[] wideByteCodes; int bcCaseCountIndex = 0; int bcCaseValueIndex = 0; @@ -69,6 +70,7 @@ int bcThisMethodIndex = 0; int bcSuperMethodIndex = 0; int bcInitRefIndex = 0; + int wideByteCodeIndex = 0; Segment segment = null; @@ -76,7 +78,7 @@ String superClass = null; String newClass = null; - public OperandManager(int[] bcCaseCount, int[][] bcCaseValue, int[] bcByte, int[] bcShort, int[] bcLocal, int[] bcLabel, int[] bcIntRef, int[] bcFloatRef, int[] bcLongRef, int[] bcDoubleRef, int[] bcStringRef, int[] bcClassRef, int[] bcFieldRef, int[] bcMethodRef, int[] bcIMethodRef, int[] bcThisField, int[] bcSuperField, int[] bcThisMethod, int[] bcSuperMethod, int[] bcInitRef) { + public OperandManager(int[] bcCaseCount, int[] bcCaseValue, int[] bcByte, int[] bcShort, int[] bcLocal, int[] bcLabel, int[] bcIntRef, int[] bcFloatRef, int[] bcLongRef, int[] bcDoubleRef, int[] bcStringRef, int[] bcClassRef, int[] bcFieldRef, int[] bcMethodRef, int[] bcIMethodRef, int[] bcThisField, int[] bcSuperField, int[] bcThisMethod, int[] bcSuperMethod, int[] bcInitRef, int[] wideByteCodes) { this.bcCaseCount = bcCaseCount; this.bcCaseValue = bcCaseValue; this.bcByte = bcByte; @@ -98,13 +100,14 @@ this.bcThisMethod = bcThisMethod; this.bcSuperMethod = bcSuperMethod; this.bcInitRef = bcInitRef; + this.wideByteCodes = wideByteCodes; } public int nextCaseCount() { return bcCaseCount[bcCaseCountIndex++]; } - public int[] nextCaseValues() { + public int nextCaseValues() { return bcCaseValue[bcCaseValueIndex++]; } @@ -180,6 +183,10 @@ return bcInitRef[bcInitRefIndex++]; } + public int nextWideByteCode() { + return wideByteCodes[wideByteCodeIndex++]; + } + public void setSegment(Segment segment) { this.segment = segment; } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/SourceFileAttribute.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/SourceFileAttribute.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/SourceFileAttribute.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/SourceFileAttribute.java Fri Jan 4 02:10:32 2008 @@ -27,7 +27,7 @@ public SourceFileAttribute(String name) { super("SourceFile"); //$NON-NLS-1$ - this.name = new CPUTF8(name); + this.name = new CPUTF8(name, ClassConstantPool.DOMAIN_ATTRIBUTEASCIIZ); } public boolean equals(Object obj) { Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/IMethodRefForm.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/IMethodRefForm.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/IMethodRefForm.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/IMethodRefForm.java Fri Jan 4 02:10:32 2008 @@ -16,7 +16,9 @@ */ package org.apache.harmony.pack200.bytecode.forms; +import org.apache.harmony.pack200.SegmentConstantPool; import org.apache.harmony.pack200.bytecode.ByteCode; +import org.apache.harmony.pack200.bytecode.CPInterfaceMethodRef; import org.apache.harmony.pack200.bytecode.OperandManager; /** @@ -24,7 +26,7 @@ * bytecodes which have IMethod references (and only * IMethod references). */ -public class IMethodRefForm extends ByteCodeForm { +public class IMethodRefForm extends ReferenceForm { public IMethodRefForm(int opcode, String name, int[] rewrite) { @@ -39,13 +41,21 @@ return true; } + protected int getOffset(OperandManager operandManager) { + return operandManager.nextIMethodRef(); + } + + protected int getPoolID() { + return SegmentConstantPool.CP_IMETHOD; + } + /* (non-Javadoc) - * @see org.apache.harmony.pack200.bytecode.forms.ByteCodeForm#setByteCodeOperands(org.apache.harmony.pack200.bytecode.ByteCode, org.apache.harmony.pack200.bytecode.OperandTable, org.apache.harmony.pack200.SegmentConstantPool) + * @see org.apache.harmony.pack200.bytecode.forms.ByteCodeForm#setByteCodeOperands(org.apache.harmony.pack200.bytecode.ByteCode, org.apache.harmony.pack200.bytecode.OperandTable, org.apache.harmony.pack200.Segment) */ public void setByteCodeOperands(ByteCode byteCode, OperandManager operandManager, int codeLength) { -//TODO: implement this. Removed the error message because -// it causes failures in the JUnit tests. -// throw new Error("Not implemented yet"); + super.setByteCodeOperands(byteCode, operandManager, codeLength); + int count=((CPInterfaceMethodRef)byteCode.getNestedClassFileEntries()[0]).invokeInterfaceCount(); + byteCode.getRewrite()[3] = count; } } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/LookupSwitchForm.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/LookupSwitchForm.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/LookupSwitchForm.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/LookupSwitchForm.java Fri Jan 4 02:10:32 2008 @@ -29,53 +29,61 @@ super(opcode, name, rewrite); } + /* (non-Javadoc) + * @see org.apache.harmony.pack200.bytecode.forms.SwitchForm#setByteCodeOperands(org.apache.harmony.pack200.bytecode.ByteCode, org.apache.harmony.pack200.bytecode.OperandManager, int) + */ public void setByteCodeOperands(ByteCode byteCode, OperandManager operandManager, int codeLength) { - if (switchCaseCountingBroken) - return; int case_count = operandManager.nextCaseCount(); int default_pc = operandManager.nextLabel(); - int case_values[] = operandManager.nextCaseValues(); + int case_values[] = new int[case_count]; + for(int index=0; index < case_count; index++) { + case_values[index] = operandManager.nextCaseValues(); + } int case_pcs[] = new int[case_count]; - for (int index = 0; index < case_count; index++) { + for(int index=0; index < case_count; index++) { case_pcs[index] = operandManager.nextLabel(); } - // All this gets dumped into the rewrite bytes of the - // poor bytecode. int[] labelsArray = new int[case_count + 1]; labelsArray[0] = default_pc; - for (int index = 1; index < case_count + 1; index++) { - labelsArray[index] = case_pcs[index - 1]; + for(int index=1; index < case_count + 1; index++) { + labelsArray[index] = case_pcs[index-1]; } byteCode.setByteCodeTargets(labelsArray); + + // All this gets dumped into the rewrite bytes of the + // poor bytecode. + + // Unlike most byte codes, the LookupSwitch is a // variable-sized bytecode. Because of this, the // rewrite array has to be defined here individually // for each bytecode, rather than in the ByteCodeForm // class. - + // First, there's the bytecode. Then there are 0-3 // bytes of padding so that the first (default) // label is on a 4-byte offset. - int padLength = 3 - (codeLength % 4); + int padLength = 3 - (codeLength % 4); int rewriteSize = 1 + padLength + 4 // defaultbytes - + 4 // npairs - + (4 * case_values.length) + (4 * case_pcs.length); - + + 4 // npairs + + (4 * case_values.length) + + (4 * case_pcs.length); + int[] newRewrite = new int[rewriteSize]; int rewriteIndex = 0; - + // Fill in what we can now // opcode newRewrite[rewriteIndex++] = byteCode.getOpcode(); - + // padding - for (int index = 0; index < padLength; index++) { + for(int index=0; index < padLength; index++) { newRewrite[rewriteIndex++] = 0; } - + // defaultbyte // This gets overwritten by fixUpByteCodeTargets newRewrite[rewriteIndex++] = -1; @@ -91,7 +99,7 @@ // match-offset pairs // The case_values aren't overwritten, but the // case_pcs will get overwritten by fixUpByteCodeTargets - for (int index = 0; index < case_values.length; index++) { + for(int index = 0; index < case_values.length; index++) { // match setRewrite4Bytes(case_values[index], rewriteIndex, newRewrite); rewriteIndex += 4; Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/SwitchForm.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/SwitchForm.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/SwitchForm.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/SwitchForm.java Fri Jan 4 02:10:32 2008 @@ -20,9 +20,7 @@ import org.apache.harmony.pack200.bytecode.CodeAttribute; import org.apache.harmony.pack200.bytecode.OperandManager; -public abstract class SwitchForm extends ByteCodeForm { - - static boolean switchCaseCountingBroken = true; +public abstract class SwitchForm extends VariableInstructionForm { public SwitchForm(int opcode, String name) { super(opcode, name); @@ -45,78 +43,14 @@ /* (non-Javadoc) * @see org.apache.harmony.pack200.bytecode.forms.ByteCodeForm#setByteCodeOperands(org.apache.harmony.pack200.bytecode.ByteCode, org.apache.harmony.pack200.bytecode.OperandTable, org.apache.harmony.pack200.SegmentConstantPool) */ - public abstract void setByteCodeOperands(ByteCode byteCode, - OperandManager operandManager, int codeLength); - - /** - * Given an int operand, set the rewrite bytes for - * the next available operand position and the three - * immediately following it to a highest-byte, - * mid-high, mid-low, low-byte encoding of the operand. - * - * Note that unlike the ByteCode setOperand* operations, this - * starts with an actual bytecode rewrite array (rather than - * a ByteCodeForm prototype rewrite array). Also, this method - * overwrites -1 values in the rewrite array - so if you start - * with an array that looks like: - * {100, -1, -1, -1, -1, 200, -1, -1, -1, -1} then calling - * setRewrite4Bytes(0, rewrite) the first time will convert - * it to: - * {100, 0, 0, 0, 0, 200, -1, -1, -1, -1} - * Calling setRewrite4Bytes(0, rewrite) a second time will - * convert it to: - * {100, 0, 0, 0, 0, 200, 0, 0, 0, 0} - * - * @param operand int to set the rewrite bytes to - * @param rewrite int[] bytes to rewrite - */ - public void setRewrite4Bytes(int operand, int[] rewrite) { - int firstOperandPosition = -1; - - // Find the first -1 in the rewrite array - for(int index=0; index < rewrite.length - 3; index++) { - if((rewrite[index] == -1) - && (rewrite[index+1] == -1) - && (rewrite[index+2] == -1) - && (rewrite[index+3] == -1)) { - firstOperandPosition = index; - break; - } - } - setRewrite4Bytes(operand, firstOperandPosition, rewrite); + public void setByteCodeOperands(ByteCode byteCode, + OperandManager operandManager, int codeLength) { } - - /** - * This method writes operand directly into the rewrite - * array at index position specified. - * @param operand value to write - * @param absPosition position in array to write. Note that - * this is absolute position in the array, so one can - * overwrite the bytecode if one isn't careful. - * @param rewrite array to write into - */ - public void setRewrite4Bytes(int operand, int absPosition, int[] rewrite) { - if(absPosition < 0) { - throw new Error("Trying to rewrite " + this + " but there is no room for 4 bytes"); - } - - int byteCodeRewriteLength = rewrite.length; - - if(absPosition + 3 > byteCodeRewriteLength) { - throw new Error("Trying to rewrite " + this + " with an int at position " + absPosition + " but this won't fit in the rewrite array"); - } - - rewrite[absPosition] = ((0xFF000000) & operand) >> 24; - rewrite[absPosition + 1] = ((0x00FF0000) & operand) >> 16; - rewrite[absPosition + 2] = ((0x0000FF00) & operand) >> 8; - rewrite[absPosition + 3] = ((0x000000FF) & operand); - } - + /* (non-Javadoc) * @see org.apache.harmony.pack200.bytecode.forms.ByteCodeForm#fixUpByteCodeTargets(org.apache.harmony.pack200.bytecode.ByteCode, org.apache.harmony.pack200.bytecode.CodeAttribute) */ public void fixUpByteCodeTargets(ByteCode byteCode, CodeAttribute codeAttribute) { - if(switchCaseCountingBroken) return; // SwitchForms need to fix up the target of label operations int[] originalTargets = byteCode.getByteCodeTargets(); int numberOfLabels = originalTargets.length; Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/TableSwitchForm.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/TableSwitchForm.java?rev=608790&r1=608789&r2=608790&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/TableSwitchForm.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/TableSwitchForm.java Fri Jan 4 02:10:32 2008 @@ -20,7 +20,7 @@ import org.apache.harmony.pack200.bytecode.OperandManager; public class TableSwitchForm extends SwitchForm { - + public TableSwitchForm(int opcode, String name) { super(opcode, name); } @@ -29,56 +29,62 @@ super(opcode, name, rewrite); } + + /* (non-Javadoc) + * @see org.apache.harmony.pack200.bytecode.forms.SwitchForm#setByteCodeOperands(org.apache.harmony.pack200.bytecode.ByteCode, org.apache.harmony.pack200.bytecode.OperandManager, int) + */ public void setByteCodeOperands(ByteCode byteCode, OperandManager operandManager, int codeLength) { - if (switchCaseCountingBroken) - return; int case_count = operandManager.nextCaseCount(); int default_pc = operandManager.nextLabel(); - int case_values[] = operandManager.nextCaseValues(); + int case_value = -1; + case_value = operandManager.nextCaseValues(); + int case_pcs[] = new int[case_count]; - for (int index = 0; index < case_count; index++) { + for(int index=0; index < case_count; index++) { case_pcs[index] = operandManager.nextLabel(); } - int lowValue = case_values[0]; - int highValue = lowValue + case_count - 1; - // All this gets dumped into the rewrite bytes of the - // poor bytecode. int[] labelsArray = new int[case_count + 1]; labelsArray[0] = default_pc; - for (int index = 1; index < case_count + 1; index++) { - labelsArray[index] = case_pcs[index - 1]; + for(int index=1; index < case_count + 1; index++) { + labelsArray[index] = case_pcs[index-1]; } byteCode.setByteCodeTargets(labelsArray); + int lowValue = case_value; + int highValue = lowValue + case_count - 1; + // All this gets dumped into the rewrite bytes of the + // poor bytecode. + + // Unlike most byte codes, the TableSwitch is a // variable-sized bytecode. Because of this, the // rewrite array has to be defined here individually // for each bytecode, rather than in the ByteCodeForm // class. - + // First, there's the bytecode. Then there are 0-3 // bytes of padding so that the first (default) // label is on a 4-byte offset. - int padLength = 3 - (codeLength % 4); + int padLength = 3 - (codeLength % 4); int rewriteSize = 1 + padLength + 4 // defaultbytes - + 4 // lowbyte - + 4 // highbyte - + (4 * case_pcs.length); - + + 4 // lowbyte + + 4 // highbyte + + (4 * case_pcs.length); + int[] newRewrite = new int[rewriteSize]; int rewriteIndex = 0; - + // Fill in what we can now // opcode newRewrite[rewriteIndex++] = byteCode.getOpcode(); - + // padding - for (int index = 0; index < padLength; index++) { + for(int index=0; index < padLength; index++) { newRewrite[rewriteIndex++] = 0; } - + // defaultbyte // This gets overwritten by fixUpByteCodeTargets newRewrite[rewriteIndex++] = -1; @@ -98,7 +104,7 @@ // jump offsets // The case_pcs will get overwritten by fixUpByteCodeTargets - for (int index = 0; index < case_count; index++) { + for(int index = 0; index < case_count; index++) { // offset newRewrite[rewriteIndex++] = -1; newRewrite[rewriteIndex++] = -1; Added: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/VariableInstructionForm.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/VariableInstructionForm.java?rev=608790&view=auto ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/VariableInstructionForm.java (added) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/VariableInstructionForm.java Fri Jan 4 02:10:32 2008 @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.bytecode.forms; + +/** + * This abstract class implements the common code for + * instructions which have variable lengths. This + * is currently the *switch instructions and some + * wide (_w) instructions. + */ +public abstract class VariableInstructionForm extends ByteCodeForm { + + public VariableInstructionForm(int opcode, String name) { + super(opcode, name); + } + + public VariableInstructionForm(int opcode, String name, int[] rewrite) { + super(opcode, name, rewrite); + } + + /** + * Given an int operand, set the rewrite bytes for + * the next available operand position and the three + * immediately following it to a highest-byte, + * mid-high, mid-low, low-byte encoding of the operand. + * + * Note that unlike the ByteCode setOperand* operations, this + * starts with an actual bytecode rewrite array (rather than + * a ByteCodeForm prototype rewrite array). Also, this method + * overwrites -1 values in the rewrite array - so if you start + * with an array that looks like: + * {100, -1, -1, -1, -1, 200, -1, -1, -1, -1} then calling + * setRewrite4Bytes(0, rewrite) the first time will convert + * it to: + * {100, 0, 0, 0, 0, 200, -1, -1, -1, -1} + * Calling setRewrite4Bytes(0, rewrite) a second time will + * convert it to: + * {100, 0, 0, 0, 0, 200, 0, 0, 0, 0} + * + * @param operand int to set the rewrite bytes to + * @param rewrite int[] bytes to rewrite + */ + public void setRewrite4Bytes(int operand, int[] rewrite) { + int firstOperandPosition = -1; + + // Find the first -1 in the rewrite array + for(int index=0; index < rewrite.length - 3; index++) { + if((rewrite[index] == -1) + && (rewrite[index+1] == -1) + && (rewrite[index+2] == -1) + && (rewrite[index+3] == -1)) { + firstOperandPosition = index; + break; + } + } + setRewrite4Bytes(operand, firstOperandPosition, rewrite); + } + + /** + * Given an int operand, set the rewrite bytes for + * the next available operand position and the byte + * immediately following it to a high-byte, + * low-byte encoding of the operand. + * + * Note that unlike the ByteCode setOperand* operations, this + * starts with an actual bytecode rewrite array (rather than + * a ByteCodeForm prototype rewrite array). Also, this method + * overwrites -1 values in the rewrite array - so if you start + * with an array that looks like: + * {100, -1, -1, -1, -1, 200, -1, -1, -1, -1} then calling + * setRewrite2Bytes(0, rewrite) the first time will convert + * it to: + * {100, 0, 0, -1, -1, 200, -1, -1, -1, -1} + * Calling setRewrite2Bytes(0, rewrite) a second time will + * convert it to: + * {100, 0, 0, 0, 0, 200, -1, -1, -1, -1} + * + * @param operand int to set the rewrite bytes to + * @param rewrite int[] bytes to rewrite + */ + public void setRewrite2Bytes(int operand, int[] rewrite) { + int firstOperandPosition = -1; + + // Find the first -1 in the rewrite array + for(int index=0; index < rewrite.length - 3; index++) { + if((rewrite[index] == -1) + && (rewrite[index+1] == -1)) { + firstOperandPosition = index; + break; + } + } + setRewrite2Bytes(operand, firstOperandPosition, rewrite); + } + + /** + * This method writes operand directly into the rewrite + * array at index position specified. + * @param operand value to write + * @param absPosition position in array to write. Note that + * this is absolute position in the array, so one can + * overwrite the bytecode if one isn't careful. + * @param rewrite array to write into + */ + public void setRewrite4Bytes(int operand, int absPosition, int[] rewrite) { + if(absPosition < 0) { + throw new Error("Trying to rewrite " + this + " but there is no room for 4 bytes"); + } + + int byteCodeRewriteLength = rewrite.length; + + if(absPosition + 3 > byteCodeRewriteLength) { + throw new Error("Trying to rewrite " + this + " with an int at position " + absPosition + " but this won't fit in the rewrite array"); + } + + rewrite[absPosition] = ((0xFF000000) & operand) >> 24; + rewrite[absPosition + 1] = ((0x00FF0000) & operand) >> 16; + rewrite[absPosition + 2] = ((0x0000FF00) & operand) >> 8; + rewrite[absPosition + 3] = ((0x000000FF) & operand); + } + + /** + * This method writes operand directly into the rewrite + * array at index position specified. + * @param operand value to write + * @param absPosition position in array to write. Note that + * this is absolute position in the array, so one can + * overwrite the bytecode if one isn't careful. + * @param rewrite array to write into + */ + public void setRewrite2Bytes(int operand, int absPosition, int[] rewrite) { + if(absPosition < 0) { + throw new Error("Trying to rewrite " + this + " but there is no room for 4 bytes"); + } + + int byteCodeRewriteLength = rewrite.length; + + if(absPosition + 1 > byteCodeRewriteLength) { + throw new Error("Trying to rewrite " + this + " with an int at position " + absPosition + " but this won't fit in the rewrite array"); + } + + rewrite[absPosition] = ((0xFF00) & operand) >> 8; + rewrite[absPosition + 1] = ((0x00FF) & operand); + } +} Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/VariableInstructionForm.java ------------------------------------------------------------------------------ svn:eol-style = native