FileDocCategorySizeDatePackage
CodeHacker.javaAPI DocJ2ME CLDC 1.110938Wed Feb 05 15:56:04 GMT 2003vm

CodeHacker

public class CodeHacker extends Object

Fields Summary
ConstantPool
pool
boolean
warn
boolean
verbose
PrintStream
log
boolean
useLosslessOpcodes
ClassInfo
java_lang_Object
private boolean
success
private byte
newopcode
Constructors Summary
public CodeHacker(ConstantPool p, boolean lossless, boolean w, boolean v)


              
    pool = p;
    warn = w;
    verbose = v;
    log = System.out;
    java_lang_Object = ClassInfo.lookupClass("java/lang/Object");
    if ( java_lang_Object == null ){
        log.println("CodeHacker: could not find java/lang/Object");
    }
    useLosslessOpcodes = lossless;
    
Methods Summary
private FMIrefConstantdup(FMIrefConstant c)

    return (FMIrefConstant) pool.dup( c );
    
private static intgetInt(byte[] code, int w)

    return    (  (int)code[w]   << 24 ) |
        (( (int)code[w+1] &0xff ) << 16 ) |
        (( (int)code[w+2] &0xff ) << 8 ) |
         ( (int)code[w+3] &0xff );
    
private static intgetUnsignedShort(byte[] code, int w)

    return    (( (int)code[w] &0xff ) << 8 ) | ( (int)code[w+1] &0xff );
    
private booleanisSpecialSuperCall(MethodInfo me, MethodInfo callee)

    String name = callee.name.string;
    if ( (callee.access&Const.ACC_PRIVATE) != 0 ) return false;
    if ( name.equals("<init>") ) return false;
    ClassInfo myclass = me.parent;
    ClassInfo hisclass = callee.parent;
    if ( myclass == hisclass ) return false;
    // walk up my chain, looking for other's class
    while ( myclass != null ){
        myclass = myclass.superClassInfo;
        if ( myclass == hisclass ) return true;
    }
    return false;
    
private voidlookupFailed(ClassConstant me, FMIrefConstant target)

    log.println("Quickening "+me.name.string+": lookup failed for "+target);
    success = false;
    
private static voidputShort(byte[] code, int w, short v)

    code[w]   = (byte)(v>>>8);
    code[w+1] = (byte)v;
    
public booleanquickenCode(ClassInfo c)

    ConstantObject constants[] = c.constants;
    MethodInfo     method[]= c.methods;
    int n = method.length;
    int i = 0;
    boolean result = true;
    try {
        for ( i = 0; i < n; i++ ){
        if ( ! quickenCode( method[i], constants ) )
            result = false;
        }
    } catch( DataFormatException e ){
        System.err.println("Quickening "+method[i].qualifiedName()+" got exception:");
        e.printStackTrace();
        return false;
    }
    return result;
    
