FileDocCategorySizeDatePackage
EVMMethodInfo.javaAPI DocJ2ME CLDC 1.145609Wed Feb 05 15:56:04 GMT 2003vm

EVMMethodInfo

public class EVMMethodInfo extends vm.VMMethodInfo implements vm.EVMConst, vm.Const

Fields Summary
private boolean
impureCode
private boolean
mustAlign
private boolean
codeExamined
public MethodInfo
method
private String
myNativeName
private int
inlining
static final int
NO_INLINE_FLAG
static final int
SAME_CLASS_FLAG
static final int
REDO_INLINING_FLAG
static final boolean
UseLosslessQuickOpcodes
Keep this var to make code look the same as in inline.c
public static final boolean
SAVE_TARGET_METHODS
Flag used in quickenCode() to save old methodblock info so we can use it here for inlining. This affects invokevirtual_quick which typically overwrites the methodblock info with and .
private static int
methodNumber
static final int
inline_NOT_DONE
Attempt to inline the code of this method
static final int
inline_IN_PROGRESS
static final int
inline_DONE
private int
inlineState
static int[]
poppers
static OpcodeInfoType[]
OpcodeInfo
private String
myName
static int
total
Constructors Summary
public EVMMethodInfo(MethodInfo m)


         
    method = m;
    method.vmMethodInfo = this;
    
Methods Summary
public intEVMflags()

    int flagval = 0;
    int a = method.access;
    if ( (a&ACC_PUBLIC) != 0 ) flagval |= EVM_METHOD_ACC_PUBLIC;
    if ( (a&ACC_PRIVATE) != 0 ) flagval |= EVM_METHOD_ACC_PRIVATE;
    if ( (a&ACC_PROTECTED) != 0 ) flagval |= EVM_METHOD_ACC_PROTECTED;
    if ( (a&ACC_STATIC) != 0 ) flagval |= EVM_METHOD_ACC_STATIC;
    if ( (a&ACC_FINAL) != 0 ) flagval |= EVM_METHOD_ACC_FINAL;
    if ( (a&ACC_SYNCHRONIZED) != 0 ) flagval |= EVM_METHOD_ACC_SYNCHRONIZED;
    if ( (a&ACC_NATIVE) != 0 ) flagval |= EVM_METHOD_ACC_NATIVE;
    if ( (a&ACC_ABSTRACT) != 0 ) flagval |= EVM_METHOD_ACC_ABSTRACT;
    return flagval;

    
private static byteINLINING_WORD1(int simp)

    return (byte) (simp & 0xFF);
    
private static byteINLINING_WORD2(int simp)

    return (byte) ((simp >> 8) & 0xFF);
    
private static byteINLINING_WORD3(int simp)

    return (byte) ((simp >> 16) & 0xFF);
    
private static intMAKE_INLINING(int op1, int op2, int op3)

    return (op1 << 0) + (op2 << 8) + (op3 << 16);
    
private byte[]MethodCallInline(int pc, vm.EVMMethodInfo mb)

    byte code[] = method.code;
    int opcode = code[pc] & 0xff;

    if (opcode == opc_invokevirtual_fast) {   
        /* This is a virtual method call.  No use even bother trying to
         * inline the method, unless its final
         */
        if (((mb.method.access & ACC_FINAL) == 0) 
           && ((mb.method.parent.access & ACC_FINAL) == 0))
        return null;
        }
            
    int mbInlining = mb.getInlining();
    if ((mbInlining & NO_INLINE_FLAG) != 0)
        return null;
    /* Does this inlining have a dependency on the constant pool, and so
     * can only be used on a method in the same class. */
    if ((mbInlining & SAME_CLASS_FLAG) != 0) {
        if (this.method.parent != mb.method.parent)
        return null;
    }
    /* There is a inlining.  Copy that value into "result" */
    byte[] result = new byte[3];
    result[0] = INLINING_WORD1(mbInlining);
    result[1] = INLINING_WORD2(mbInlining);
    result[2] = INLINING_WORD3(mbInlining);
    return result;
    
