From: <cap...@us...> - 2007-03-20 18:53:30
|
Revision: 6 http://svn.sourceforge.net/pearcolator/?rev=6&view=rev Author: captain5050 Date: 2007-03-20 08:49:03 -0700 (Tue, 20 Mar 2007) Log Message: ----------- Build fixes. Move files from rvm into dbt Modified Paths: -------------- build.xml src/org/binarytranslator/vmInterface/DBT_Trace.java Added Paths: ----------- ext/DBT_Dummy.java ext/org/jikesrvm/classloader/ ext/org/jikesrvm/classloader/VM_Member.java ext/org/jikesrvm/classloader/VM_Method.java ext/org/jikesrvm/classloader/VM_NormalMethod.java ext/org/jikesrvm/opt/OPT_Simplifier.java ext/org/jikesrvm/opt/ir/OPT_BC2IR.java ext/org/jikesrvm/opt/ir/OPT_ConditionOperand.java ext/org/jikesrvm/opt/ir/OPT_GenerationContext.java ext/org/jikesrvm/opt/ir/OPT_HIRInfo.java ext/org/jikesrvm/opt/ir/ia32/ ext/org/jikesrvm/opt/ir/ia32/OPT_IA32ConditionOperand.java Modified: build.xml =================================================================== --- build.xml 2007-03-19 16:01:57 UTC (rev 5) +++ build.xml 2007-03-20 15:49:03 UTC (rev 6) @@ -15,16 +15,34 @@ </javac> </target> <target name="compile-external"> + <delete verbose="true"> + <fileset dir="${build.classes}"> + <include name="org/jikesrvm/opt/ir/ia32/OPT_IA32ConditionOperand.class" /> + <include name="org/jikesrvm/opt/ir/OPT_HIRGenerator.class" /> + <include name="org/jikesrvm/opt/ir/OPT_GenerationContext.class" /> + <include name="org/jikesrvm/opt/ir/OPT_ConditionOperand.class" /> + <include name="org/jikesrvm/opt/ir/OPT_BC2IR.class" /> + <include name="org/jikesrvm/opt/ir/OPT_HIRInfo.class" /> + <include name="org/jikesrvm/opt/OPT_Simplifier.class" /> + <include name="org/jikesrvm/ppc/PPC_Disassembler.class" /> + <include name="org/jikesrvm/ppc/opcode_tab.class" /> + <include name="org/jikesrvm/ppc/opcodeXX.class" /> + <include name="org/jikesrvm/classloader/VM_Method.class" /> + <include name="org/jikesrvm/classloader/VM_Member.class" /> + <include name="org/jikesrvm/classloader/VM_NormalMethod.class" /> + </fileset> + </delete> <javac destdir="${build.classes}" debug="true" debugLevel="lines,source" source="1.5" target="1.5" srcdir="${dbt-ext.java}"> + <include name="DBT_Dummy.java" /> <classpath> <pathelement location="${build.vmmagic-stub.classes}"/> <pathelement location="${build.classes}"/> </classpath> </javac> </target> -</project> \ No newline at end of file +</project> Added: ext/DBT_Dummy.java =================================================================== --- ext/DBT_Dummy.java (rev 0) +++ ext/DBT_Dummy.java 2007-03-20 15:49:03 UTC (rev 6) @@ -0,0 +1,25 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + */ + +/** + * Dummy class containing enough references to force java compiler + * to find every class comprising the chnages to the opt compiler for DBT + */ +class OptDummy { + static org.jikesrvm.opt.ir.ia32.OPT_IA32ConditionOperand a; + static org.jikesrvm.opt.ir.OPT_HIRGenerator b; + static org.jikesrvm.opt.ir.OPT_GenerationContext c; + static org.jikesrvm.opt.ir.OPT_ConditionOperand d; + static org.jikesrvm.opt.ir.OPT_HIRInfo e; + static org.jikesrvm.opt.OPT_Simplifier f; + static org.jikesrvm.ppc.PPC_Disassembler g; + static org.jikesrvm.classloader.VM_Method j; + static org.jikesrvm.classloader.VM_Member k; + static org.jikesrvm.classloader.VM_NormalMethod l; +} Added: ext/org/jikesrvm/classloader/VM_Member.java =================================================================== --- ext/org/jikesrvm/classloader/VM_Member.java (rev 0) +++ ext/org/jikesrvm/classloader/VM_Member.java 2007-03-20 15:49:03 UTC (rev 6) @@ -0,0 +1,197 @@ +/* + * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net). + * The Jikes RVM project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright IBM Corp 2001,2002 + */ +package org.jikesrvm.classloader; + +import org.jikesrvm.*; +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Offset; + +/** + * A field or method of a java class. + * + * @author Bowen Alpern + * @author Dave Grove + * @author Derek Lieber + */ +public abstract class VM_Member extends VM_AnnotatedElement implements VM_Constants, VM_ClassLoaderConstants { + + /** + * The class that declared this member, avaliable by calling + * getDeclaringClass once the class is loaded. + */ + private final VM_TypeReference declaringClass; + + /** + * The canonical VM_MemberReference for this member + */ + protected final VM_MemberReference memRef; + + /** + * The modifiers associated with this member. + */ + public final short modifiers; + + /** + * The signature is a string representing the generic type for this + * field or method declaration, may be null + */ + private final VM_Atom signature; + + /** + * The member's jtoc/obj/tib offset in bytes. + * Set by {@link VM_Class#resolve()} + */ + protected int offset; + + /** + * NOTE: Only {@link VM_Class} is allowed to create an instance of a VM_Member. + * + * @param declaringClass the VM_TypeReference object of the class that declared this member + * @param memRef the canonical memberReference for this member. + * @param modifiers modifiers associated with this member. + * @param signature generic type of this member + * @param annotations array of runtime visible annotations + */ + protected VM_Member(VM_TypeReference declaringClass, VM_MemberReference memRef, + short modifiers, VM_Atom signature, + VM_Annotation[] annotations) { + super(annotations); + this.declaringClass = declaringClass; + this.memRef = memRef; + this.modifiers = modifiers; + this.signature = signature; + this.offset = Short.MIN_VALUE+1; // invalid value. Set to valid value during VM_Class.resolve() + } + + //--------------------------------------------------------------------// + // Section 1. // + // The following are available after class loading. // + //--------------------------------------------------------------------// + + /** + * Class that declared this field or method. Not available before + * the class is loaded. + */ + @Uninterruptible + public final VM_Class getDeclaringClass() { + return declaringClass.peekResolvedType().asClass(); + } + + /** + * Canonical member reference for this member. + */ + @Uninterruptible + public final VM_MemberReference getMemberRef() { + return memRef; + } + + /** + * Name of this member. + */ + @Uninterruptible + public final VM_Atom getName() { + return memRef.getName(); + } + + /** + * Descriptor for this member. + * something like "I" for a field or "(I)V" for a method. + */ + @Uninterruptible + public final VM_Atom getDescriptor() { + return memRef.getDescriptor(); + } + + /** + * Generic type for member + */ + public final VM_Atom getSignature() { + return signature; + } + + /** + * Get a unique id for this member. + * The id is the id of the canonical VM_MemberReference for this member + * and thus may be used to find the member by first finding the member reference. + */ + @Uninterruptible + public final int getId() { + return memRef.getId(); + } + + /* + * Define hashcode in terms of VM_Atom.hashCode to enable + * consistent hash codes during bootImage writing and run-time. + */ + public int hashCode() { + return memRef.hashCode(); + } + + public final String toString() { + return declaringClass + "." + getName() + " " + getDescriptor(); + } + + /** + * Usable from classes outside its package? + */ + public final boolean isPublic() { + return (modifiers & ACC_PUBLIC) != 0; + } + + /** + * Usable only from this class? + */ + public final boolean isPrivate() { + return (modifiers & ACC_PRIVATE) != 0; + } + + /** + * Usable from subclasses? + */ + public final boolean isProtected() { + return (modifiers & ACC_PROTECTED) != 0; + } + + /** + * Get the member's modifiers. + */ + public final int getModifiers() { + return modifiers; + } + + //------------------------------------------------------------------// + // Section 2. // + // The following are available after the declaring class has been // + // "resolved". // + //------------------------------------------------------------------// + + /** + * Offset of this field or method, in bytes. + * <ul> + * <li> For a static field: offset of field from start of jtoc + * <li> For a static method: offset of code object reference from start of jtoc + * <li> For a non-static field: offset of field from start of object + * <li> For a non-static method: offset of code object reference from start of tib + * </ul> + */ + @Uninterruptible + public final Offset getOffset() { + if (VM.VerifyAssertions) VM._assert(declaringClass.isResolved()); + return Offset.fromIntSignExtend(offset); + } + + /** + * Only meant to be used by VM_ObjectModel.layoutInstanceFields. + * TODO: refactor system so this functionality is in the classloader package + * and this method doesn't have to be final. + */ + public final void setOffset(Offset off) { + offset = off.toInt(); + } +} Added: ext/org/jikesrvm/classloader/VM_Method.java =================================================================== --- ext/org/jikesrvm/classloader/VM_Method.java (rev 0) +++ ext/org/jikesrvm/classloader/VM_Method.java 2007-03-20 15:49:03 UTC (rev 6) @@ -0,0 +1,642 @@ +/* + * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net). + * The Jikes RVM project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright IBM Corp 2001,2002 + */ +package org.jikesrvm.classloader; + +import org.jikesrvm.*; +import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; +import org.jikesrvm.ArchitectureSpecific.VM_LazyCompilationTrampolineGenerator; + +import java.io.DataInputStream; +import java.io.IOException; + +import org.vmmagic.unboxed.Offset; +import org.vmmagic.pragma.*; + +/** + * A method of a java class corresponding to a method_info structure + * in the class file. A method is read from a class file using the + * {@link #readMethod} method. + * + * @author Bowen Alpern + * @author Dave Grove + * @author Derek Lieber + * @author Ian Rogers + */ +public abstract class VM_Method extends VM_Member implements VM_BytecodeConstants { + + /** + * current compiled method for this method + */ + protected VM_CompiledMethod currentCompiledMethod; + /** + * exceptions this method might throw (null --> none) + */ + protected final VM_TypeReference[] exceptionTypes; + /** + * Method paramter annotations from the class file that are + * described as runtime visible. These annotations are available to + * the reflection API. + */ + protected final VM_Annotation[] parameterAnnotations; + /** + * A value present in the method info tables of annotation types. It + * represents the default result from an annotation method. + */ + protected final Object annotationDefault; + /** + * The offset of this virtual method in the jtoc if it's been placed + * there by constant propagation, otherwise 0. + */ + private Offset jtocOffset; + + /** + * Construct a read method + * + * @param declaringClass the VM_Class object of the class that declared this field + * @param memRef the canonical memberReference for this method. + * @param modifiers modifiers associated with this method. + * @param exceptionTypes exceptions thrown by this method. + * @param signature generic type of this method. + * @param annotations array of runtime visible annotations + * @param parameterAnnotations array of runtime visible parameter annotations + * @param annotationDefault value for this annotation that appears + */ + protected VM_Method(VM_TypeReference declaringClass, VM_MemberReference memRef, + short modifiers, VM_TypeReference[] exceptionTypes, VM_Atom signature, + VM_Annotation[] annotations, + VM_Annotation[] parameterAnnotations, + Object annotationDefault) + { + super(declaringClass, memRef, (short)(modifiers & APPLICABLE_TO_METHODS), signature, annotations); + this.parameterAnnotations = parameterAnnotations; + this.annotationDefault = annotationDefault; + memRef.asMethodReference().setResolvedMember(this); + this.exceptionTypes = exceptionTypes; + this.jtocOffset = Offset.fromIntSignExtend(-1); + } + + /** + * Called from {@link VM_Class#readClass(VM_TypeReference, DataInputStream)} to create an + * instance of a VM_Method by reading the relevant data from the argument bytecode stream. + * + * @param declaringClass the VM_TypeReference of the class being loaded + * @param constantPool the constantPool of the VM_Class object that's being constructed + * @param memRef the canonical memberReference for this member. + * @param modifiers modifiers associated with this member. + * @param input the DataInputStream to read the method's attributes from + */ + static VM_Method readMethod(VM_TypeReference declaringClass, int[] constantPool, VM_MemberReference memRef, + short modifiers, DataInputStream input) throws IOException { + short tmp_localWords = 0; + short tmp_operandWords = 0; + byte[] tmp_bytecodes = null; + VM_ExceptionHandlerMap tmp_exceptionHandlerMap = null; + VM_TypeReference[] tmp_exceptionTypes = null; + int[] tmp_lineNumberMap = null; + VM_Atom tmp_signature = null; + VM_Annotation[] annotations = null; + VM_Annotation[] parameterAnnotations = null; + Object tmp_annotationDefault = null; + + // Read the attributes + for (int i = 0, n = input.readUnsignedShort(); i<n; i++) { + VM_Atom attName = VM_Class.getUtf(constantPool, input.readUnsignedShort()); + int attLength = input.readInt(); + + // Only bother to interpret non-boring Method attributes + if (attName == VM_ClassLoader.codeAttributeName) { + tmp_operandWords = input.readShort(); + tmp_localWords = input.readShort(); + tmp_bytecodes = new byte[input.readInt()]; + input.readFully(tmp_bytecodes); + tmp_exceptionHandlerMap = VM_ExceptionHandlerMap.readExceptionHandlerMap(input, constantPool); + + // Read the attributes portion of the code attribute + for (int j = 0, n2 = input.readUnsignedShort(); j<n2; j++) { + attName = VM_Class.getUtf(constantPool, input.readUnsignedShort()); + attLength = input.readInt(); + + if (attName == VM_ClassLoader.lineNumberTableAttributeName) { + int cnt = input.readUnsignedShort(); + if (cnt != 0) { + tmp_lineNumberMap = new int[cnt]; + for (int k = 0; k<cnt; k++) { + int startPC = input.readUnsignedShort(); + int lineNumber = input.readUnsignedShort(); + tmp_lineNumberMap[k] = (lineNumber << BITS_IN_SHORT) | startPC; + } + } + } else { + // All other entries in the attribute portion of the code attribute are boring. + input.skipBytes(attLength); + } + } + } else if (attName == VM_ClassLoader.exceptionsAttributeName) { + int cnt = input.readUnsignedShort(); + if (cnt != 0) { + tmp_exceptionTypes = new VM_TypeReference[cnt]; + for (int j = 0, m = tmp_exceptionTypes.length; j < m; ++j) { + tmp_exceptionTypes[j] = VM_Class.getTypeRef(constantPool, input.readUnsignedShort()); + } + } + } else if (attName == VM_ClassLoader.syntheticAttributeName) { + modifiers |= ACC_SYNTHETIC; + } else if (attName == VM_ClassLoader.signatureAttributeName) { + tmp_signature = VM_Class.getUtf(constantPool, input.readUnsignedShort()); + } else if (attName == VM_ClassLoader.runtimeVisibleAnnotationsAttributeName) { + annotations = VM_AnnotatedElement.readAnnotations(constantPool, input, 2, + declaringClass.getClassLoader()); + } else if (attName == VM_ClassLoader.runtimeVisibleParameterAnnotationsAttributeName) { + parameterAnnotations = VM_AnnotatedElement.readAnnotations(constantPool, input, 1, + declaringClass.getClassLoader()); + } else if (attName == VM_ClassLoader.annotationDefaultAttributeName) { + try { + tmp_annotationDefault = VM_Annotation.readValue(constantPool, input, declaringClass.getClassLoader()); + } + catch (ClassNotFoundException e){ + throw new Error(e); + } + } else { + // all other method attributes are boring + input.skipBytes(attLength); + } + } + VM_Method method; + if ((modifiers & ACC_NATIVE) != 0) { + method = new VM_NativeMethod(declaringClass, memRef, modifiers, tmp_exceptionTypes, tmp_signature, + annotations, parameterAnnotations, tmp_annotationDefault); + } else if ((modifiers & ACC_ABSTRACT) != 0) { + method = new VM_AbstractMethod(declaringClass, memRef, modifiers, tmp_exceptionTypes, tmp_signature, + annotations, parameterAnnotations, tmp_annotationDefault); + + } else { + method = new VM_NormalMethod(declaringClass, memRef, modifiers, tmp_exceptionTypes, + tmp_localWords, tmp_operandWords, tmp_bytecodes, + tmp_exceptionHandlerMap, tmp_lineNumberMap, + constantPool, tmp_signature, + annotations, parameterAnnotations, tmp_annotationDefault); + } + return method; + } + + /** + * Create a copy of the method that occurs in the annotation + * interface. The method body will contain a read of the field at + * the constant pool index specified. + * + * @param annotationClass the class this method belongs to + * @param constantPool for the class + * @param memRef the member reference corresponding to this method + * @param interfaceMethod the interface method that will copied to + * produce the annotation method + * @param constantPoolIndex the index of the field that will be + * returned by this method + * @return the created method + */ + static VM_Method createAnnotationMethod(VM_TypeReference annotationClass, int[] constantPool, + VM_MemberReference memRef, VM_Method interfaceMethod, + int constantPoolIndex) { + byte[] bytecodes = new byte[] { + (byte)JBC_aload_0, + (byte)JBC_getfield, + (byte)(constantPoolIndex >>> 8), + (byte)constantPoolIndex, + // Xreturn + (byte)typeRefToReturnBytecode(interfaceMethod.getReturnType()) + }; + return new VM_NormalMethod(annotationClass, memRef, (short)(ACC_PUBLIC|ACC_FINAL|ACC_SYNTHETIC), null, + (short)1, (short)2, bytecodes, + null, null, + constantPool, + null, null, null, null); + } + /** + * Create a method to initialise the annotation class + * + * @param aClass the class this method belongs to + * @param constantPool for the class + * @param memRef the member reference corresponding to this method + * @param objectInitIndex an index into the constant pool for a + * method reference to java.lang.Object.<init> + * @param aFields + * @param aMethods + * @return the created method + */ + static VM_Method createAnnotationInit(VM_TypeReference aClass, int[] constantPool, + VM_MemberReference memRef, int objectInitIndex, + VM_Field[] aFields, VM_Method[] aMethods, + int[] defaultConstants) { + byte[] bytecode = new byte[6+(defaultConstants.length*7)]; + bytecode[0] = (byte)JBC_aload_0; // stack[0] = this + bytecode[1] = (byte)JBC_aload_1; // stack[1] = instanceof VM_Annotation + bytecode[2] = (byte)JBC_invokespecial; + bytecode[3] = (byte)(objectInitIndex >>> 8); + bytecode[4] = (byte)objectInitIndex; + for(int i=0, j=0; i < aMethods.length; i++) { + if(aMethods[i].annotationDefault != null) { + bytecode[(j*7)+5+0] = (byte)JBC_aload_0; // stack[0] = this + if(VM_Class.getLiteralSize(constantPool, defaultConstants[j]) == BYTES_IN_INT) { + bytecode[(j*7)+5+1] = (byte)JBC_ldc_w; // stack[1] = value + } + else { + bytecode[(j*7)+5+1] = (byte)JBC_ldc2_w;// stack[1&2] = value + } + bytecode[(j*7)+5+2] = (byte)(defaultConstants[j] >>> 8); + bytecode[(j*7)+5+3] = (byte)defaultConstants[j]; + bytecode[(j*7)+5+4] = (byte)JBC_putfield; + bytecode[(j*7)+5+5] = (byte)(i >>> 8); + bytecode[(j*7)+5+6] = (byte)i; + j++; + } + } + bytecode[bytecode.length-1] = (byte)JBC_return; + return new VM_NormalMethod(aClass, memRef, (short)(ACC_PUBLIC|ACC_FINAL|ACC_SYNTHETIC), null, + (short)2, (short)3, bytecode, + null, null, + constantPool, + null, null, null, null); + } + + /** + * What would be the appropriate return bytecode for the given type + * reference? + */ + private static int typeRefToReturnBytecode(VM_TypeReference tr) { + if(!tr.isPrimitiveType()) { + return JBC_areturn; + } else { + VM_Primitive pt = (VM_Primitive)tr.peekResolvedType(); + if((pt == VM_Type.BooleanType)||(pt == VM_Type.ByteType)||(pt == VM_Type.ShortType)|| + (pt == VM_Type.CharType)||(pt == VM_Type.IntType)) { + return JBC_ireturn; + } + else if(pt == VM_Type.LongType) { + return JBC_lreturn; + } + else if(pt == VM_Type.FloatType) { + return JBC_freturn; + } + else if(pt == VM_Type.DoubleType) { + return JBC_dreturn; + } + else { + VM._assert(false); + return -1; + } + } + } + /** + * Is this method a class initializer? + */ + @Uninterruptible + public final boolean isClassInitializer() { + return getName() == VM_ClassLoader.StandardClassInitializerMethodName; + } + + /** + * Is this method an object initializer? + */ + @Uninterruptible + public final boolean isObjectInitializer() { + return getName() == VM_ClassLoader.StandardObjectInitializerMethodName; + } + + /** + * Is this method a compiler-generated object initializer helper? + */ + @Uninterruptible + public final boolean isObjectInitializerHelper() { + return getName() == VM_ClassLoader.StandardObjectInitializerHelperMethodName; + } + + /** + * Type of this method's return value. + */ + @Uninterruptible + public final VM_TypeReference getReturnType() { + return memRef.asMethodReference().getReturnType(); + } + + /** + * Type of this method's parameters. + * Note: does *not* include implicit "this" parameter, if any. + */ + @Uninterruptible + public final VM_TypeReference[] getParameterTypes() { + return memRef.asMethodReference().getParameterTypes(); + } + + /** + * Space required by this method for its parameters, in words. + * Note: does *not* include implicit "this" parameter, if any. + */ + @Uninterruptible + public final int getParameterWords() { + return memRef.asMethodReference().getParameterWords(); + } + + /** + * Has machine code been generated for this method's bytecodes? + */ + public final boolean isCompiled() { + return currentCompiledMethod != null; + } + + /** + * Get the current compiled method for this method. + * Will return null if there is no current compiled method! + * + * We make this method Unpreemptible to avoid a race-condition + * in VM_Reflection.invoke. + * @return compiled method + */ + @Unpreemptible + public final synchronized VM_CompiledMethod getCurrentCompiledMethod() { + return currentCompiledMethod; + } + + /** + * Declared as statically dispatched? + */ + @Uninterruptible + public final boolean isStatic() { + return (modifiers & ACC_STATIC) != 0; + } + + /** + * Declared as non-overridable by subclasses? + */ + @Uninterruptible + public final boolean isFinal() { + return (modifiers & ACC_FINAL) != 0; + } + + /** + * Guarded by monitorenter/monitorexit? + */ + @Uninterruptible + public final boolean isSynchronized() { + return (modifiers & ACC_SYNCHRONIZED) != 0; + } + + /** + * Not implemented in java? + */ + @Uninterruptible + public final boolean isNative() { + return (modifiers & ACC_NATIVE) != 0; + } + + /** + * Not implemented in Java and use C not JNI calling convention + */ + public final boolean isSysCall() { + return isNative() && isStatic() && isAnnotationDeclared(VM_TypeReference.SysCall); + } + + /** + * Implemented in subclass? + */ + @Uninterruptible + public final boolean isAbstract() { + return (modifiers & ACC_ABSTRACT) != 0; + } + + /** + * Not present in source code file? + */ + public boolean isSynthetic() { + return (modifiers & ACC_SYNTHETIC) != 0; + } + + /** + * Exceptions thrown by this method - + * something like { "java/lang/IOException", "java/lang/EOFException" } + * @return info (null --> method doesn't throw any exceptions) + */ + @Uninterruptible + public final VM_TypeReference[] getExceptionTypes() { + return exceptionTypes; + } + + /** + * Is this method interruptible? + * In other words, should the compiler insert yieldpoints + * in method prologue, epilogue, and backwards branches. + * Also, only methods that are Interruptible have stackoverflow checks + * in the method prologue (since there is no mechanism for handling a stackoverflow + * that doesn't violate the uninterruptiblity of the method). + * To determine if a method is interruptible, the following conditions + * are checked (<em>in order</em>): + * <ul> + * <li> If it is a <clinit> or <init> method then it is interruptible. + * <li> If is the synthetic 'this' method used by jikes to + * factor out default initializers for <init> methods then it is interruptible. + * <li> If it is annotated with <CODE>Interruptible</CODE> it is interruptible. + * <li> If it is annotated with <CODE>Preemptible</CODE> it is interruptible. + * <li> If it is annotated with <CODE>Uninterruptible</CODE> it is not interruptible. + * <li> If it is annotated with <CODE>UninterruptibleNoWarn</CODE> it is not interruptible. + * <li> If it is annotated with <CODE>Unpreemptible</CODE> it is not interruptible. + * <li> If its declaring class is annotated with <CODE>Uninterruptible</CODE> + * or <CODE>Unpreemptible</CODE> it is not interruptible. + * </ul> + */ + public final boolean isInterruptible() { + if (isClassInitializer() || isObjectInitializer()) return true; + if (isObjectInitializerHelper()) return true; + if (hasInterruptibleAnnotation()) return true; + if (hasPreemptibleAnnotation()) return true; + if (hasUninterruptibleNoWarnAnnotation()) return false; + if (hasUninterruptibleAnnotation()) return false; + if (hasUnpreemptibleAnnotation()) return false; + if (getDeclaringClass().hasUnpreemptibleAnnotation()) return false; + return !getDeclaringClass().hasUninterruptibleAnnotation(); + } + + /** + * Is the method Unpreemptible? See the comment in {@link #isInterruptible} + */ + public final boolean isUnpreemptible() { + if (isClassInitializer() || isObjectInitializer()) return false; + if (isObjectInitializerHelper()) return false; + if (hasInterruptibleAnnotation()) return false; + if (hasPreemptibleAnnotation()) return false; + if (hasUninterruptibleAnnotation()) return false; + if (hasUninterruptibleNoWarnAnnotation()) return false; + if (hasUnpreemptibleAnnotation()) return true; + return getDeclaringClass().hasUnpreemptibleAnnotation(); + } + + /** + * Is the method Uninterruptible? See the comment in {@link #isInterruptible} + */ + public final boolean isUninterruptible() { + if (isClassInitializer() || isObjectInitializer()) return false; + if (isObjectInitializerHelper()) return false; + if (hasInterruptibleAnnotation()) return false; + if (hasPreemptibleAnnotation()) return false; + if (hasUnpreemptibleAnnotation()) return false; + if (hasUninterruptibleAnnotation()) return true; + if (hasUninterruptibleNoWarnAnnotation()) return true; + return getDeclaringClass().hasUninterruptibleAnnotation(); + } + + /** + * Has this method been marked as forbidden to inline? + * ie., it is marked with the <CODE>NoInline</CODE> annotation or + * the <CODE>NoOptCompile</CODE> annotation? + */ + public final boolean hasNoInlinePragma() { + return (hasNoInlineAnnotation() || hasNoOptCompileAnnotation()); + } + + /** + * @return true if the method may write to a given field + */ + public boolean mayWrite(VM_Field field) { + return true; // be conservative. native methods can write to anything + } + + /** + * @return true if the method is the implementation of a runtime service + * that is called "under the covers" from the generated code and thus is not subject to + * inlining via the normal mechanisms. + */ + public boolean isRuntimeServiceMethod() { + return false; // only VM_NormalMethods can be runtime service impls in Jikes RVM and they override this method + } + + //------------------------------------------------------------------// + // Section 2. // + // The following are available after the declaring class has been // + // "resolved". // + //------------------------------------------------------------------// + + /** + * Get the code array that corresponds to the entry point (prologue) for the method. + */ + public final synchronized VM_CodeArray getCurrentEntryCodeArray() { + VM_Class declaringClass = getDeclaringClass(); + if (VM.VerifyAssertions) VM._assert(declaringClass.isResolved()); + if (isCompiled()) { + return currentCompiledMethod.getEntryCodeArray(); + } else if (!VM.writingBootImage || isNative()) { + if (!isStatic() && !isObjectInitializer() && !isPrivate()) { + // A non-private virtual method. + if (declaringClass.isJavaLangObjectType() || + declaringClass.getSuperClass().findVirtualMethod(getName(), getDescriptor()) == null) { + // The root method of a virtual method family can use the lazy method invoker directly. + return VM_Entrypoints.lazyMethodInvokerMethod.getCurrentEntryCodeArray(); + } else { + // All other virtual methods in the family must generate unique stubs to + // ensure correct operation of the method test (guarded inlining of virtual calls). + return VM_LazyCompilationTrampolineGenerator.getTrampoline(); + } + } else { + // We'll never do a method test against this method. + // Therefore we can use the lazy method invoker directly. + return VM_Entrypoints.lazyMethodInvokerMethod.getCurrentEntryCodeArray(); + } + } else { + compile(); + return currentCompiledMethod.getEntryCodeArray(); + } + } + + /** + * Generate machine code for this method if valid + * machine code doesn't already exist. + * Return the resulting VM_CompiledMethod object. + */ + public final synchronized void compile() { + if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isResolved()); + if (isCompiled()) return; + + if (VM.TraceClassLoading && VM.runningVM) VM.sysWrite("VM_Method: (begin) compiling " + this + "\n"); + + VM_CompiledMethod cm = genCode(); + + // Ensure that cm wasn't invalidated while it was being compiled. + synchronized(cm) { + if (cm.isInvalid()) { + VM_CompiledMethods.setCompiledMethodObsolete(cm); + } else { + currentCompiledMethod = cm; + } + } + + if (VM.TraceClassLoading && VM.runningVM) VM.sysWrite("VM_Method: (end) compiling " + this + "\n"); + } + + protected abstract VM_CompiledMethod genCode(); + + //----------------------------------------------------------------// + // Section 3. // + // The following are available after the declaring class has been // + // "instantiated". // + //----------------------------------------------------------------// + + /** + * Change machine code that will be used by future executions of this method + * (ie. optimized <-> non-optimized) + * @param compiledMethod new machine code + * Side effect: updates jtoc or method dispatch tables + * ("type information blocks") + * for this class and its subclasses + */ + public synchronized void replaceCompiledMethod(VM_CompiledMethod compiledMethod) { + if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isInstantiated()); + // If we're replacing with a non-null compiledMethod, ensure that is still valid! + if (compiledMethod != null) { + synchronized(compiledMethod) { + if (compiledMethod.isInvalid()) return; + } + } + + // Grab version that is being replaced + VM_CompiledMethod oldCompiledMethod = currentCompiledMethod; + currentCompiledMethod = compiledMethod; + + // Install the new method in jtoc/tib. If virtual, will also replace in + // all subclasses that inherited the method. + getDeclaringClass().updateMethod(this); + + // Replace constant-ified virtual method in JTOC if necessary + if(jtocOffset.toInt() != -1) { + VM_Statics.setSlotContents(jtocOffset, getCurrentEntryCodeArray()); + } + + // Now that we've updated the jtoc/tib, old version is obsolete + if (oldCompiledMethod != null) { + VM_CompiledMethods.setCompiledMethodObsolete(oldCompiledMethod); + } + } + + /** + * If CM is the current compiled code for this, then invaldiate it. + */ + public final synchronized void invalidateCompiledMethod(VM_CompiledMethod cm) { + if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isInstantiated()); + if (currentCompiledMethod == cm) { + replaceCompiledMethod(null); + } + } + + /** + * Find or create a jtoc offset for this method + */ + public final synchronized Offset findOrCreateJtocOffset() { + if (VM.VerifyAssertions) VM._assert(!isStatic() && !isObjectInitializer()); + if(jtocOffset.EQ(Offset.zero())) { + jtocOffset = VM_Statics.allocateReferenceSlot(); + VM_Statics.setSlotContents(jtocOffset, getCurrentEntryCodeArray()); + } + return jtocOffset; + } +} Added: ext/org/jikesrvm/classloader/VM_NormalMethod.java =================================================================== --- ext/org/jikesrvm/classloader/VM_NormalMethod.java (rev 0) +++ ext/org/jikesrvm/classloader/VM_NormalMethod.java 2007-03-20 15:49:03 UTC (rev 6) @@ -0,0 +1,675 @@ +/* + * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net). + * The Jikes RVM project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright IBM Corp 2001,2002, 2004 + */ +package org.jikesrvm.classloader; + +import org.jikesrvm.*; +import org.vmmagic.pragma.*; +import org.jikesrvm.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.opt.ir.OPT_BC2IR; +import org.jikesrvm.opt.ir.OPT_GenerationContext; + +/** + * A method of a java class that has bytecodes. + * + * @author Bowen Alpern + * @author Stephen Fink + * @author Dave Grove + * @author Derek Lieber + * @modified Ian Rogers + */ +public class VM_NormalMethod + extends VM_Method + implements VM_BytecodeConstants +{ + + /* As we read the bytecodes for the method, we compute + * a simple summary of some interesting properties of the method. + * Because we do this for every method, we require the summarization to + * be fast and the computed summary to be very space efficient. + * + * The following constants encode the estimated relative cost in + * machine instructions when a particular class of bytecode is compiled + * by the optimizing compiler. The estimates approximate the typical + * optimization the compiler is able to perform. + * This information is used to estimate how big a method will be when + * it is inlined. + */ + public static final int SIMPLE_OPERATION_COST = 1; + public static final int LONG_OPERATION_COST = 2; + public static final int ARRAY_LOAD_COST = 2; + public static final int ARRAY_STORE_COST = 2; + public static final int JSR_COST = 5; + public static final int CALL_COST = 6; + // Bias to inlining methods with magic + // most magics are quite cheap (0-1 instructions) + public static final int MAGIC_COST = 0; + // News are actually more expensive than calls + // but bias to inline methods that allocate + // objects becuase we expect better downstream optimization of + // the caller due to class analysis + // and propagation of nonNullness + public static final int ALLOCATION_COST = 4; + // Approximations, assuming some CSE/PRE of object model computations + public static final int CLASS_CHECK_COST = 2*SIMPLE_OPERATION_COST; + public static final int STORE_CHECK_COST = 4*SIMPLE_OPERATION_COST; + // Just a call. + public static final int THROW_COST = CALL_COST; + // Really a bunch of operations plus a call, but undercharge because + // we don't have worry about this causing an exponential growth of call chain + // and we probably want to inline synchronization + // (to get a chance to optimize it). + public static final int SYNCH_COST = 4*SIMPLE_OPERATION_COST; + // The additional cost of a switch isn't that large, since if the + // switch has more than a few cases the method will be too big to inline + // anyways. + public static final int SWITCH_COST = CALL_COST; + + // Definition of flag bits + protected static final char HAS_MAGIC = 0x8000; + protected static final char HAS_SYNCH = 0x4000; + protected static final char HAS_ALLOCATION = 0x2000; + protected static final char HAS_THROW = 0x1000; + protected static final char HAS_INVOKE = 0x0800; + protected static final char HAS_FIELD_READ = 0x0400; + protected static final char HAS_FIELD_WRITE= 0x0200; + protected static final char HAS_ARRAY_READ = 0x0100; + protected static final char HAS_ARRAY_WRITE= 0x0080; + protected static final char HAS_JSR = 0x0040; + protected static final char HAS_COND_BRANCH= 0x0020; + protected static final char HAS_SWITCH = 0x0010; + protected static final char HAS_BACK_BRANCH= 0x0008; + protected static final char IS_RS_METHOD = 0x0004; + + /** + * storage for bytecode summary flags + */ + protected char summaryFlags; + /** + * storage for bytecode summary size + */ + protected char summarySize; + + /** + * words needed for local variables (including parameters) + */ + private final short localWords; + + /** + * words needed for operand stack (high water mark) + * TODO: OSR redesign; add subclass of NormalMethod for OSR method + * and then make this field final in NormalMethod. + */ + private short operandWords; + + /** + * bytecodes for this method (null --> none) + */ + public final byte[] bytecodes; + + /** + * try/catch/finally blocks for this method (null --> none) + */ + private final VM_ExceptionHandlerMap exceptionHandlerMap; + + /** + * pc to source-line info (null --> none) + * Each entry contains both the line number (upper 16 bits) + * and corresponding start PC (lower 16 bits). + */ + private final int[] lineNumberMap; + + // Extra fields for on-stack replacement + // TODO: rework the system so we don't waste space for this on the VM_Method object + /* bytecode array constists of prologue and original bytecodes */ + private byte[] synthesizedBytecodes = null; + /* record osr prologue */ + private byte[] osrPrologue = null; + /* prologue may change the maximum stack height, remember the + * original stack height */ + private short savedOperandWords; + + /** + * Construct a normal Java bytecode method's information + * + * @param dc the VM_TypeReference object of the class that declared this field + * @param mr the canonical memberReference for this member. + * @param mo modifiers associated with this member. + * @param et exceptions thrown by this method. + * @param lw the number of local words used by the bytecode of this method + * @param ow the number of operand words used by the bytecode of this method + * @param bc the bytecodes of this method + * @param eMap the exception handler map for this method + * @param lm the line number map for this method + * @param constantPool the constantPool for this method + * @param sig generic type of this method. + * @param annotations array of runtime visible annotations + * @param parameterAnnotations array of runtime visible paramter annotations + * @param ad annotation default value for that appears in annotation classes + */ + public VM_NormalMethod(VM_TypeReference dc, VM_MemberReference mr, + short mo, VM_TypeReference[] et, short lw, short ow, byte[] bc, + VM_ExceptionHandlerMap eMap, int[] lm, + int[] constantPool, VM_Atom sig, + VM_Annotation[] annotations, + VM_Annotation[] parameterAnnotations, + Object ad) + { + super(dc, mr, mo, et, sig, annotations, parameterAnnotations, ad); + localWords = lw; + operandWords = ow; + bytecodes = bc; + exceptionHandlerMap = eMap; + lineNumberMap = lm; + computeSummary(constantPool); + } + + /** + * Generate the code for this method + */ + protected VM_CompiledMethod genCode() throws VerifyError { + // The byte code verifier is dead; needs replacement. +// if (VM.VerifyBytecode) { +// VM_Verifier verifier = new VM_Verifier(); +// verifier.verifyMethod(this); +// } + + if (VM.writingBootImage) { + return VM_BootImageCompiler.compile(this); + } else { + return VM_RuntimeCompiler.compile(this); + } + } + + /** + * Space required by this method for its local variables, in words. + * Note: local variables include parameters + */ + @Uninterruptible + public int getLocalWords() { + return localWords; + } + + /** + * Space required by this method for its operand stack, in words. + */ + @Uninterruptible + public int getOperandWords() { + return operandWords; + } + + /** + * Get a representation of the bytecodes in the code attribute of this method. + * @return object representing the bytecodes + */ + public VM_BytecodeStream getBytecodes() { + return new VM_BytecodeStream(this, bytecodes); + } + + /** + * Fill in DynamicLink object for the invoke at the given bytecode index + * @param dynamicLink the dynamicLink object to initialize + * @param bcIndex the bcIndex of the invoke instruction + */ + @Uninterruptible + public void getDynamicLink(VM_DynamicLink dynamicLink, int bcIndex) { + if (VM.VerifyAssertions) VM._assert(bytecodes != null); + if (VM.VerifyAssertions) VM._assert(bcIndex + 2 < bytecodes.length); + int bytecode = bytecodes[bcIndex] & 0xFF; + if (VM.VerifyAssertions) VM._assert((VM_BytecodeConstants.JBC_invokevirtual <= bytecode) + && (bytecode <= VM_BytecodeConstants.JBC_invokeinterface)); + int constantPoolIndex = ((bytecodes[bcIndex + 1] & 0xFF) << BITS_IN_BYTE) | (bytecodes[bcIndex + 2] & 0xFF); + dynamicLink.set(getDeclaringClass().getMethodRef(constantPoolIndex), bytecode); + } + + /** + * Size of bytecodes for this method + */ + public int getBytecodeLength() { + return bytecodes.length; + } + + /** + * Exceptions caught by this method. + * @return info (null --> method doesn't catch any exceptions) + */ + @Uninterruptible + public VM_ExceptionHandlerMap getExceptionHandlerMap() { + return exceptionHandlerMap; + } + + /** + * Return the line number information for the argument bytecode index. + * @return The line number, a positive integer. Zero means unable to find. + */ + @Uninterruptible + public int getLineNumberForBCIndex(int bci) { + if (lineNumberMap == null) return 0; + int idx; + for (idx = 0; idx<lineNumberMap.length; idx++) { + int pc = lineNumberMap[idx] & 0xffff; // lower 16 bits are bcIndex + if (bci < pc) { + if (idx == 0) idx++; // add 1, so we can subtract 1 below. + break; + } + } + return lineNumberMap[--idx] >>> 16; // upper 16 bits are line number + } + + // Extra methods for on-stack replacement + // VM_BaselineCompiler and OPT_BC2IR should check if a method is + // for specialization by calling isForOsrSpecialization, the compiler + // uses synthesized bytecodes (prologue + original bytecodes) for + // OSRing method. Other interfaces of method are not changed, therefore, + // dynamic linking and gc referring to bytecodes are safe. + + /** + * Checks if the method is in state for OSR specialization now + * @return true, if it is (with prologue) + */ + public boolean isForOsrSpecialization() { + return this.synthesizedBytecodes != null; + } + + /** + * Sets method in state for OSR specialization, i.e, the subsequent calls + * of {@link #getBytecodes} return the stream of specialized bytecodes. + * + * NB: between flag and action, it should not allow GC or threadSwitch happen. + * @param prologue The bytecode of prologue + * @param newStackHeight The prologue may change the default height of + * stack + */ + public void setForOsrSpecialization(byte[] prologue, short newStackHeight) { + if (VM.VerifyAssertions) VM._assert(this.synthesizedBytecodes == null); + + 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); + + this.osrPrologue = prologue; + this.synthesizedBytecodes = newBytecodes; + this.savedOperandWords = operandWords; + if (newStackHeight > operandWords) + this.operandWords = newStackHeight; + } + + /** + * Restores the original state of the method. + */ + public void finalizeOsrSpecialization() { + if (VM.VerifyAssertions) VM._assert(this.synthesizedBytecodes != null); + this.synthesizedBytecodes = null; + this.osrPrologue = null; + this.operandWords = savedOperandWords; + } + + /** + * Returns the OSR prologue length for adjusting various tables and maps. + * @return the length of prologue if the method is in state for OSR, + * 0 otherwise. + */ + public int getOsrPrologueLength() { + return isForOsrSpecialization()?this.osrPrologue.length:0; + } + + /** + * Returns a bytecode stream of osr prologue + * @return osr prologue bytecode stream + */ + public VM_BytecodeStream getOsrPrologue() { + if (VM.VerifyAssertions) VM._assert(synthesizedBytecodes != null); + return new VM_BytecodeStream(this, osrPrologue); + } + + /** + * Returns the synthesized bytecode stream with osr prologue + * @return bytecode stream + */ + public VM_BytecodeStream getOsrSynthesizedBytecodes() { + if (VM.VerifyAssertions) VM._assert(synthesizedBytecodes != null); + return new VM_BytecodeStream(this, synthesizedBytecodes); + } + + + /* + * Methods to access and compute method summary information + */ + + /** + * @return An estimate of the expected size of the machine code instructions + * that will be generated by the opt compiler if the method is inlined. + */ + public int inlinedSizeEstimate() { + return summarySize & 0xFFFF; + } + + /** + * @return true if the method contains a VM_Magic.xxx or Address.yyy + */ + public boolean hasMagic() { + return (summaryFlags & HAS_MAGIC) != 0; + } + + /** + * @return true if the method contains a monitorenter/exit or is synchronized + */ + public boolean hasSynch() { + return (summaryFlags & HAS_SYNCH) != 0; + } + + /** + * @return true if the method contains an allocation + */ + public boolean hasAllocation() { + return (summaryFlags & HAS_ALLOCATION) != 0; + } + + /** + * @return true if the method contains an athrow + */ + public boolean hasThrow() { + return (summaryFlags & HAS_THROW) != 0; + } + + /** + * @return true if the method contains an invoke + */ + public boolean hasInvoke() { + return (summaryFlags & HAS_INVOKE) != 0; + } + + /** + * @return true if the method contains a getfield or getstatic + */ + public boolean hasFieldRead() { + return (summaryFlags & HAS_FIELD_READ) != 0; + } + + /** + * @return true if the method contains a putfield or putstatic + */ + public boolean hasFieldWrite() { + return (summaryFlags & HAS_FIELD_WRITE) != 0; + } + + /** + * @return true if the method contains an array load + */ + public boolean hasArrayRead() { + return (summaryFlags & HAS_ARRAY_READ) != 0; + } + + /** + * @return true if the method contains an array store + */ + public boolean hasArrayWrite() { + return (summaryFlags & HAS_ARRAY_WRITE) != 0; + } + + /** + * @return true if the method contains a jsr + */ + public boolean hasJSR() { + return (summaryFlags & HAS_JSR) != 0; + } + + /** + * @return true if the method contains a conditional branch + */ + public boolean hasCondBranch() { + return (summaryFlags & HAS_COND_BRANCH) != 0; + } + + /** + * @return true if the method contains a switch + */ + public boolean hasSwitch() { + return (summaryFlags & HAS_SWITCH) != 0; + } + + /** + * @return true if the method contains a backwards branch + */ + public boolean hasBackwardsBranch() { + return (summaryFlags & HAS_BACK_BRANCH) != 0; + } + + /** + * @return true if the method is the implementation of a runtime service + * that is called "under the covers" from the generated code and thus is not subject to + * inlining via the normal mechanisms. + */ + public boolean isRuntimeServiceMethod() { + return (summaryFlags & IS_RS_METHOD) != 0; + } + + /** + * Set the value of the 'runtime service method' flag to the argument + * value. A method is considered to be a runtime service method if it + * is only/primarialy invoked "under the covers" from the generated code + * and thus is not subject to inlining via the normal mechanisms. + * For example, the implementations of bytecodes such as new or checkcast + * or the implementation of yieldpoints. + * @param value true if this is a runtime service method, false it is not. + */ + public void setRuntimeServiceMethod(boolean value) { + if (value) { + summaryFlags |= IS_RS_METHOD; + } else { + summaryFlags &= ~IS_RS_METHOD; + } + } + + /** + * @return true if the method may write to a given field + */ + public boolean mayWrite(VM_Field field) { + if (!hasFieldWrite()) return false; + VM_FieldReference it = field.getMemberRef().asFieldReference(); + VM_BytecodeStream bcodes = getBytecodes(); + while (bcodes.hasMoreBytecodes()) { + int opcode = bcodes.nextInstruction(); + if (opcode == JBC_putstatic || opcode == JBC_putfield) { + VM_FieldReference fr = bcodes.getFieldReference(); + if (!fr.definitelyDifferent(it)) return true; + } else { + bcodes.skipInstruction(); + } + } + return false; + } + + /** + * This method computes a summary of interesting method characteristics + * and stores an encoding of the summary as an int. + */ + protected void computeSummary(int[] constantPool) { + int calleeSize = 0; + if (isSynchronized()) { + summaryFlags |= HAS_SYNCH; + calleeSize += 2*SYNCH_COST; // NOTE: ignoring catch/unlock/rethrow block. Probably the right thing to do. + } + + VM_BytecodeStream bcodes = getBytecodes(); + while (bcodes.hasMoreBytecodes()) { + switch (bcodes.nextInstruction()) { + // Array loads: null check, bounds check, index computation, load + case JBC_iaload:case JBC_laload:case JBC_faload:case JBC_daload: + case JBC_aaload:case JBC_baload:case JBC_caload:case JBC_saload: + summaryFlags |= HAS_ARRAY_READ; + calleeSize += ARRAY_LOAD_COST; + break; + + // Array stores: null check, bounds check, index computation, load + case JBC_iastore:case JBC_lastore:case JBC_fastore: + case JBC_dastore:case JBC_bastore:case JBC_castore:case JBC_sastore: + summaryFlags |= HAS_ARRAY_WRITE; + calleeSize += ARRAY_STORE_COST; + break; + case JBC_aastore: + summaryFlags |= HAS_ARRAY_WRITE; + calleeSize += ARRAY_STORE_COST + STORE_CHECK_COST; + break; + + // primitive computations (likely to be very cheap) + case JBC_iadd:case JBC_fadd:case JBC_dadd:case JBC_isub: + case JBC_fsub:case JBC_dsub:case JBC_imul:case JBC_fmul: + case JBC_dmul:case JBC_idiv:case JBC_fdiv:case JBC_ddiv: + case JBC_irem:case JBC_frem:case JBC_drem:case JBC_ineg: + case JBC_fneg:case JBC_dneg:case JBC_ishl:case JBC_ishr: + case JBC_lshr:case JBC_iushr:case JBC_iand:case JBC_ior: + case JBC_ixor:case JBC_iinc: + calleeSize += SIMPLE_OPERATION_COST; + break; + + // long computations may be different cost than primitive computations + case JBC_ladd:case JBC_lsub:case JBC_lmul:case JBC_ldiv: + case JBC_lrem:case JBC_lneg:case JBC_lshl:case JBC_lushr: + case JBC_land:case JBC_lor:case JBC_lxor: + calleeSize += LONG_OPERATION_COST; + break; + + // Some conversion operations are very cheap + case JBC_int2byte:case JBC_int2char:case JBC_int2short: + calleeSize += SIMPLE_OPERATION_COST; + break; + // Others are a little more costly + case JBC_i2l:case JBC_l2i: + calleeSize += LONG_OPERATION_COST; + break; + // Most are roughly as expensive as a call + case JBC_i2f:case JBC_i2d:case JBC_l2f:case JBC_l2d: + case JBC_f2i:case JBC_f2l:case JBC_f2d:case JBC_d2i: + case JBC_d2l:case JBC_d2f: + calleeSize += CALL_COST; + break; + + // approximate compares as 1 simple operation + case JBC_lcmp:case JBC_fcmpl:case JBC_fcmpg:case JBC_dcmpl: + case JBC_dcmpg: + calleeSize += SIMPLE_OPERATION_COST; + break; + + // most control flow is cheap; jsr is more expensive + case JBC_ifeq:case JBC_ifne:case JBC_iflt:case JBC_ifge: + case JBC_ifgt:case JBC_ifle:case JBC_if_icmpeq:case JBC_if_icmpne: + case JBC_if_icmplt:case JBC_if_icmpge:case JBC_if_icmpgt: + case JBC_if_icmple:case JBC_if_acmpeq:case JBC_if_acmpne: + case JBC_ifnull:case JBC_ifnonnull: + summaryFlags |= HAS_COND_BRANCH; + if (bcodes.getBranchOffset() < 0) summaryFlags |= HAS_BACK_BRANCH; + calleeSize += SIMPLE_OPERATION_COST; + continue; // we've processed all of the bytes, so avoid the call to skipInstruction() + case JBC_goto: + if (bcodes.getBranchOffset() < 0) summaryFlags |= HAS_BACK_BRANCH; + calleeSize += SIMPLE_OPERATION_COST; + continue; // we've processed all of the bytes, so avoid the call to skipInstruction() + case JBC_goto_w: + if (bcodes.getWideBranchOffset() < 0) summaryFlags |= HAS_BACK_BRANCH; + calleeSize += SIMPLE_OPERATION_COST; + continue; // we've processed all of the bytes, so avoid the call to skipInstruction() + case JBC_jsr:case JBC_jsr_w: + summaryFlags |= HAS_JSR; + calleeSize += JSR_COST; + break; + + case JBC_tableswitch:case JBC_lookupswitch: + summaryFlags |= HAS_SWITCH; + calleeSize += SWITCH_COST; + break; + + case JBC_putstatic: case JBC_putfield: + summaryFlags |= HAS_FIELD_WRITE; + calleeSize += SIMPLE_OPERATION_COST; + break; + + case JBC_getstatic: case JBC_getfield: + summaryFlags |= HAS_FIELD_READ; + calleeSize += SIMPLE_OPERATION_COST; + break; + + // Various flavors of calls. Assign them call cost (differentiate?) + case JBC_invokevirtual:case JBC_invokespecial: + case JBC_invokestatic: + // Special case VM_Magic's as being cheaper. + VM_MethodReference meth = bcodes.getMethodReference(constantPool); + if (meth.getType().isMagicType()) { + summaryFlags |= HAS_MAGIC; + calleeSize += MAGIC_COST; + } else { + summaryFlags |= HAS_INVOKE; + calleeSize += CALL_COST; + } + continue; // we've processed all of the bytes, so avoid the call to skipInstruction() + + case JBC_invokeinterface: + summaryFlags |= HAS_INVOKE; + calleeSize += CALL_COST; + break; + + case JBC_xxxunusedxxx: + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); + break; + + case JBC_new: case JBC_newarray: case JBC_anewarray: + summaryFlags |= HAS_ALLOCATION; + calleeSize += ALLOCATION_COST; + break; + + case JBC_arraylength: + calleeSize += SIMPLE_OPERATION_COST; + break; + + case JBC_athrow: + summaryFlags |= HAS_THROW; + calleeSize += THROW_COST; + break; + + case JBC_checkcast:case JBC_instanceof: + calleeSize += CLASS_CHECK_COST; + break; + + case JBC_monitorenter:case JBC_monitorexit: + summaryFlags |= HAS_SYNCH; + calleeSize += SYNCH_COST; + break; + + case JBC_multianewarray: + summaryFlags |= HAS_ALLOCATION; + calleeSize += CALL_COST; + break; + } + bcodes.skipInstruction(); + } + if (calleeSize > Character.MAX_VALUE) { + summarySize = Character.MAX_VALUE; + } else { + summarySize = (char)calleeSize; + } + } + + /** + * Create an optimizing compiler HIR code generator for this type of + * method + * @param context the generation context for the HIR generation + * @return a HIR generator + */ + public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context){ + return new OPT_BC2IR(context); + } + + /** + * Must this method be OPT compiled? + * @param context the generation context for the HIR generation + * @return a HIR generator + */ + public boolean optCompileOnly() { + return false; + } +} Added: ext/org/jikesrvm/opt/OPT_Simplifier.java =================================================================== --- ext/org/jikesrvm/opt/OPT_Simplifier.java (rev 0) +++ ext/org/jikesrvm/opt/OPT_Simplifier.java 2007-03-20 15:49:03 UTC (rev 6) @@ -0,0 +1,3160 @@ +/* + *... [truncated message content] |