private booleanquickenCode(MethodInfo m, ConstantObject[] c)

    byte code[] = m.code;
    int list[] = m.ldcInstructions;
    ConstantObject        co;
    FieldConstant        fc;
    MethodConstant        mc;
    NameAndTypeConstant    nt;
    ClassConstant        cc;
    String            t;
    ClassConstant        me = m.parent.thisClass;
    MethodInfo        mi;
    ClassInfo        ci;

    success = true;
    if (verbose){
        log.println("Q>>METHOD "+m.name.string );
    }
    if ( list != null ){
        for ( int i = 0; i < list.length; i++ ){
        int loc = list[i];
        if ( loc < 0 ) continue;
        switch( (int)code[loc]&0xff ){
        case Const.opc_ldc:
            //
            // no danger of lookup failure here,
            // so don't even examine the referenced object.
            //
            co = c[(int)code[loc+1]&0xff];
            break;
        default:
            throw new DataFormatException( "unexpected opcode in ldc="+
            ((int)code[loc]&0xff)+" at loc="+loc+
            " in "+m.qualifiedName() );
        }
        }
    }
    list = m.wideConstantRefInstructions;
    if ( list != null ){
        MethodInfo[] tList = null;
        int tli = 0;        // index into tList
        if (VMMethodInfo.SAVE_TARGET_METHODS) {
        tList = new MethodInfo[list.length];
        }
        for ( int i = 0; i < list.length; i++ ){
        int loc = list[i];
        if ( loc < 0 ) continue;
        co = c[ getUnsignedShort(code, loc+1) ];
        if ( ! co.isResolved() ){
            //
            // don't try to quicken unresolved references.
            // this is not fatal!
            //
            // Do quicken if its a reference to an array!!
            // What a hack!
            if ( (co instanceof ClassConstant ) &&
             ((ClassConstant)co).name.string.charAt(0) == Const.SIGC_ARRAY ){
            ((ClassConstant)co).forget(); // never mind, we'll fix later...
            } else {
            if ( warn ){
                log.println("Warning: could not quicken reference from " + m.qualifiedName() + " to "+co );
            }
            continue;
            }
        }
        switch( (int)code[loc]&0xff ){
        case Const.opc_ldc_w:
            co.incldcReference();
            break;
        case Const.opc_ldc2_w:
            break;
        case Const.opc_getstatic:
            quickenFieldAccess( me, code, loc, true, c,
            Const.opc_getstatic_fast,
            Const.opc_getstatic2_fast, Const.opc_getstaticp_fast);
            break;
        case Const.opc_putstatic:
            quickenFieldAccess( me, code, loc, true, c,
            Const.opc_putstatic_fast,
            Const.opc_putstatic2_fast, 
            Const.opc_putstatic_fast);
            break;
        case Const.opc_getfield:
            if (quickenFieldAccess( me, code, loc, false, c,
              Const.opc_getfield_fast,
              Const.opc_getfield2_fast, 
              Const.opc_getfieldp_fast )) {
            // doesn't reference constant pool any more
            list[i] = -1;
            }
            break;
        case Const.opc_putfield:
            if (quickenFieldAccess( me, code, loc, false, c,
              Const.opc_putfield_fast,
              Const.opc_putfield2_fast,
              Const.opc_putfield_fast)) {
            // doesn't reference constant pool any more
            list[i] = -1;
            }
            break;

        case Const.opc_invokevirtual:
                    mc = (MethodConstant)c[ getUnsignedShort( code, loc+1 ) ];
                    mi = mc.find();
                    if (mi != null){
                        if (mi.isPrivateMember() 
                            || ((mi.access & Const.ACC_FINAL) != 0)
                            || ((mi.parent.access & Const.ACC_FINAL) != 0)) { 
                            code[loc] = (byte)Const.opc_invokespecial_fast;
                        }
                    }
                    break;

        case Const.opc_invokeinterface:
            break;

        case Const.opc_invokestatic:
            code[loc] = (byte)Const.opc_invokestatic_fast;
            break;

        case Const.opc_new:
            code[loc] = (byte)Const.opc_new_fast;
            break;

        case Const.opc_anewarray:
            // code[loc] = (byte)Const.opc_anewarray_fast;
            break;

        case Const.opc_checkcast:
            code[loc] = (byte)Const.opc_checkcast_fast;
            break;

        case Const.opc_instanceof:
            code[loc] = (byte)Const.opc_instanceof_fast;
            break;

        case Const.opc_multianewarray:
            code[loc] = (byte)Const.opc_multianewarray_fast;
            break;

        case Const.opc_invokespecial:
            code[loc] = (byte)Const.opc_invokespecial_fast;
            break;

        default: 
            throw new DataFormatException( "unexpected opcode in wideConstantRef="+
            ((int)code[loc]&0xff)+" at loc="+loc+
            " in "+m.qualifiedName() );
        }
        }
        // Alloc and copy to new targetMethods array
        if (VMMethodInfo.SAVE_TARGET_METHODS) {
        m.targetMethods = new MethodInfo[tli];
        System.arraycopy(tList, 0, m.targetMethods, 0, tli);
        }
    }
    return success;
    
private booleanquickenFieldAccess(ClassConstant me, byte[] code, int loc, boolean isStatic, ConstantObject[] c, int oneWord, int twoWords, int refReference)

    FieldConstant fc = (FieldConstant)c[ getUnsignedShort( code, loc+1 ) ];
    FieldInfo  fi = fc.find();
    if ( fi == null ){
        // never even try to quicken anything we cannot resolve.
        lookupFailed( me, fc );
        return false;
    }
    byte newCode;
    switch (fc.sig.type.string.charAt(0) ){
    case '[":
    case 'L":
        newCode = (byte)refReference;
        break;
    case 'D":
    case 'J":
        newCode = (byte)twoWords;
        break;
    default:
        newCode = (byte)oneWord;
        break;
    }
    if ( isStatic ) {
        code[loc] = newCode;
        return false; // still references constant pool!
    } else {
        int fieldOffset = fi.instanceOffset;
        code[loc+1] =  (byte)((fieldOffset >> 8) & 0xFF);
        code[loc+2] =  (byte) (fieldOffset & 0xFF);
        code[loc] = newCode;
        return true;
    }