private static intREGNUM(vm.OpcodeInfoType ptr)

    return (ptr.outStack);
    
private static intREGSIZE(vm.OpcodeInfoType ptr)

    return (ptr.inStack);
    
public intalignment()

    if ( ! codeExamined ){
        examineCode(); // may throw exception without setting codeExamined
    }
    return mustAlign ? 4 : 1;
    
private intcalculateInlining()

 
        MethodInfo mb = this.method;
    byte[] code = mb.code;

    /* The checkThis flag indicates that the resulting code must 
     * throw a NullPointerException if the first argument is null
     */
    boolean checkThis = ((mb.access & ACC_STATIC) == 0) 
                     && !method.name.string.equals("<init>");
        
    boolean redoInlining = false;
    int stackSize, stackBase;
    OpcodeInfoType opPtr;

    stackSize = 0;
    stackBase = 0;            // Prevent javac warning
    for (int pc = 0; ; pc++) { 
        /* At this point in our simulation of the execution of the
         * method, registers stackBase .. stackBase+stackSize - 1 are
         * pushed onto the the stack.  pc points to the next
         * instruction to look at.
         */
        int opcode = code[pc] & 0xff;
        int opcode2;
        int reg, regSize, nextReg;

        if (stackSize == 0)
        stackBase = 0;
        nextReg = stackBase + stackSize;
        opPtr = OpcodeInfo[opcode];

        switch (opPtr.opcode) { 

        case opc_iload_0: /* register load.  regnum from opcode */
        case opc_iload:    /* register load.  regnum from pc[1] */
            if (opPtr.opcode == opc_iload_0) { 
            reg = REGNUM(opPtr);
        } else { 
            reg = code[pc + 1] & 0xff; pc++;
        }
        regSize = REGSIZE(opPtr);
        if (stackSize == 0) /* stack is currently empty */
            stackBase = reg;
        else if (nextReg != reg)
            return NO_INLINE_FLAG;
        stackSize += regSize;
        continue;

        case opc_pop:    /* pop stack, or nop */
        stackSize -= REGSIZE(opPtr);
        continue;

        case opc_nonnull_quick: /* special instruction */
        if (nextReg == 1) {
            /* We're checking register 0 to ensure that it isn't null */
            stackSize = 0; checkThis = true;
            continue;
        }
        return NO_INLINE_FLAG;

        case opc_invokeignored_quick: /* special instruction */
        {        
        int popCount = code[pc + 1] & 0xff;
        if (code[pc + 2] != 0) {  
            /* We only know how to check register 0 for non-null ness */
            if (nextReg != popCount)
            return NO_INLINE_FLAG;
            checkThis = true;
            stackSize -= popCount;
        } else { 
            stackSize -= popCount;          
        }
        pc += 2;
        continue;
        }

        case opc_return:    /* return void or value */
        return makeReturnResult(checkThis, nextReg, REGSIZE(opPtr));

        case opc_iadd: {    /* any simple instruction */
        int ilength = opcLengths[opcode];
        int result;
        opcode2 = code[pc + ilength] & 0xff;

        if (!((opPtr.outStack > 0)
             ? isXreturn(opcode2)
             : (opcode2 == opc_return
                || opcode == opc_athrow)))
            return NO_INLINE_FLAG;

        if ((opPtr.flags & OpcodeInfoType.NULL_CHECK) != 0
            && (stackBase == 0)) {
            /* We don't need to generate code to check for null, since
             * the instruction already does it.
             */
            checkThis = false;
        }
        switch (ilength) {
        case 1:
            result =
            makeOpcodeResult(checkThis, nextReg, opPtr.inStack,
                     1, opcode, 0, 0);
            break;
        case 2:
            result = 
            makeOpcodeResult(checkThis, nextReg, opPtr.inStack,
                     2, opcode, code[pc+1] & 0xff, 0);
            break;
        case 3:
            result = 
            makeOpcodeResult(checkThis, nextReg, opPtr.inStack,
                     3, opcode,
                     code[pc+1] & 0xff, code[pc+2] & 0xff);
            break;
        default:
            throw new RuntimeException("sysAssert(FALSE);");
            // result = NO_INLINE_FLAG; // not reached
            // break;            // not reached
        }
        if ((result & NO_INLINE_FLAG) == 0) { 
            if ((opPtr.flags & OpcodeInfoType.CONSTANT_POOL) != 0) 
            result |= SAME_CLASS_FLAG;
            if (redoInlining) 
            result |= REDO_INLINING_FLAG;
        }
        return result;
        }

        default:
        throw new RuntimeException("sysAssert(FALSE);");
        case 255:        /* random instruction */
        return NO_INLINE_FLAG;

        } /* of switch statement */
    } /* end of for loop */
    
