Revision: 5681 http://jnode.svn.sourceforge.net/jnode/?rev=5681&view=rev Author: crawley Date: 2009-09-18 07:23:15 +0000 (Fri, 18 Sep 2009)
Log Message: ----------- When a native method is replaced with a Java one (from a Native... class), the method's bytecode stream must still use the constant pool for the Native... class. Modified Paths: -------------- branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_BytecodeStream.java branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_Method.java branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_NormalMethod.java branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/ClassDecoder.java branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/Modifier.java branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/VmMember.java branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/VmMethod.java Modified: branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_BytecodeStream.java =================================================================== --- branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_BytecodeStream.java 2009-09-18 07:00:06 UTC (rev 5680) +++ branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_BytecodeStream.java 2009-09-18 07:23:15 UTC (rev 5681) @@ -16,8 +16,8 @@ * @author Igor Pechtchanski */ public class VM_BytecodeStream implements VM_BytecodeConstants, VM_SizeConstants { - private final VM_NormalMethod method; - private final VM_Class declaringClass; + private VM_NormalMethod method; + private VM_Class declaringClass; private final int bcLength; private final byte[] bcodes; private int bcIndex; @@ -25,6 +25,7 @@ private boolean wide; /** + * Create a bytecode stream from a method descriptor and an array of bytecodes. * @param m the method containing the bytecodes * @param bc the array of bytecodes */ @@ -35,6 +36,15 @@ bcLength = bc.length; bcIndex = 0; } + + /** + * Create a bytecode stream from an existing one. The method and bytecode + * array will be shared. + * @param stream the existing bytecode stream + */ + public VM_BytecodeStream(VM_BytecodeStream stream) { + this(stream.method, stream.bcodes); + } /** * Returns the method that this bytecode stream is from @@ -61,6 +71,14 @@ public final int length() { return bcLength; } + + /** + * Returns the bytecodes or {...@code null}. + * @return the bytecode array + */ + public final byte[] bytecodes() { + return bcodes; + } /** * Returns the current bytecode index Modified: branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_Method.java =================================================================== --- branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_Method.java 2009-09-18 07:00:06 UTC (rev 5680) +++ branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_Method.java 2009-09-18 07:23:15 UTC (rev 5681) @@ -2,6 +2,7 @@ import java.nio.ByteBuffer; +import org.jnode.vm.classmgr.VmByteCode; import org.jnode.vm.classmgr.VmExceptions; import org.jnode.vm.classmgr.VmInstanceMethod; import org.jnode.vm.classmgr.VmLineNumberMap; @@ -41,7 +42,7 @@ } public final boolean hasNoInlinePragma() { - return ((VmMethod)jnodeMember).hasNoInlinePragma(); + return ((VmMethod) jnodeMember).hasNoInlinePragma(); } @@ -50,22 +51,24 @@ } public void invalidateCompiledMethod(VM_CompiledMethod cm) { - if (VM.VerifyAssertions) VM._assert(declaringClass.isInstantiated()); + if (VM.VerifyAssertions) { + VM._assert(declaringClass.isInstantiated()); + } if (currentCompiledMethod == cm) { - replaceCompiledMethod(null); + replaceCompiledMethod(null); } } public boolean isObjectInitializer() { - return ((VmMethod)jnodeMember).isConstructor(); + return ((VmMethod) jnodeMember).isConstructor(); } public boolean isNative() { - return ((VmMethod)jnodeMember).isNative(); + return ((VmMethod) jnodeMember).isNative(); } public boolean isAbstract() { - return ((VmMethod)jnodeMember).isAbstract(); + return ((VmMethod) jnodeMember).isAbstract(); } public boolean mayWrite(VM_Field f) { @@ -73,15 +76,15 @@ } public boolean isInterruptible() { - return !((VmMethod)jnodeMember).isUninterruptible(); + return !((VmMethod) jnodeMember).isUninterruptible(); } public boolean hasInlinePragma() { - return ((VmMethod)jnodeMember).hasInlinePragma(); + return ((VmMethod) jnodeMember).hasInlinePragma(); } public boolean isClassInitializer() { - return ((VmMethod)jnodeMember).isInitializer(); + return ((VmMethod) jnodeMember).isInitializer(); } public boolean isCompiled() { @@ -102,20 +105,26 @@ * Check that it provides the functionality you want before calling it. */ public static VM_Method buildFromJnodeMethod(VmMethod method) { - if(method == null) return null; - VM_Class dc = VM_Class.buildFromJnodeClass(method.getDeclaringClass()); + if (method == null) { + return null; + } + VM_Class dc = method.isReplacement() ? + VM_Class.buildFromJnodeClass(method.getRealDeclaringClass()) : + VM_Class.buildFromJnodeClass(method.getDeclaringClass()); String name = method.getName(); String desc = method.getSignature(); VM_Atom mn = VM_Atom.findOrCreateAsciiAtom(name); VM_Atom d = VM_Atom.findOrCreateAsciiAtom(desc); VM_MemberReference mr = VM_MemberReference.findOrCreate(dc.getTypeRef(), mn, d); - if (((VM_MethodReference)mr).isResolved()) - return (VM_Method)mr.resolveMember(); - VM_Method jikesMethod; - if(method.isAbstract()) - return jikesMethod = new VM_AbstractMethod(dc, mr, method.getModifiers(), null, method); - if(method.isNative()) - return jikesMethod = new VM_NativeMethod(dc, mr, method.getModifiers(), null, method); + if (((VM_MethodReference) mr).isResolved()) { + return (VM_Method) mr.resolveMember(); + } + if (method.isAbstract()) { + return new VM_AbstractMethod(dc, mr, method.getModifiers(), null, method); + } + if (method.isNative()) { + return new VM_NativeMethod(dc, mr, method.getModifiers(), null, method); + } //If we reach here the method is definitely "normal", i.e. not native and not abstract int bclength = method.getBytecodeSize(); @@ -125,27 +134,34 @@ VmExceptions jnodeExceptions = method.getExceptions(); VM_ExceptionHandlerMap eMap = null; int n = method.getBytecode().getExceptionHandlers().size(); - if (n!=0) eMap = new VM_ExceptionHandlerMap(method.getBytecode().getExceptionHandlers(), dc, n); - VmLineNumberMap jnodeLineMap = method.getBytecode().getLineNrs(); - int [] lineMap = new int[jnodeLineMap.getLength()]; - for (int i = 0; i < lineMap.length; i++) { - int startPC = jnodeLineMap.getStartPCAt(i); - int lineNumber = jnodeLineMap.getLineNrAt(i); - lineMap[i] = (lineNumber << BITS_IN_SHORT) | startPC; + if (n != 0) { + eMap = new VM_ExceptionHandlerMap(method.getBytecode().getExceptionHandlers(), dc, n); } - return jikesMethod = new VM_NormalMethod(dc, mr, method.getModifiers(), + VmLineNumberMap jnodeLineMap = method.getBytecode().getLineNrs(); + int [] lineMap; + if (jnodeLineMap == null) { + // FIXME ... figure out why this happens + lineMap = null; + } else { + lineMap = new int[jnodeLineMap.getLength()]; + for (int i = 0; i < lineMap.length; i++) { + int startPC = jnodeLineMap.getStartPCAt(i); + int lineNumber = jnodeLineMap.getLineNrAt(i); + lineMap[i] = (lineNumber << BITS_IN_SHORT) | startPC; + } + } + VM_NormalMethod jikesMethod = new VM_NormalMethod(dc, mr, method.getModifiers(), null, method.getBytecode().getNoLocals(), method.getNoArguments(), bcodes, eMap, lineMap, method); - - + return jikesMethod; } public int getSelector() { - return ((VmMethod)jnodeMember).getSelector(); + return ((VmMethod) jnodeMember).getSelector(); } public Offset getTibOffset() { - return Offset.fromIntZeroExtend(((VmInstanceMethod)jnodeMember).getTibOffset()); + return Offset.fromIntZeroExtend(((VmInstanceMethod) jnodeMember).getTibOffset()); } Modified: branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_NormalMethod.java =================================================================== --- branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_NormalMethod.java 2009-09-18 07:00:06 UTC (rev 5680) +++ branches/jikesRVM/core/src/core/com/ibm/JikesRVM/classloader/VM_NormalMethod.java 2009-09-18 07:23:15 UTC (rev 5681) @@ -132,7 +132,7 @@ /** * bytecodes for this method (null --> none) */ - private final byte[] bytecodes; + private final VM_BytecodeStream bytecodes; // Extra fields for on-stack replacement // TODO: rework the system so we don't waste space for this on the VM_Method @@ -152,12 +152,12 @@ private VM_ExceptionHandlerMap exceptionHandlerMap; public VM_NormalMethod(VM_Class dc, VM_MemberReference mr, int mo, - VM_TypeReference[] et, int lw, int ow, byte[] bc, + VM_TypeReference[] et, int lw, int ow, byte[] bcodes, VM_ExceptionHandlerMap eMap, int[] lm, VmMethod ref) { super(dc, mr, mo, et, ref); localWords = lw; operandWords = ow; - bytecodes = bc; + bytecodes = new VM_BytecodeStream(this, bcodes); exceptionHandlerMap = eMap; lineNumberMap = lm; computeSummary(); @@ -188,7 +188,7 @@ * @return object representing the bytecodes */ public final VM_BytecodeStream getBytecodes() { - return new VM_BytecodeStream(this, bytecodes); + return new VM_BytecodeStream(bytecodes); } @@ -257,10 +257,10 @@ if (VM.VerifyAssertions) VM._assert(this.synthesizedBytecodes == null); - byte[] newBytecodes = new byte[prologue.length + bytecodes.length]; + byte[] newBytecodes = new byte[prologue.length + bytecodes.length()]; System.arraycopy(prologue, 0, newBytecodes, 0, prologue.length); - System.arraycopy(bytecodes, 0, newBytecodes, prologue.length, - bytecodes.length); + System.arraycopy(bytecodes.bytecodes(), 0, newBytecodes, prologue.length, + bytecodes.length()); this.osrPrologue = prologue; this.synthesizedBytecodes = newBytecodes; Modified: branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/ClassDecoder.java =================================================================== --- branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/ClassDecoder.java 2009-09-18 07:00:06 UTC (rev 5680) +++ branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/ClassDecoder.java 2009-09-18 07:23:15 UTC (rev 5681) @@ -1034,7 +1034,9 @@ rejectNatives); if (bc != null) { mts.setModifier(false, Modifier.ACC_NATIVE); + mts.setModifier(true, Modifier.ACC_REPLACED); mts.setBytecode(bc); + mts.setRealDeclaringClass(bc.getMethod().getDeclaringClass()); } else { if (rejectNatives) { throw new ClassFormatError("Native method " + mts); Modified: branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/Modifier.java =================================================================== --- branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/Modifier.java 2009-09-18 07:00:06 UTC (rev 5680) +++ branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/Modifier.java 2009-09-18 07:23:15 UTC (rev 5681) @@ -62,6 +62,12 @@ public static final int ACC_MAGIC = 0x10000000; // C /** + * Is this a replaced method; i.e. one declared as native and + * then replaced with a Java method by the boot image builder. + */ + public static final int ACC_REPLACED = 0x40000000; + + /** * Is this a special method (init, clinit) */ public static final int ACC_SPECIAL = 0x80000000; @@ -114,6 +120,10 @@ return ((modifier & ACC_NATIVE) != 0); } + public static boolean isReplaced(int modifier) { + return ((modifier & ACC_REPLACED) != 0); + } + public static boolean isInterface(int modifier) { return ((modifier & ACC_INTERFACE) != 0); } Modified: branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/VmMember.java =================================================================== --- branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/VmMember.java 2009-09-18 07:00:06 UTC (rev 5680) +++ branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/VmMember.java 2009-09-18 07:23:15 UTC (rev 5681) @@ -44,10 +44,14 @@ */ private int modifiers; /** - * Declaring class of this member + * Notional declaring class of this member */ protected final VmType<?> declaringClass; /** + * Actual declaring class of this member + */ + protected VmType<?> realDeclaringClass; + /** * Hashcode of name+signature */ private final int cachedHashCode; @@ -60,7 +64,8 @@ * @param modifiers * @param declaringClass */ - protected VmMember(String name, String signature, int modifiers, VmType declaringClass) { + protected VmMember(String name, String signature, int modifiers, + VmType declaringClass) { if (name.equals("<clinit>")) { modifiers |= Modifier.ACC_INITIALIZER; } else if (name.equals("<init>")) { @@ -73,6 +78,7 @@ this.signature = signature; this.modifiers = modifiers; this.declaringClass = declaringClass; + this.realDeclaringClass = declaringClass; this.cachedHashCode = calcHashCode(name, signature); } @@ -133,7 +139,7 @@ } /** - * Gets the Class i'm declared in. + * Gets the Class i'm notionally declared in. * * @return VmClass */ @@ -144,6 +150,26 @@ } /** + * Gets the Class i'm actually declared in. This differs from the + * notional declaring class if this is a native method that has been + * replaced by a Java method. + * + * @return VmClass + */ + @KernelSpace + @org.jnode.annotation.Uninterruptible + public final VmType<?> getRealDeclaringClass() { + return realDeclaringClass; + } + + /** + * Sets the Class i'm actually declared in. + */ + public void setRealDeclaringClass(VmType<?> realDeclaringClass) { + this.realDeclaringClass = realDeclaringClass; + } + + /** * Is this member public? * * @return boolean Modified: branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/VmMethod.java =================================================================== --- branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/VmMethod.java 2009-09-18 07:00:06 UTC (rev 5680) +++ branches/jikesRVM/core/src/core/org/jnode/vm/classmgr/VmMethod.java 2009-09-18 07:23:15 UTC (rev 5681) @@ -113,7 +113,7 @@ * @param declaringClass */ protected VmMethod(String name, String signature, int modifiers, - VmType<?> declaringClass) { + VmType<?> declaringClass) { super( name, signature, @@ -310,7 +310,11 @@ public final boolean isNative() { return Modifier.isNative(getModifiers()); } - + + public boolean isReplacement() { + return Modifier.isReplaced(getModifiers()); + } + public final boolean isSpecial() { return Modifier.isSpecial(getModifiers()); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Come build with us! The BlackBerry® Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9-12, 2009. Register now! http://p.sf.net/sfu/devconf _______________________________________________ Jnode-svn-commits mailing list Jnode-svn-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jnode-svn-commits