From: <dgr...@us...> - 2009-01-13 18:18:25
|
Revision: 15279 http://jikesrvm.svn.sourceforge.net/jikesrvm/?rev=15279&view=rev Author: dgrove-oss Date: 2009-01-13 18:18:15 +0000 (Tue, 13 Jan 2009) Log Message: ----------- RVM-746 WIP: Pull the code to read the class file out of RVMClass and into a new class, ClassFileReader. Cleanup work before attempting to switch to using an Unboxed type that is constructed by parsing a classfile. Modified Paths: -------------- rvmroot/trunk/rvm/src/org/jikesrvm/classloader/BytecodeStream.java rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ClassLoaderConstants.java rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ExceptionHandlerMap.java rvmroot/trunk/rvm/src/org/jikesrvm/classloader/LocalVariableTable.java rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMAnnotation.java rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMClass.java rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMClassLoader.java rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMField.java rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMMethod.java rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/BuildReferenceMaps.java rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/TemplateCompilerFramework.java rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/bc2ir/BC2IR.java rvmroot/trunk/rvm/src/org/jikesrvm/osr/BytecodeTraverser.java Added Paths: ----------- rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ClassFileReader.java Modified: rvmroot/trunk/rvm/src/org/jikesrvm/classloader/BytecodeStream.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/classloader/BytecodeStream.java 2009-01-11 17:18:07 UTC (rev 15278) +++ rvmroot/trunk/rvm/src/org/jikesrvm/classloader/BytecodeStream.java 2009-01-13 18:18:15 UTC (rev 15279) @@ -477,7 +477,7 @@ opcode == JBC_getfield || opcode == JBC_putfield); } - return RVMClass.getFieldRef(constantPool, readUnsignedShort()); + return ClassFileReader.getFieldRef(constantPool, readUnsignedShort()); } /** * Returns a reference to a field @@ -506,7 +506,7 @@ opcode == JBC_invokestatic || opcode == JBC_invokeinterface); } - return RVMClass.getMethodRef(constantPool, readUnsignedShort()); + return ClassFileReader.getMethodRef(constantPool, readUnsignedShort()); } /** @@ -697,7 +697,7 @@ public final int getIntConstant(int index) { if (VM.VerifyAssertions) { VM._assert((opcode == JBC_ldc || opcode == JBC_ldc_w) && - getDeclaringClass().getLiteralDescription(index) == RVMClass.CP_INT); + getDeclaringClass().getLiteralDescription(index) == ClassFileReader.CP_INT); } Offset offset = getDeclaringClass().getLiteralOffset(index); int val = Statics.getSlotContentsAsInt(offset); @@ -718,7 +718,7 @@ */ public final long getLongConstant(int index) { if (VM.VerifyAssertions) { - VM._assert(opcode == JBC_ldc2_w && getDeclaringClass().getLiteralDescription(index) == RVMClass.CP_LONG); + VM._assert(opcode == JBC_ldc2_w && getDeclaringClass().getLiteralDescription(index) == ClassFileReader.CP_LONG); } Offset offset = getDeclaringClass().getLiteralOffset(index); long val = Statics.getSlotContentsAsLong(offset); @@ -740,7 +740,7 @@ public final float getFloatConstant(int index) { if (VM.VerifyAssertions) { VM._assert((opcode == JBC_ldc || opcode == JBC_ldc_w) && - getDeclaringClass().getLiteralDescription(index) == RVMClass.CP_FLOAT); + getDeclaringClass().getLiteralDescription(index) == ClassFileReader.CP_FLOAT); } Offset offset = getDeclaringClass().getLiteralOffset(index); int val_raw = Statics.getSlotContentsAsInt(offset); @@ -762,7 +762,7 @@ */ public final double getDoubleConstant(int index) { if (VM.VerifyAssertions) { - VM._assert(opcode == JBC_ldc2_w && getDeclaringClass().getLiteralDescription(index) == RVMClass.CP_DOUBLE); + VM._assert(opcode == JBC_ldc2_w && getDeclaringClass().getLiteralDescription(index) == ClassFileReader.CP_DOUBLE); } Offset offset = getDeclaringClass().getLiteralOffset(index); long val_raw = Statics.getSlotContentsAsLong(offset); @@ -785,7 +785,7 @@ public final String getStringConstant(int index) { if (VM.VerifyAssertions) { VM._assert((opcode == JBC_ldc || opcode == JBC_ldc_w) && - getDeclaringClass().getLiteralDescription(index) == RVMClass.CP_STRING); + getDeclaringClass().getLiteralDescription(index) == ClassFileReader.CP_STRING); } Offset offset = getDeclaringClass().getLiteralOffset(index); String val = (String) Statics.getSlotContentsAsObject(offset); Added: rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ClassFileReader.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ClassFileReader.java (rev 0) +++ rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ClassFileReader.java 2009-01-13 18:18:15 UTC (rev 15279) @@ -0,0 +1,526 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ + +package org.jikesrvm.classloader; + +import java.io.DataInputStream; +import java.io.IOException; + +import org.jikesrvm.Constants; +import org.jikesrvm.VM; +import org.jikesrvm.runtime.Statics; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Offset; + +/** + * Support code to parse a DataInputStream in the Java classfile format + * and create the appropriate instance of an RVMClass or UnboxedType. + * Also low-level support for our internal constant pool format. + */ +public class ClassFileReader implements Constants, ClassLoaderConstants { + + /** + * Create an instance of a RVMClass. + * @param typeRef the cannonical type reference for this type. + * @param input the data stream from which to read the class's description. + */ + static RVMClass readClass(TypeReference typeRef, DataInputStream input) throws ClassFormatError, IOException { + + if (RVMClass.classLoadingDisabled) { + throw new RuntimeException("ClassLoading Disabled : " + typeRef); + } + + if (VM.TraceClassLoading && VM.runningVM) { + VM.sysWrite("RVMClass: (begin) load file " + typeRef.getName() + "\n"); + } + + int magic = input.readInt(); + if (magic != 0xCAFEBABE) { + throw new ClassFormatError("bad magic number " + Integer.toHexString(magic)); + } + + // Get the class file version number and check to see if it is a version + // that we support. + int minor = input.readUnsignedShort(); + int major = input.readUnsignedShort(); + switch (major) { + case 45: + case 46: + case 47: + case 48: + case 49: // we support all variants of these major versions so the minor number doesn't matter. + break; + case 50: // we only support up to 50.0 (ie Java 1.6.0) + if (minor == 0) break; + default: + throw new UnsupportedClassVersionError("unsupported class file version " + major + "." + minor); + } + + // + // pass 1: read constant pool + // + int[] constantPool = new int[input.readUnsignedShort()]; + byte[] tmpTags = new byte[constantPool.length]; + + // note: slot 0 is unused + for (int i = 1; i < constantPool.length; i++) { + tmpTags[i] = input.readByte(); + switch (tmpTags[i]) { + case TAG_UTF: { + byte[] utf = new byte[input.readUnsignedShort()]; + input.readFully(utf); + int atomId = Atom.findOrCreateUtf8Atom(utf).getId(); + constantPool[i] = ClassFileReader.packCPEntry(ClassFileReader.CP_UTF, atomId); + break; + } + case TAG_UNUSED: + if (VM.VerifyAssertions) VM._assert(NOT_REACHED); + break; + + case TAG_INT: { + int literal = input.readInt(); + int offset = Statics.findOrCreateIntSizeLiteral(literal); + constantPool[i] = ClassFileReader.packCPEntry(ClassFileReader.CP_INT, offset); + break; + } + case TAG_FLOAT: { + int literal = input.readInt(); + int offset = Statics.findOrCreateIntSizeLiteral(literal); + constantPool[i] = ClassFileReader.packCPEntry(ClassFileReader.CP_FLOAT, offset); + break; + } + case TAG_LONG: { + long literal = input.readLong(); + int offset = Statics.findOrCreateLongSizeLiteral(literal); + constantPool[i] = ClassFileReader.packCPEntry(ClassFileReader.CP_LONG, offset); + i++; + break; + } + case TAG_DOUBLE: { + long literal = input.readLong(); + int offset = Statics.findOrCreateLongSizeLiteral(literal); + constantPool[i] = ClassFileReader.packCPEntry(ClassFileReader.CP_DOUBLE, offset); + i++; + break; + } + case TAG_TYPEREF: + constantPool[i] = input.readUnsignedShort(); + break; + + case TAG_STRING: + constantPool[i] = input.readUnsignedShort(); + break; + + case TAG_FIELDREF: + case TAG_METHODREF: + case TAG_INTERFACE_METHODREF: { + int classDescriptorIndex = input.readUnsignedShort(); + int memberNameAndDescriptorIndex = input.readUnsignedShort(); + constantPool[i] = ClassFileReader.packTempCPEntry(classDescriptorIndex, memberNameAndDescriptorIndex); + break; + } + + case TAG_MEMBERNAME_AND_DESCRIPTOR: { + int memberNameIndex = input.readUnsignedShort(); + int descriptorIndex = input.readUnsignedShort(); + constantPool[i] = ClassFileReader.packTempCPEntry(memberNameIndex, descriptorIndex); + break; + } + + default: + throw new ClassFormatError("bad constant pool"); + } + } + + // + // pass 2: post-process type and string constant pool entries + // (we must do this in a second pass because of forward references) + // + try { + for (int i = 1; i < constantPool.length; i++) { + switch (tmpTags[i]) { + case TAG_LONG: + case TAG_DOUBLE: + ++i; + break; + + case TAG_TYPEREF: { // in: utf index + Atom typeName = ClassFileReader.getUtf(constantPool, constantPool[i]); + int typeRefId = + TypeReference.findOrCreate(typeRef.getClassLoader(), typeName.descriptorFromClassName()).getId(); + constantPool[i] = ClassFileReader.packCPEntry(ClassFileReader.CP_CLASS, typeRefId); + break; + } // out: type reference id + + case TAG_STRING: { // in: utf index + Atom literal = ClassFileReader.getUtf(constantPool, constantPool[i]); + int offset = literal.getStringLiteralOffset(); + constantPool[i] = ClassFileReader.packCPEntry(ClassFileReader.CP_STRING, offset); + break; + } // out: jtoc slot number + } + } + } catch (java.io.UTFDataFormatException x) { + throw new ClassFormatError(x.toString()); + } + + // + // pass 3: post-process type field and method constant pool entries + // + for (int i = 1; i < constantPool.length; i++) { + switch (tmpTags[i]) { + case TAG_LONG: + case TAG_DOUBLE: + ++i; + break; + + case TAG_FIELDREF: + case TAG_METHODREF: + case TAG_INTERFACE_METHODREF: { // in: classname+membername+memberdescriptor indices + int bits = constantPool[i]; + int classNameIndex = ClassFileReader.unpackTempCPIndex1(bits); + int memberNameAndDescriptorIndex = ClassFileReader.unpackTempCPIndex2(bits); + int memberNameAndDescriptorBits = constantPool[memberNameAndDescriptorIndex]; + int memberNameIndex = ClassFileReader.unpackTempCPIndex1(memberNameAndDescriptorBits); + int memberDescriptorIndex = ClassFileReader.unpackTempCPIndex2(memberNameAndDescriptorBits); + + TypeReference tref = ClassFileReader.getTypeRef(constantPool, classNameIndex); + Atom memberName = ClassFileReader.getUtf(constantPool, memberNameIndex); + Atom memberDescriptor = ClassFileReader.getUtf(constantPool, memberDescriptorIndex); + MemberReference mr = MemberReference.findOrCreate(tref, memberName, memberDescriptor); + int mrId = mr.getId(); + constantPool[i] = ClassFileReader.packCPEntry(ClassFileReader.CP_MEMBER, mrId); + break; + } // out: MemberReference id + } + } + + short modifiers = input.readShort(); + int myTypeIndex = input.readUnsignedShort(); + TypeReference myTypeRef = ClassFileReader.getTypeRef(constantPool, myTypeIndex); + if (myTypeRef != typeRef) { + // eg. file contains a different class than would be + // expected from its .class file name + if (!VM.VerifyAssertions) { + throw new ClassFormatError("expected class \"" + + typeRef.getName() + + "\" but found \"" + + myTypeRef.getName() + + "\""); + } else { + throw new ClassFormatError("expected class \"" + + typeRef.getName() + + "\" but found \"" + + myTypeRef.getName() + + "\"\n" + typeRef + " != " + myTypeRef); + } + } + + TypeReference superType = ClassFileReader.getTypeRef(constantPool, input.readUnsignedShort()); // possibly null + RVMClass superClass = null; + if (((modifiers & ACC_INTERFACE) == 0) && (superType != null)) { + superClass = superType.resolve().asClass(); + } + + int numInterfaces = input.readUnsignedShort(); + RVMClass[] declaredInterfaces; + if (numInterfaces == 0) { + declaredInterfaces = RVMType.emptyVMClass; + } else { + declaredInterfaces = new RVMClass[numInterfaces]; + for (int i = 0; i < numInterfaces; ++i) { + TypeReference inTR = ClassFileReader.getTypeRef(constantPool, input.readUnsignedShort()); + declaredInterfaces[i] = inTR.resolve().asClass(); + } + } + + int numFields = input.readUnsignedShort(); + RVMField[] declaredFields; + if (numFields == 0) { + declaredFields = RVMType.emptyVMField; + } else { + declaredFields = new RVMField[numFields]; + for (int i = 0; i < numFields; i++) { + short fmodifiers = input.readShort(); + Atom fieldName = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); + Atom fieldDescriptor = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); + MemberReference memRef = MemberReference.findOrCreate(typeRef, fieldName, fieldDescriptor); + declaredFields[i] = RVMField.readField(typeRef, constantPool, memRef, fmodifiers, input); + } + } + + int numMethods = input.readUnsignedShort(); + RVMMethod[] declaredMethods; + RVMMethod classInitializerMethod = null; + if (numMethods == 0) { + declaredMethods = RVMType.emptyVMMethod; + } else { + declaredMethods = new RVMMethod[numMethods]; + for (int i = 0; i < numMethods; i++) { + short mmodifiers = input.readShort(); + Atom methodName = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); + Atom methodDescriptor = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); + MemberReference memRef = MemberReference.findOrCreate(typeRef, methodName, methodDescriptor); + RVMMethod method = RVMMethod.readMethod(typeRef, constantPool, memRef, mmodifiers, input); + declaredMethods[i] = method; + if (method.isClassInitializer()) { + classInitializerMethod = method; + } + } + } + TypeReference[] declaredClasses = null; + Atom sourceName = null; + TypeReference declaringClass = null; + Atom signature = null; + RVMAnnotation[] annotations = null; + TypeReference enclosingClass = null; + MethodReference enclosingMethod = null; + // Read attributes. + for (int i = 0, n = input.readUnsignedShort(); i < n; ++i) { + Atom attName = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); + int attLength = input.readInt(); + + // Class attributes + if (attName == RVMClassLoader.sourceFileAttributeName && attLength == 2) { + sourceName = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); + } else if (attName == RVMClassLoader.innerClassesAttributeName) { + // Parse InnerClasses attribute, and use the information to populate + // the list of declared member classes. We do this so we can + // support the java.lang.Class.getDeclaredClasses() + // and java.lang.Class.getDeclaredClass methods. + + int numberOfClasses = input.readUnsignedShort(); + declaredClasses = new TypeReference[numberOfClasses]; + + for (int j = 0; j < numberOfClasses; ++j) { + int innerClassInfoIndex = input.readUnsignedShort(); + int outerClassInfoIndex = input.readUnsignedShort(); + int innerNameIndex = input.readUnsignedShort(); + int innerClassAccessFlags = input.readUnsignedShort(); + + if (innerClassInfoIndex != 0 && outerClassInfoIndex == myTypeIndex && innerNameIndex != 0) { + // This looks like a declared inner class. + declaredClasses[j] = ClassFileReader.getTypeRef(constantPool, innerClassInfoIndex); + } + + if (innerClassInfoIndex == myTypeIndex) { + if (outerClassInfoIndex != 0) { + declaringClass = ClassFileReader.getTypeRef(constantPool, outerClassInfoIndex); + if (enclosingClass == null) { + // TODO: is this the null test necessary? + enclosingClass = declaringClass; + } + } + if ((innerClassAccessFlags & (ACC_PRIVATE | ACC_PROTECTED)) != 0) { + modifiers &= ~(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED); + } + modifiers |= innerClassAccessFlags; + } + } + } else if (attName == RVMClassLoader.syntheticAttributeName) { + modifiers |= ACC_SYNTHETIC; + } else if (attName == RVMClassLoader.enclosingMethodAttributeName) { + int enclosingClassIndex = input.readUnsignedShort(); + enclosingClass = ClassFileReader.getTypeRef(constantPool, enclosingClassIndex); + + int enclosingMethodIndex = input.readUnsignedShort(); + if (enclosingMethodIndex != 0) { + int memberNameIndex = constantPool[enclosingMethodIndex] >>> BITS_IN_SHORT; + int memberDescriptorIndex = constantPool[enclosingMethodIndex] & ((1 << BITS_IN_SHORT) - 1); + Atom memberName = ClassFileReader.getUtf(constantPool, memberNameIndex); + Atom memberDescriptor = ClassFileReader.getUtf(constantPool, memberDescriptorIndex); + enclosingMethod = + MemberReference.findOrCreate(enclosingClass, memberName, memberDescriptor).asMethodReference(); + } + } else if (attName == RVMClassLoader.signatureAttributeName) { + signature = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); + } else if (attName == RVMClassLoader.runtimeVisibleAnnotationsAttributeName) { + annotations = AnnotatedElement.readAnnotations(constantPool, input, typeRef.getClassLoader()); + } else { + int skippedAmount = input.skipBytes(attLength); + if (skippedAmount != attLength) { + throw new IOException("Unexpected short skip"); + } + } + } + + return new RVMClass(typeRef, + constantPool, + modifiers, + superClass, + declaredInterfaces, + declaredFields, + declaredMethods, + declaredClasses, + declaringClass, + enclosingClass, + enclosingMethod, + sourceName, + classInitializerMethod, + signature, + annotations); + } + + @Uninterruptible + static int packCPEntry(byte type, int value) { + return (type << 29) | (value & 0x1fffffff); + } + + @Uninterruptible + static byte unpackCPType(int cpValue) { + return (byte) (cpValue >>> 29); + } + + @Uninterruptible + static int unpackSignedCPValue(int cpValue) { + return (cpValue << 3) >> 3; + } + + @Uninterruptible + static int unpackUnsignedCPValue(int cpValue) { + return cpValue & 0x1fffffff; + } + + @Uninterruptible + static boolean packedCPTypeIsClassType(int cpValue) { + return (cpValue & (7 << 29)) == (ClassFileReader.CP_CLASS << 29); + } + + @Uninterruptible + static int packTempCPEntry(int index1, int index2) { + return (index1 << 16) | (index2 & 0xffff); + } + + @Uninterruptible + static int unpackTempCPIndex1(int cpValue) { + return cpValue >>> 16; + } + + @Uninterruptible + static int unpackTempCPIndex2(int cpValue) { + return cpValue & 0xffff; + } + + static int getLiteralSize(int[] constantPool, int constantPoolIndex) { + int cpValue = constantPool[constantPoolIndex]; + switch (unpackCPType(cpValue)) { + case ClassFileReader.CP_INT: + case ClassFileReader.CP_FLOAT: + return BYTES_IN_INT; + case ClassFileReader.CP_LONG: + case ClassFileReader.CP_DOUBLE: + return BYTES_IN_LONG; + case ClassFileReader.CP_CLASS: + case ClassFileReader.CP_STRING: + return BYTES_IN_ADDRESS; + default: + VM._assert(NOT_REACHED); + return 0; + } + } + + /** + * Get offset of a literal constant, in bytes. + * Offset is with respect to virtual machine's "table of contents" (jtoc). + */ + static Offset getLiteralOffset(int[] constantPool, int constantPoolIndex) { + int cpValue = constantPool[constantPoolIndex]; + if (VM.VerifyAssertions) { + int value = unpackSignedCPValue(cpValue); + byte type = unpackCPType(cpValue); + switch (type) { + case ClassFileReader.CP_INT: + case ClassFileReader.CP_FLOAT: + case ClassFileReader.CP_LONG: + case ClassFileReader.CP_DOUBLE: + case ClassFileReader.CP_STRING: + return Offset.fromIntSignExtend(value); + case ClassFileReader.CP_CLASS: { + int typeId = unpackUnsignedCPValue(cpValue); + Class<?> literalAsClass = TypeReference.getTypeRef(typeId).resolve().getClassForType(); + return Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(literalAsClass)); + } + default: + VM._assert(NOT_REACHED); + return Offset.fromIntSignExtend(0xebad0ff5); + } + } else { + if (packedCPTypeIsClassType(cpValue)) { + int typeId = unpackUnsignedCPValue(cpValue); + Class<?> literalAsClass = TypeReference.getTypeRef(typeId).resolve().getClassForType(); + return Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(literalAsClass)); + } else { + int value = unpackSignedCPValue(cpValue); + return Offset.fromIntSignExtend(value); + } + } + } + + /** + * Get description of a literal constant. + */ + static byte getLiteralDescription(int[] constantPool, int constantPoolIndex) { + int cpValue = constantPool[constantPoolIndex]; + byte type = unpackCPType(cpValue); + return type; + } + + /** + * Get contents of a "typeRef" constant pool entry. + * @return type that was referenced + */ + @Uninterruptible + static TypeReference getTypeRef(int[] constantPool, int constantPoolIndex) { + if (constantPoolIndex != 0) { + int cpValue = constantPool[constantPoolIndex]; + if (VM.VerifyAssertions) VM._assert(unpackCPType(cpValue) == ClassFileReader.CP_CLASS); + return TypeReference.getTypeRef(unpackUnsignedCPValue(cpValue)); + } else { + return null; + } + } + + /** + * Get contents of a "methodRef" constant pool entry. + */ + @Uninterruptible + static MethodReference getMethodRef(int[] constantPool, int constantPoolIndex) { + int cpValue = constantPool[constantPoolIndex]; + if (VM.VerifyAssertions) VM._assert(unpackCPType(cpValue) == ClassFileReader.CP_MEMBER); + return (MethodReference) MemberReference.getMemberRef(unpackUnsignedCPValue(cpValue)); + } + + /** + * Get contents of a "methodRef" constant pool entry. + */ + @Uninterruptible + static FieldReference getFieldRef(int[] constantPool, int constantPoolIndex) { + int cpValue = constantPool[constantPoolIndex]; + if (VM.VerifyAssertions) VM._assert(unpackCPType(cpValue) == ClassFileReader.CP_MEMBER); + return (FieldReference) MemberReference.getMemberRef(unpackUnsignedCPValue(cpValue)); + } + + /** + * Get contents of a "utf" from a constant pool entry. + */ + @Uninterruptible + static Atom getUtf(int[] constantPool, int constantPoolIndex) { + int cpValue = constantPool[constantPoolIndex]; + if (VM.VerifyAssertions) VM._assert(unpackCPType(cpValue) == ClassFileReader.CP_UTF); + return Atom.getAtom(unpackUnsignedCPValue(cpValue)); + } + + /** Constant pool entry for a UTF-8 encoded atom */ + public static final byte CP_UTF = 0; + +} Property changes on: rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ClassFileReader.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:eol-style + native Modified: rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ClassLoaderConstants.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ClassLoaderConstants.java 2009-01-11 17:18:07 UTC (rev 15278) +++ rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ClassLoaderConstants.java 2009-01-13 18:18:15 UTC (rev 15279) @@ -12,7 +12,7 @@ */ package org.jikesrvm.classloader; -interface ClassLoaderConstants { +public interface ClassLoaderConstants { // Attribute modifiers for class-, method-, and field- descriptions. // // applicability @@ -116,4 +116,20 @@ byte FloatTypeCode = (byte) 'F'; byte DoubleTypeCode = (byte) 'D'; byte CharTypeCode = (byte) 'C'; + + // Constants for our internal encoding of constant pools. + /** Constant pool entry for int literal */ + byte CP_INT = 1; + /** Constant pool entry for long literal */ + byte CP_LONG = 2; + /** Constant pool entry for float literal */ + byte CP_FLOAT = 3; + /** Constant pool entry for double literal */ + byte CP_DOUBLE = 4; + /** Constant pool entry for string literal (for annotations, may be other objects) */ + byte CP_STRING = 5; + /** Constant pool entry for member (field or method) reference */ + byte CP_MEMBER = 6; + /** Constant pool entry for type reference or class literal */ + byte CP_CLASS = 7; } Modified: rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ExceptionHandlerMap.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ExceptionHandlerMap.java 2009-01-11 17:18:07 UTC (rev 15278) +++ rvmroot/trunk/rvm/src/org/jikesrvm/classloader/ExceptionHandlerMap.java 2009-01-13 18:18:15 UTC (rev 15279) @@ -105,7 +105,7 @@ startPCs[i] = input.readUnsignedShort(); endPCs[i] = input.readUnsignedShort(); handlerPCs[i] = input.readUnsignedShort(); - TypeReference et = RVMClass.getTypeRef(constantPool, input.readUnsignedShort()); // possibly null + TypeReference et = ClassFileReader.getTypeRef(constantPool, input.readUnsignedShort()); // possibly null if (et == null) { // A finally block...set to java.lang.Throwable to avoid // needing to think about this case anywhere else in the VM. Modified: rvmroot/trunk/rvm/src/org/jikesrvm/classloader/LocalVariableTable.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/classloader/LocalVariableTable.java 2009-01-11 17:18:07 UTC (rev 15278) +++ rvmroot/trunk/rvm/src/org/jikesrvm/classloader/LocalVariableTable.java 2009-01-13 18:18:15 UTC (rev 15279) @@ -104,8 +104,8 @@ LocalVariable lv = new LocalVariable( input.readUnsignedShort(), input.readUnsignedShort(), - RVMClass.getUtf(constantPool, input.readUnsignedShort()), - RVMClass.getUtf(constantPool, input.readUnsignedShort()), + ClassFileReader.getUtf(constantPool, input.readUnsignedShort()), + ClassFileReader.getUtf(constantPool, input.readUnsignedShort()), input.readUnsignedShort()); lvs[i] = lv; } Modified: rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMAnnotation.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMAnnotation.java 2009-01-11 17:18:07 UTC (rev 15278) +++ rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMAnnotation.java 2009-01-13 18:18:15 UTC (rev 15279) @@ -78,7 +78,7 @@ TypeReference type; // Read type int typeIndex = input.readUnsignedShort(); - type = TypeReference.findOrCreate(classLoader, RVMClass.getUtf(constantPool, typeIndex)); + type = TypeReference.findOrCreate(classLoader, ClassFileReader.getUtf(constantPool, typeIndex)); // Read values int numAnnotationMembers = input.readUnsignedShort(); AnnotationMember[] elementValuePairs = new AnnotationMember[numAnnotationMembers]; @@ -149,75 +149,75 @@ switch (elementValue_tag) { case'B': { if(VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Byte); - Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); + Offset offset = ClassFileReader.getLiteralOffset(constantPool, input.readUnsignedShort()); value = (byte) Statics.getSlotContentsAsInt(offset); break; } case'C': { if(VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Char); - Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); + Offset offset = ClassFileReader.getLiteralOffset(constantPool, input.readUnsignedShort()); value = (char) Statics.getSlotContentsAsInt(offset); break; } case'D': { if(VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Double); - Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); + Offset offset = ClassFileReader.getLiteralOffset(constantPool, input.readUnsignedShort()); long longValue = Statics.getSlotContentsAsLong(offset); value = Double.longBitsToDouble(longValue); break; } case'F': { if(VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Float); - Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); + Offset offset = ClassFileReader.getLiteralOffset(constantPool, input.readUnsignedShort()); int intValue = Statics.getSlotContentsAsInt(offset); value = Float.intBitsToFloat(intValue); break; } case'I': { if(VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Int); - Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); + Offset offset = ClassFileReader.getLiteralOffset(constantPool, input.readUnsignedShort()); value = Statics.getSlotContentsAsInt(offset); break; } case'J': { if(VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Long); - Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); + Offset offset = ClassFileReader.getLiteralOffset(constantPool, input.readUnsignedShort()); value = Statics.getSlotContentsAsLong(offset); break; } case'S': { if(VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Short); - Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); + Offset offset = ClassFileReader.getLiteralOffset(constantPool, input.readUnsignedShort()); value = (short) Statics.getSlotContentsAsInt(offset); break; } case'Z': { if(VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Boolean); - Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); + Offset offset = ClassFileReader.getLiteralOffset(constantPool, input.readUnsignedShort()); value = Statics.getSlotContentsAsInt(offset) == 1; break; } case's': { if(VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.JavaLangString); - value = RVMClass.getUtf(constantPool, input.readUnsignedShort()).toString(); + value = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()).toString(); break; } case'e': { int typeNameIndex = input.readUnsignedShort(); @SuppressWarnings("unchecked") Class enumType = TypeReference.findOrCreate(classLoader, - RVMClass.getUtf(constantPool, typeNameIndex)).resolve().getClassForType(); + ClassFileReader.getUtf(constantPool, typeNameIndex)).resolve().getClassForType(); int constNameIndex = input.readUnsignedShort(); //noinspection unchecked - value = Enum.valueOf(enumType, RVMClass.getUtf(constantPool, constNameIndex).toString()); + value = Enum.valueOf(enumType, ClassFileReader.getUtf(constantPool, constNameIndex).toString()); break; } case'c': { if(VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.JavaLangClass); int classInfoIndex = input.readUnsignedShort(); // Value should be a class but resolving the class at this point could cause infinite recursion in class loading - TypeReference unresolvedValue = TypeReference.findOrCreate(classLoader, RVMClass.getUtf(constantPool, classInfoIndex)); + TypeReference unresolvedValue = TypeReference.findOrCreate(classLoader, ClassFileReader.getUtf(constantPool, classInfoIndex)); if (unresolvedValue.peekType() != null) { value = unresolvedValue.peekType().getClassForType(); } else { @@ -639,7 +639,7 @@ throws IOException, ClassNotFoundException { // Read name of pair int elemNameIndex = input.readUnsignedShort(); - Atom name = RVMClass.getUtf(constantPool, elemNameIndex); + Atom name = ClassFileReader.getUtf(constantPool, elemNameIndex); MethodReference meth; Object value; if (type.isResolved()) { Modified: rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMClass.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMClass.java 2009-01-11 17:18:07 UTC (rev 15278) +++ rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMClass.java 2009-01-13 18:18:15 UTC (rev 15279) @@ -12,8 +12,6 @@ */ package org.jikesrvm.classloader; -import java.io.DataInputStream; -import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.annotation.Inherited; @@ -52,37 +50,13 @@ /** Flag for closed world testing */ public static boolean classLoadingDisabled = false; - /** Constant pool entry for a UTF-8 encoded atom */ - public static final byte CP_UTF = 0; - - /** Constant pool entry for int literal */ - public static final byte CP_INT = 1; - - /** Constant pool entry for long literal */ - public static final byte CP_LONG = 2; - - /** Constant pool entry for float literal */ - public static final byte CP_FLOAT = 3; - - /** Constant pool entry for double literal */ - public static final byte CP_DOUBLE = 4; - - /** Constant pool entry for string literal (for annotations, may be other objects) */ - public static final byte CP_STRING = 5; - - /** Constant pool entry for member (field or method) reference */ - public static final byte CP_MEMBER = 6; - - /** Constant pool entry for type reference or class literal */ - public static final byte CP_CLASS = 7; - /** * The constant pool holds constants used by the class and the Java * bytecodes in the methods associated with this class. This * constant pool isn't that from the class file, instead it has been - * processed during class loading (see {@link #readClass}). The loaded + * processed during class loading (see {@link ClassFileReader#readClass}). The loaded * class' constant pool has 3 bits of type information (such as - * (see {@link #CP_INT})), the rest of the int holds data as follows: + * (see {@link ClassFileReader#CP_INT})), the rest of the int holds data as follows: * * <ul> * <li>utf: value is a UTF atom identifier</li> @@ -623,124 +597,20 @@ // Items are fetched by specifying their "constant pool index". // - @Uninterruptible - static int packCPEntry(byte type, int value) { - return (type << 29) | (value & 0x1fffffff); - } - - @Uninterruptible - private static byte unpackCPType(int cpValue) { - return (byte) (cpValue >>> 29); - } - - @Uninterruptible - private static int unpackSignedCPValue(int cpValue) { - return (cpValue << 3) >> 3; - } - - @Uninterruptible - private static int unpackUnsignedCPValue(int cpValue) { - return cpValue & 0x1fffffff; - } - - @Uninterruptible - private static boolean packedCPTypeIsClassType(int cpValue) { - return (cpValue & (7 << 29)) == (CP_CLASS << 29); - } - - @Uninterruptible - private static int packTempCPEntry(int index1, int index2) { - return (index1 << 16) | (index2 & 0xffff); - } - - @Uninterruptible - private static int unpackTempCPIndex1(int cpValue) { - return cpValue >>> 16; - } - - @Uninterruptible - private static int unpackTempCPIndex2(int cpValue) { - return cpValue & 0xffff; - } - - static int getLiteralSize(int[] constantPool, int constantPoolIndex) { - int cpValue = constantPool[constantPoolIndex]; - switch (unpackCPType(cpValue)) { - case CP_INT: - case CP_FLOAT: - return BYTES_IN_INT; - case CP_LONG: - case CP_DOUBLE: - return BYTES_IN_LONG; - case CP_CLASS: - case CP_STRING: - return BYTES_IN_ADDRESS; - default: - VM._assert(NOT_REACHED); - return 0; - } - } - /** * Get offset of a literal constant, in bytes. * Offset is with respect to virtual machine's "table of contents" (jtoc). */ public Offset getLiteralOffset(int constantPoolIndex) { - return getLiteralOffset(this.constantPool, constantPoolIndex); + return ClassFileReader.getLiteralOffset(this.constantPool, constantPoolIndex); } /** - * Get offset of a literal constant, in bytes. - * Offset is with respect to virtual machine's "table of contents" (jtoc). - */ - static Offset getLiteralOffset(int[] constantPool, int constantPoolIndex) { - int cpValue = constantPool[constantPoolIndex]; - if (VM.VerifyAssertions) { - int value = unpackSignedCPValue(cpValue); - byte type = unpackCPType(cpValue); - switch (type) { - case CP_INT: - case CP_FLOAT: - case CP_LONG: - case CP_DOUBLE: - case CP_STRING: - return Offset.fromIntSignExtend(value); - case CP_CLASS: { - int typeId = unpackUnsignedCPValue(cpValue); - Class<?> literalAsClass = TypeReference.getTypeRef(typeId).resolve().getClassForType(); - return Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(literalAsClass)); - } - default: - VM._assert(NOT_REACHED); - return Offset.fromIntSignExtend(0xebad0ff5); - } - } else { - if (packedCPTypeIsClassType(cpValue)) { - int typeId = unpackUnsignedCPValue(cpValue); - Class<?> literalAsClass = TypeReference.getTypeRef(typeId).resolve().getClassForType(); - return Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(literalAsClass)); - } else { - int value = unpackSignedCPValue(cpValue); - return Offset.fromIntSignExtend(value); - } - } - } - - /** * Get description of a literal constant. */ - static byte getLiteralDescription(int[] constantPool, int constantPoolIndex) { - int cpValue = constantPool[constantPoolIndex]; - byte type = unpackCPType(cpValue); - return type; - } - - /** - * Get description of a literal constant. - */ public byte getLiteralDescription(int constantPoolIndex) { int cpValue = constantPool[constantPoolIndex]; - byte type = unpackCPType(cpValue); + byte type = ClassFileReader.unpackCPType(cpValue); return type; } @@ -750,83 +620,38 @@ */ @Uninterruptible public TypeReference getTypeRef(int constantPoolIndex) { - return getTypeRef(constantPool, constantPoolIndex); + return ClassFileReader.getTypeRef(constantPool, constantPoolIndex); } /** - * Get contents of a "typeRef" constant pool entry. - * @return type that was referenced - */ - @Uninterruptible - static TypeReference getTypeRef(int[] constantPool, int constantPoolIndex) { - if (constantPoolIndex != 0) { - int cpValue = constantPool[constantPoolIndex]; - if (VM.VerifyAssertions) VM._assert(unpackCPType(cpValue) == CP_CLASS); - return TypeReference.getTypeRef(unpackUnsignedCPValue(cpValue)); - } else { - return null; - } - } - - /** * Get contents of a "methodRef" constant pool entry. */ @Uninterruptible public MethodReference getMethodRef(int constantPoolIndex) { - return getMethodRef(constantPool, constantPoolIndex); + return ClassFileReader.getMethodRef(constantPool, constantPoolIndex); } /** - * Get contents of a "methodRef" constant pool entry. - */ - @Uninterruptible - static MethodReference getMethodRef(int[] constantPool, int constantPoolIndex) { - int cpValue = constantPool[constantPoolIndex]; - if (VM.VerifyAssertions) VM._assert(unpackCPType(cpValue) == CP_MEMBER); - return (MethodReference) MemberReference.getMemberRef(unpackUnsignedCPValue(cpValue)); - } - - /** * Get contents of a "fieldRef" constant pool entry. */ @Uninterruptible public FieldReference getFieldRef(int constantPoolIndex) { int cpValue = constantPool[constantPoolIndex]; - if (VM.VerifyAssertions) VM._assert(unpackCPType(cpValue) == CP_MEMBER); - return (FieldReference) MemberReference.getMemberRef(unpackUnsignedCPValue(cpValue)); + if (VM.VerifyAssertions) VM._assert(ClassFileReader.unpackCPType(cpValue) == ClassFileReader.CP_MEMBER); + return (FieldReference) MemberReference.getMemberRef(ClassFileReader.unpackUnsignedCPValue(cpValue)); } /** - * Get contents of a "methodRef" constant pool entry. - */ - @Uninterruptible - static FieldReference getFieldRef(int[] constantPool, int constantPoolIndex) { - int cpValue = constantPool[constantPoolIndex]; - if (VM.VerifyAssertions) VM._assert(unpackCPType(cpValue) == CP_MEMBER); - return (FieldReference) MemberReference.getMemberRef(unpackUnsignedCPValue(cpValue)); - } - - /** * Get contents of a "utf" constant pool entry. */ @Uninterruptible Atom getUtf(int constantPoolIndex) { int cpValue = constantPool[constantPoolIndex]; - if (VM.VerifyAssertions) VM._assert(unpackCPType(cpValue) == CP_UTF); - return Atom.getAtom(unpackUnsignedCPValue(cpValue)); + if (VM.VerifyAssertions) VM._assert(ClassFileReader.unpackCPType(cpValue) == ClassFileReader.CP_UTF); + return Atom.getAtom(ClassFileReader.unpackUnsignedCPValue(cpValue)); } /** - * Get contents of a "utf" from a constant pool entry. - */ - @Uninterruptible - static Atom getUtf(int[] constantPool, int constantPoolIndex) { - int cpValue = constantPool[constantPoolIndex]; - if (VM.VerifyAssertions) VM._assert(unpackCPType(cpValue) == CP_UTF); - return Atom.getAtom(unpackUnsignedCPValue(cpValue)); - } - - /** * Return true if the SynchronizedObject annotation is present. * @see org.vmmagic.pragma.SynchronizedObject */ @@ -1168,11 +993,11 @@ * @param signature the generic type name for this class * @param annotations array of runtime visible annotations */ - private RVMClass(TypeReference typeRef, int[] constantPool, short modifiers, RVMClass superClass, - RVMClass[] declaredInterfaces, RVMField[] declaredFields, RVMMethod[] declaredMethods, - TypeReference[] declaredClasses, TypeReference declaringClass, TypeReference enclosingClass, - MethodReference enclosingMethod, Atom sourceName, RVMMethod classInitializerMethod, - Atom signature, RVMAnnotation[] annotations) { + RVMClass(TypeReference typeRef, int[] constantPool, short modifiers, RVMClass superClass, + RVMClass[] declaredInterfaces, RVMField[] declaredFields, RVMMethod[] declaredMethods, + TypeReference[] declaredClasses, TypeReference declaringClass, TypeReference enclosingClass, + MethodReference enclosingMethod, Atom sourceName, RVMMethod classInitializerMethod, + Atom signature, RVMAnnotation[] annotations) { super(typeRef, 0, annotations); if (VM.VerifyAssertions) VM._assert(!getTypeRef().isUnboxedType()); if (VM.VerifyAssertions && null != superClass) VM._assert(!superClass.getTypeRef().isUnboxedType()); @@ -1218,348 +1043,6 @@ } /** - * Create an instance of a RVMClass. - * @param typeRef the cannonical type reference for this type. - * @param input the data stream from which to read the class's description. - */ - static RVMClass readClass(TypeReference typeRef, DataInputStream input) throws ClassFormatError, IOException { - - if (classLoadingDisabled) { - throw new RuntimeException("ClassLoading Disabled : " + typeRef); - } - - if (VM.TraceClassLoading && VM.runningVM) { - VM.sysWrite("RVMClass: (begin) load file " + typeRef.getName() + "\n"); - } - - int magic = input.readInt(); - if (magic != 0xCAFEBABE) { - throw new ClassFormatError("bad magic number " + Integer.toHexString(magic)); - } - - // Get the class file version number and check to see if it is a version - // that we support. - int minor = input.readUnsignedShort(); - int major = input.readUnsignedShort(); - switch (major) { - case 45: - case 46: - case 47: - case 48: - case 49: // we support all variants of these major versions so the minor number doesn't matter. - break; - case 50: // we only support up to 50.0 (ie Java 1.6.0) - if (minor == 0) break; - default: - throw new UnsupportedClassVersionError("unsupported class file version " + major + "." + minor); - } - - // - // pass 1: read constant pool - // - int[] constantPool = new int[input.readUnsignedShort()]; - byte[] tmpTags = new byte[constantPool.length]; - - // note: slot 0 is unused - for (int i = 1; i < constantPool.length; i++) { - tmpTags[i] = input.readByte(); - switch (tmpTags[i]) { - case TAG_UTF: { - byte[] utf = new byte[input.readUnsignedShort()]; - input.readFully(utf); - int atomId = Atom.findOrCreateUtf8Atom(utf).getId(); - constantPool[i] = packCPEntry(CP_UTF, atomId); - break; - } - case TAG_UNUSED: - if (VM.VerifyAssertions) VM._assert(NOT_REACHED); - break; - - case TAG_INT: { - int literal = input.readInt(); - int offset = Statics.findOrCreateIntSizeLiteral(literal); - constantPool[i] = packCPEntry(CP_INT, offset); - break; - } - case TAG_FLOAT: { - int literal = input.readInt(); - int offset = Statics.findOrCreateIntSizeLiteral(literal); - constantPool[i] = packCPEntry(CP_FLOAT, offset); - break; - } - case TAG_LONG: { - long literal = input.readLong(); - int offset = Statics.findOrCreateLongSizeLiteral(literal); - constantPool[i] = packCPEntry(CP_LONG, offset); - i++; - break; - } - case TAG_DOUBLE: { - long literal = input.readLong(); - int offset = Statics.findOrCreateLongSizeLiteral(literal); - constantPool[i] = packCPEntry(CP_DOUBLE, offset); - i++; - break; - } - case TAG_TYPEREF: - constantPool[i] = input.readUnsignedShort(); - break; - - case TAG_STRING: - constantPool[i] = input.readUnsignedShort(); - break; - - case TAG_FIELDREF: - case TAG_METHODREF: - case TAG_INTERFACE_METHODREF: { - int classDescriptorIndex = input.readUnsignedShort(); - int memberNameAndDescriptorIndex = input.readUnsignedShort(); - constantPool[i] = packTempCPEntry(classDescriptorIndex, memberNameAndDescriptorIndex); - break; - } - - case TAG_MEMBERNAME_AND_DESCRIPTOR: { - int memberNameIndex = input.readUnsignedShort(); - int descriptorIndex = input.readUnsignedShort(); - constantPool[i] = packTempCPEntry(memberNameIndex, descriptorIndex); - break; - } - - default: - throw new ClassFormatError("bad constant pool"); - } - } - - // - // pass 2: post-process type and string constant pool entries - // (we must do this in a second pass because of forward references) - // - try { - for (int i = 1; i < constantPool.length; i++) { - switch (tmpTags[i]) { - case TAG_LONG: - case TAG_DOUBLE: - ++i; - break; - - case TAG_TYPEREF: { // in: utf index - Atom typeName = getUtf(constantPool, constantPool[i]); - int typeRefId = - TypeReference.findOrCreate(typeRef.getClassLoader(), typeName.descriptorFromClassName()).getId(); - constantPool[i] = packCPEntry(CP_CLASS, typeRefId); - break; - } // out: type reference id - - case TAG_STRING: { // in: utf index - Atom literal = getUtf(constantPool, constantPool[i]); - int offset = literal.getStringLiteralOffset(); - constantPool[i] = packCPEntry(CP_STRING, offset); - break; - } // out: jtoc slot number - } - } - } catch (java.io.UTFDataFormatException x) { - throw new ClassFormatError(x.toString()); - } - - // - // pass 3: post-process type field and method constant pool entries - // - for (int i = 1; i < constantPool.length; i++) { - switch (tmpTags[i]) { - case TAG_LONG: - case TAG_DOUBLE: - ++i; - break; - - case TAG_FIELDREF: - case TAG_METHODREF: - case TAG_INTERFACE_METHODREF: { // in: classname+membername+memberdescriptor indices - int bits = constantPool[i]; - int classNameIndex = unpackTempCPIndex1(bits); - int memberNameAndDescriptorIndex = unpackTempCPIndex2(bits); - int memberNameAndDescriptorBits = constantPool[memberNameAndDescriptorIndex]; - int memberNameIndex = unpackTempCPIndex1(memberNameAndDescriptorBits); - int memberDescriptorIndex = unpackTempCPIndex2(memberNameAndDescriptorBits); - - TypeReference tref = getTypeRef(constantPool, classNameIndex); - Atom memberName = getUtf(constantPool, memberNameIndex); - Atom memberDescriptor = getUtf(constantPool, memberDescriptorIndex); - MemberReference mr = MemberReference.findOrCreate(tref, memberName, memberDescriptor); - int mrId = mr.getId(); - constantPool[i] = packCPEntry(CP_MEMBER, mrId); - break; - } // out: MemberReference id - } - } - - short modifiers = input.readShort(); - int myTypeIndex = input.readUnsignedShort(); - TypeReference myTypeRef = getTypeRef(constantPool, myTypeIndex); - if (myTypeRef != typeRef) { - // eg. file contains a different class than would be - // expected from its .class file name - if (!VM.VerifyAssertions) { - throw new ClassFormatError("expected class \"" + - typeRef.getName() + - "\" but found \"" + - myTypeRef.getName() + - "\""); - } else { - throw new ClassFormatError("expected class \"" + - typeRef.getName() + - "\" but found \"" + - myTypeRef.getName() + - "\"\n" + typeRef + " != " + myTypeRef); - } - } - - TypeReference superType = getTypeRef(constantPool, input.readUnsignedShort()); // possibly null - RVMClass superClass = null; - if (((modifiers & ACC_INTERFACE) == 0) && (superType != null)) { - superClass = superType.resolve().asClass(); - } - - int numInterfaces = input.readUnsignedShort(); - RVMClass[] declaredInterfaces; - if (numInterfaces == 0) { - declaredInterfaces = emptyVMClass; - } else { - declaredInterfaces = new RVMClass[numInterfaces]; - for (int i = 0; i < numInterfaces; ++i) { - TypeReference inTR = getTypeRef(constantPool, input.readUnsignedShort()); - declaredInterfaces[i] = inTR.resolve().asClass(); - } - } - - int numFields = input.readUnsignedShort(); - RVMField[] declaredFields; - if (numFields == 0) { - declaredFields = emptyVMField; - } else { - declaredFields = new RVMField[numFields]; - for (int i = 0; i < numFields; i++) { - short fmodifiers = input.readShort(); - Atom fieldName = getUtf(constantPool, input.readUnsignedShort()); - Atom fieldDescriptor = getUtf(constantPool, input.readUnsignedShort()); - MemberReference memRef = MemberReference.findOrCreate(typeRef, fieldName, fieldDescriptor); - declaredFields[i] = RVMField.readField(typeRef, constantPool, memRef, fmodifiers, input); - } - } - - int numMethods = input.readUnsignedShort(); - RVMMethod[] declaredMethods; - RVMMethod classInitializerMethod = null; - if (numMethods == 0) { - declaredMethods = emptyVMMethod; - } else { - declaredMethods = new RVMMethod[numMethods]; - for (int i = 0; i < numMethods; i++) { - short mmodifiers = input.readShort(); - Atom methodName = getUtf(constantPool, input.readUnsignedShort()); - Atom methodDescriptor = getUtf(constantPool, input.readUnsignedShort()); - MemberReference memRef = MemberReference.findOrCreate(typeRef, methodName, methodDescriptor); - RVMMethod method = RVMMethod.readMethod(typeRef, constantPool, memRef, mmodifiers, input); - declaredMethods[i] = method; - if (method.isClassInitializer()) { - classInitializerMethod = method; - } - } - } - TypeReference[] declaredClasses = null; - Atom sourceName = null; - TypeReference declaringClass = null; - Atom signature = null; - RVMAnnotation[] annotations = null; - TypeReference enclosingClass = null; - MethodReference enclosingMethod = null; - // Read attributes. - for (int i = 0, n = input.readUnsignedShort(); i < n; ++i) { - Atom attName = getUtf(constantPool, input.readUnsignedShort()); - int attLength = input.readInt(); - - // Class attributes - if (attName == RVMClassLoader.sourceFileAttributeName && attLength == 2) { - sourceName = getUtf(constantPool, input.readUnsignedShort()); - } else if (attName == RVMClassLoader.innerClassesAttributeName) { - // Parse InnerClasses attribute, and use the information to populate - // the list of declared member classes. We do this so we can - // support the java.lang.Class.getDeclaredClasses() - // and java.lang.Class.getDeclaredClass methods. - - int numberOfClasses = input.readUnsignedShort(); - declaredClasses = new TypeReference[numberOfClasses]; - - for (int j = 0; j < numberOfClasses; ++j) { - int innerClassInfoIndex = input.readUnsignedShort(); - int outerClassInfoIndex = input.readUnsignedShort(); - int innerNameIndex = input.readUnsignedShort(); - int innerClassAccessFlags = input.readUnsignedShort(); - - if (innerClassInfoIndex != 0 && outerClassInfoIndex == myTypeIndex && innerNameIndex != 0) { - // This looks like a declared inner class. - declaredClasses[j] = getTypeRef(constantPool, innerClassInfoIndex); - } - - if (innerClassInfoIndex == myTypeIndex) { - if (outerClassInfoIndex != 0) { - declaringClass = getTypeRef(constantPool, outerClassInfoIndex); - if (enclosingClass == null) { - // TODO: is this the null test necessary? - enclosingClass = declaringClass; - } - } - if ((innerClassAccessFlags & (ACC_PRIVATE | ACC_PROTECTED)) != 0) { - modifiers &= ~(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED); - } - modifiers |= innerClassAccessFlags; - } - } - } else if (attName == RVMClassLoader.syntheticAttributeName) { - modifiers |= ACC_SYNTHETIC; - } else if (attName == RVMClassLoader.enclosingMethodAttributeName) { - int enclosingClassIndex = input.readUnsignedShort(); - enclosingClass = getTypeRef(constantPool, enclosingClassIndex); - - int enclosingMethodIndex = input.readUnsignedShort(); - if (enclosingMethodIndex != 0) { - int memberNameIndex = constantPool[enclosingMethodIndex] >>> BITS_IN_SHORT; - int memberDescriptorIndex = constantPool[enclosingMethodIndex] & ((1 << BITS_IN_SHORT) - 1); - Atom memberName = getUtf(constantPool, memberNameIndex); - Atom memberDescriptor = getUtf(constantPool, memberDescriptorIndex); - enclosingMethod = - MemberReference.findOrCreate(enclosingClass, memberName, memberDescriptor).asMethodReference(); - } - } else if (attName == RVMClassLoader.signatureAttributeName) { - signature = RVMClass.getUtf(constantPool, input.readUnsignedShort()); - } else if (attName == RVMClassLoader.runtimeVisibleAnnotationsAttributeName) { - annotations = AnnotatedElement.readAnnotations(constantPool, input, typeRef.getClassLoader()); - } else { - int skippedAmount = input.skipBytes(attLength); - if (skippedAmount != attLength) { - throw new IOException("Unexpected short skip"); - } - } - } - - return new RVMClass(typeRef, - constantPool, - modifiers, - superClass, - declaredInterfaces, - declaredFields, - declaredMethods, - declaredClasses, - declaringClass, - enclosingClass, - enclosingMethod, - sourceName, - classInitializerMethod, - signature, - annotations); - } - - /** * Generate size and offset information for members of this class and * allocate space in jtoc for static fields, static... [truncated message content] |