final booleancompress()


    // After inlining some code, we try to see if we can remove code.  For
    // example, the frequent case of opc_aload_0 invokeingored_quick #1 T can
    // simply "go away"

        
    MethodInfo mb = method;
        boolean rewritten = false;
        byte[] code = mb.code;
    int[] stack = new int[mb.stack + 1];
    int stackHeight = 0;
    int nextpc;
    java.util.BitSet targets = mb.getLabelTargets();

    for (int pc = 0; pc < code.length; pc = nextpc) {
        nextpc = pc + mb.opcodeLength(pc);
        int opcode = code[pc] & 0xff;
        int popping = 0;
        boolean checkThis = false;

        if (targets.get(pc)) { 
            stackHeight = 0;
        }
        stack[stackHeight] = pc;

        // Invariant.  the stackheight at this point is stackHeight or less.
        // 
        // We can pop n items from the stack (where n <= stackHeight) by
        // simply deleting all the code from stackHeight[n] to this point
        // in the code.  No side effects are removed.
        // 
        // Note that instructions that have a side effect should set
        // stackHeight = 0, to indicate that it can't be deleted.

        switch (opcode) {
        case opc_nop:
        case opc_ineg: case opc_fneg:
        case opc_i2f: case opc_f2i:
        case opc_i2b: case opc_i2c: case opc_i2s:
        case opc_newarray:
        case opc_anewarray_fast:
        case opc_instanceof_fast:
        case opc_lneg: case opc_dneg:
        case opc_l2d: case opc_d2l:
            // these don't change stack height, and we know as much about
            // the stack before as we do after.
            break;

        case opc_aconst_null: 
        case opc_iconst_m1: case opc_iconst_0: 
        case opc_iconst_1:  case opc_iconst_2:  
        case opc_iconst_3:  case opc_iconst_4:
        case opc_iconst_5:  
        case opc_fconst_0:  case opc_fconst_1: 
        case opc_fconst_2:
        case opc_bipush:    case opc_sipush:
        case opc_iload:     case opc_fload:    
        case opc_aload:
        case opc_iload_0:   case opc_iload_1:  
        case opc_iload_2:   case opc_iload_3:
        case opc_fload_0:   case opc_fload_1:  
        case opc_fload_2:   case opc_fload_3:
        case opc_aload_0:   case opc_aload_1:
        case opc_aload_2:   case opc_aload_3:
        case opc_getstatic_fast:
        case opc_dup:    
            // These push some value onto the stack, no matter what was
            // there before
            stackHeight += 1;
        break;

        case opc_lconst_0: case opc_lconst_1:
        case opc_dconst_0: case opc_dconst_1:
        case opc_lload:    case opc_dload:
        case opc_lload_0:  case opc_lload_1:
        case opc_lload_2:  case opc_lload_3:
        case opc_dload_0:  case opc_dload_1:
        case opc_dload_2:  case opc_dload_3:
        case opc_getstatic2_fast:
            // These push two values onto the stack, no matter what was 
            // there before.
            stackHeight += 2;
        break;

        case opc_i2l: case opc_i2d:
        case opc_f2l: case opc_f2d:
            // if we knew the top element of the stack, we know more
            stackHeight = (stackHeight < 1) ? 0 : stackHeight + 1;
        break;

        case opc_iadd: case opc_fadd:
        case opc_isub: case opc_fsub:
        case opc_imul: case opc_fmul:
        case opc_fdiv: case opc_frem:
        case opc_ishl: case opc_ishr: case opc_iushr:
        case opc_iand: case opc_ior: case opc_ixor:
        case opc_l2i: case opc_l2f:
        case opc_d2i:  case opc_d2f:
        case opc_fcmpl: case opc_fcmpg:
            // if we knew the top two elements of the stack, the stack
            // has just shrunk
            stackHeight = (stackHeight < 2) ? 0 : stackHeight - 1;
        break;

        case opc_lshl: case opc_lshr: case opc_lushr:
            // if we knew the top three elements of the stack, we now
            // know the top two
            stackHeight = (stackHeight < 3) ? 0 : stackHeight  - 1;
        break;

        case opc_lcmp: case opc_dcmpl: case opc_dcmpg:
            // if we knew the top 4 elements of the stack, we now
            // know the top element
            stackHeight = (stackHeight < 4) ? 0 : stackHeight - 3;
        break;
          
        case opc_ladd: case opc_dadd:
        case opc_lsub: case opc_dsub:
        case opc_lmul: case opc_dmul:
        case opc_ddiv: case opc_drem:
        case opc_land: case opc_lor: case opc_lxor:
            // if we knew the top 4 elements of the stack, we now
            // know the top 2
            stackHeight = (stackHeight < 4) ? 0 : stackHeight - 2;
        break;

        // The dup's (other than opc_dup) deal with the stack in 
        // a way that's not worth the hassle of dealing with.

        case opc_getfield_fast:
        case opc_arraylength:
            // If we throw away the result, then we just need to check that
            // the value is non-null.
        if (code[nextpc] == (byte)(opc_pop)) { 
            checkThis = true;
            nextpc += 1;
        } else { 
            stackHeight = 0;
        }
        break;

        case opc_pop2:
        popping++;    // fall thru
        case opc_pop:
            // We have to be careful.  The inliner may produce code that
            // does correspond to the stack.  For example, it might 
            // produce "pop pop2" to remove a double then an int.  We need
            // to deal with series of them at once.
        if (stackHeight > 0) {
            popping++;
            for(;;) {
            opcode = code[++pc] & 0xFF;
            if (opcode == opc_pop) 
                popping++;
            else if (opcode == opc_pop2)
                popping += 2;
            else 
                break;
            }
            nextpc = pc;
        }
        break;

        case opc_invokeignored_quick: 
            popping = code[pc + 1] & 0xff;
        if (code[pc + 2] != 0) { 
            checkThis = true; popping--;
        } 
        break;
        
        default:
            stackHeight = 0;
        }
        
        if (checkThis || (popping > 0 && stackHeight > 0)) {
        rewritten = true;
            if (stackHeight >= popping) { 
            stackHeight -= popping;
            popping = 0;
        } else { 
            popping -= stackHeight;
            stackHeight = 0;
        }
        int start = stack[stackHeight];
            
        if (checkThis) { 
            if (popping == 0 && (nextpc - start != 3)) {
                mb.replaceCode(start, nextpc, opc_nonnull_quick);
            } else { 
            mb.replaceCode(start, nextpc, 
                       opc_invokeignored_quick, popping+1, 1);
            }
            stackHeight = 0;
        } else { 
            switch (popping) { 
            case 0:  
                mb.replaceCode(start, nextpc); break;
            case 1:  
                mb.replaceCode(start, nextpc, opc_pop); break; 
            case 2:  
                mb.replaceCode(start, nextpc, opc_pop2); break; 
            default: 
                mb.replaceCode(start, nextpc, opc_invokeignored_quick, 
                       popping, 0); 
            break;
            }
        }
        }
    }
    return rewritten;
    
