CodeHackerpublic 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 FMIrefConstant | dup(FMIrefConstant c)
return (FMIrefConstant) pool.dup( c );
| private static int | getInt(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 int | getUnsignedShort(byte[] code, int w)
return (( (int)code[w] &0xff ) << 8 ) | ( (int)code[w+1] &0xff );
| private boolean | isSpecialSuperCall(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 void | lookupFailed(ClassConstant me, FMIrefConstant target)
log.println("Quickening "+me.name.string+": lookup failed for "+target);
success = false;
| private static void | putShort(byte[] code, int w, short v)
code[w] = (byte)(v>>>8);
code[w+1] = (byte)v;
| public boolean | quickenCode(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 boolean | quickenCode(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 boolean | quickenFieldAccess(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;
}
|
|