java.lang.StringdisassembleInlining()
Print the code as Java assembly language instructions


                   
      
    byte codeBytes[] = new byte[3];
    // Copy inlining into codeBytes[] buffer
    codeBytes[0] = (byte)(inlining & 0xff);
    codeBytes[1] = (byte)((inlining >> 8) & 0xff);
    codeBytes[2] = (byte)((inlining >> 16) & 0xff);
    return MethodInfo.disassemble(codeBytes, 0, 3);
    
private voidexamineCode()

    impureCode = false;
    mustAlign  = false;
    if ( method.code == null ){
        codeExamined = true;
        return;
    }
    byte [] code = method.code;
    int    ncode  = code.length;
    int    opcode;
    for( int i = 0; i < ncode; i += method.opcodeLength(i)) {
        switch (opcode = (int)code[i]&0xff) {

        case opc_tableswitch:
        case opc_lookupswitch:
        mustAlign = true;
        break;

        case opc_ldc:
        case opc_ldc_w:
        case opc_ldc2_w:
        case opc_getstatic:
        case opc_putstatic:
        case opc_getfield:
        case opc_putfield:
        case opc_invokevirtual:
        case opc_invokespecial:
        case opc_invokestatic:
        case opc_invokeinterface:
        case opc_new:
        case opc_anewarray:
        case opc_checkcast:
        case opc_instanceof:
        case opc_multianewarray:
        impureCode = true; // all get quicked.
        break;
        }
    }
    codeExamined = true;
    
public intgetInlining()

 
    MethodInfo mi = this.method;
    if (inlining == 0) { 
        if (   ((mi.access & (ACC_ABSTRACT | ACC_NATIVE |
                  ACC_SYNCHRONIZED)) != 0)
        || (mi.exceptionTable.length > 0)) {
        inlining = NO_INLINE_FLAG;
        } else { 
        inlineCode();
        inlining = calculateInlining();
        
        /*******
        if (inlining != NO_INLINE_FLAG) { 
            String sameClass = 
            ((inlining & SAME_CLASS_FLAG) != 0) ? "*" : "";
            System.out.print("get: " + this + " =>" + sameClass);
            System.out.println(" " + disassembleInlining());
        }
        ********/
        }
    }
    return inlining;
    
public java.lang.StringgetNativeName()


       
    if ( myNativeName == null ){
        // need to take parameter list into account.
        // OR just enumerate, as the actual name doesn't matter.
        // FIXME
        myNativeName = ((EVMClass)(method.parent.vmClass)).getNativeName()+ methodNumber;
        methodNumber+= 1;
    }
    return myNativeName;
    
public booleanhasBody()

    return ( (method.access & (ACC_ABSTRACT|ACC_NATIVE) )== 0 );
    
public voidinlineCode()


       
        new Error().printStackTrace();

        boolean isRewritten = false;
    if (inlineState == inline_NOT_DONE) { 
        inlineState = inline_IN_PROGRESS;
    } else { 
        return;
    }
    ConstantObject[] cp = method.parent.constants;
    byte[] code = method.code;
    byte[] rewrite;
    int tmi = 0;            // target method index

    for (int pc = 0; pc < code.length; ) {
        int opcode = code[pc] & 0xff;

        switch (opcode) {
                
        case opc_invokevirtual_fast:
        case opc_invokespecial_fast: 
        case opc_invokestatic_fast: {
        int index = method.getUnsignedShort(pc + 1);
        MethodConstant mc = (MethodConstant) cp[index];
        VMMethodInfo targetMethod = mc.find().vmMethodInfo;
        rewrite = MethodCallInline(pc, (EVMMethodInfo)targetMethod);
        if (rewrite != null) {
            isRewritten = true;
            System.arraycopy(rewrite, 0, code, pc, 3);
        }
        pc += 3;
        break;
        }

        default:
            pc += method.opcodeLength(pc);
        break;
        }
    }
    if (isRewritten) 
        compress();
    inlineState = inline_DONE;
    
public booleanisCodePure()

    if ( ! codeExamined ){
        examineCode(); // may throw exception without setting codeExamined
    }
    return !impureCode;
    
private static booleanisXreturn(int opcode)

    return (opcode >= opc_ireturn) && (opcode <= opc_areturn);
    
private intmakeOpcodeResult(boolean checkThis, int nextReg, int opcodeArgCount, int icount, int opcode, int op1, int op2)

        MethodInfo mb = method;
    int firstReg = (opcodeArgCount == 0) ? 0 : nextReg - opcodeArgCount;
    // sysAssert(firstReg >= 0 && opcodeArgCount >= 0 && icount > 0);

    if (firstReg > 0) {
        /* There are extra registers at the bottom of the stack */
        return makePoppingResult(checkThis, firstReg, opcodeArgCount, 
                     icount, opcode, op1, op2);
    } else {
        /* No extra registers at bottom of stack */
        int argsSize = mb.argsSize;
        int excessArgs = argsSize - opcodeArgCount; /* extra at top */
        int popSpace = 3 - icount; /* space to pop args at top */

        int result = 0;
        int i;

        if (checkThis) { 
        /* Unless this is a constant method that ignores all of its
         * arguments, we don't really have any way of checking
         * register 0 if the instructions doesn't.  If it is a
         * constant instruction, deduct one from both popSpace and
         * from excessArgs, since we are popping that last argument
         * when an opc_nonnull_quick;
         */
        if (opcodeArgCount > 0 || popSpace == 0)
            return NO_INLINE_FLAG;
        popSpace--; excessArgs--; 
        // sysAssert(excessArgs >= 0);
        }
        if (excessArgs > 2 * popSpace) 
        return NO_INLINE_FLAG;
        for (i = 0; i < popSpace; i++) { 
        /* If excessArgs <= popSpace, the following generates excessArgs
         * "pops" followed by nops.  Otherwise, it generates 
         * excessArgs - popSpace pop2's followed by pop's.
         */
        int opcodeTmp = (excessArgs <= i) ? opc_nop 
            : (excessArgs <= popSpace + i) ? opc_pop 
            : opc_pop2;
        result |= (opcodeTmp << (i << 3));
        }
        if (checkThis) 
        result |= opc_nonnull_quick << ((i++) << 3);
        // sysAssert(i + icount == 3);
        switch (icount) { 
           case 3: result |= op2 << ((i + 2) << 3);
           case 2: result |= op1 << ((i + 1) << 3);
           case 1: result |= opcode << ((i + 0) << 3);
        }
        return result;
    }
    
private intmakePoppingResult(boolean checkThis, int firstReg, int opcodeArgCount, int icount, int opcode, int op1, int op2)

        MethodInfo mb = method;
    int argsSize = mb.argsSize;
    int excessArgs = argsSize - opcodeArgCount - firstReg; /* extra on top*/

    if (icount > 1)
        /* We're just not prepared to deal with this. */
        return NO_INLINE_FLAG;

    if (OpcodeInfo[opcode].outStack == 0) {
        int result = 0;
        /* Something like an array store, that leaves no value on the
               stack */
        int i = 0;
        /* We can't deal with checkThis, since it might reverse the order of
         * an exception.  We have a total of two instructions to do all the 
         * pre and post popping.
         */
        if (checkThis || ((excessArgs + 1)/2 + (firstReg + 1)/2) > 2)
        return NO_INLINE_FLAG;
        for (; excessArgs > 0; excessArgs -=2) /* pre popping */
        result |= (excessArgs == 1 ? opc_pop : opc_pop2)
            << ((i++) << 3);
        result |= opcode << ((i++) << 3);
        for (; firstReg > 0; firstReg -=2) /* post popping */
        result |= (firstReg == 1 ? opc_pop : opc_pop2)
            << ((i++) << 3);
        while (i < 3)
        result |= opc_nop << ((i++) << 3);
        return result;
    }

    if (excessArgs > 0 || firstReg > 1)
        /* We can't both do useful work and remove more than this many 
         * items from the stack. */
        return NO_INLINE_FLAG;

    if (opcodeArgCount == 1) { 
        return MAKE_INLINING(opc_swap, 
                 checkThis ? opc_nonnull_quick
                    : opc_pop, 
                 opcode);
    }
    if (   ((OpcodeInfo[opcode].flags &
         (OpcodeInfoType.NULL_CHECK | OpcodeInfoType.CAN_ERROR)) == 0)
        && (OpcodeInfo[opcode].outStack == 1)) {
        /* The result creates one thing on the stack, and it can't error */
        return MAKE_INLINING(opcode,
                 opc_swap,
                 checkThis ? opc_nonnull_quick
                    : opc_pop);
    }
    return NO_INLINE_FLAG;
    
private intmakeReturnResult(boolean checkThis, int highReg, int returnSize)

             
        MethodInfo mb = method;
    int argsSize = mb.argsSize;
    if (returnSize == 0) { 
        /* Return void */
        return MAKE_INLINING(opc_invokeignored_quick, argsSize,
                 (checkThis ? 1 : 0));
    } else {
        /* Return some value from the stack */
        int returnReg = highReg - returnSize;  
        int excessArgs =  argsSize - returnSize - returnReg;
        // sysAssert(returnReg >= 0 && returnSize >= 0);
        if (returnReg == 0) { 
        /* Returning reg0 or reg0/reg1 */
        if (checkThis) { 
            /* Must be returning reg0, which is also checked. We
             * require argsSize >= 2 (which is the same thing as
             * excessArgs >= 1), because otherwise the "dup" might
             * overflow the stack.  More sophisticated inliners
             * might see if there is space on the caller's stack.
             */
            // sysAssert(returnSize == 1);
            if (argsSize < 2) { 
            return NO_INLINE_FLAG;
            } else if (excessArgs > 2) { 
                return NO_INLINE_FLAG;
            } else { 
                return MAKE_INLINING(poppers[excessArgs],
                         opc_dup,
                         opc_nonnull_quick);
            }
        } else {
            /* We're returning reg0 or reg0/reg1 which isn't null
             * checked.  We just pop extraneous stuff off the stack
             * */
            return MAKE_INLINING(opc_invokeignored_quick,
                     excessArgs, 0);
        }
        } else {
        /* At this point, returnReg > 0.  We're returning something
         * other than the bottom of the stack.
         */
            if (returnSize == 1 && returnReg == 1) { 
            if (excessArgs > 2) { 
            return NO_INLINE_FLAG;
            }
            return MAKE_INLINING(poppers[excessArgs], 
                     opc_swap, 
                     checkThis ? opc_nonnull_quick
                        : opc_pop);
        }
        return NO_INLINE_FLAG;
        }
    }
    
public intmethodOffset()

    int off = method.methodTableIndex;
    if ( off < 0 ){
        /*
         * off < 0 means that we do not have a methodtable or
         * imethodtable entry for this method. This is ok if it is:
         * - private, or
         * - static, or
         * - <init>
         * Otherwise, this is an error.
         */
        if ( method.isStaticMember( ) 
        || method.isPrivateMember( ) 
        || method.name.string.equals("<init>") ) {
            return 0;
        } else {
        throw new Error("Bad method offset for "+method.qualifiedName() );
        }
    }
    return off;
    
public java.lang.StringtoString()

    if (myName == null) {
        myName = method.parent.className + "." + method.name.string + 
        method.type.string;
    } 
    return myName;