[Joeq-checkins] /joeq_core/joeq/Compiler/Quad BasicBlock.java,1.22,1.23 MethodInline.java,1.48,1.49
Status: Alpha
Brought to you by:
joewhaley
From: V.Benjamin L. <liv...@us...> - 2006-02-25 05:49:46
|
Update of /cvsroot/joeq//joeq_core/joeq/Compiler/Quad In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19850/joeq/Compiler/Quad Modified Files: BasicBlock.java MethodInline.java Log Message: Changed the way inlining is done with the help of fake call locations. Index: BasicBlock.java =================================================================== RCS file: /cvsroot/joeq//joeq_core/joeq/Compiler/Quad/BasicBlock.java,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** BasicBlock.java 22 Sep 2004 22:17:27 -0000 1.22 --- BasicBlock.java 25 Feb 2006 05:49:42 -0000 1.23 *************** *** 197,200 **** --- 197,208 ---- } + /** + * Replace the quad at position pos. + * */ + public void replaceQuad(int pos, Quad q) { + Assert._assert(instructions != null, "Cannot add instructions to entry/exit basic block"); + instructions.set(pos, q); + } + /** Add a predecessor basic block to this basic block. * Cannot add predecessors to the entry basic block. Index: MethodInline.java =================================================================== RCS file: /cvsroot/joeq//joeq_core/joeq/Compiler/Quad/MethodInline.java,v retrieving revision 1.48 retrieving revision 1.49 diff -C2 -d -r1.48 -r1.49 *** MethodInline.java 24 Feb 2006 21:13:04 -0000 1.48 --- MethodInline.java 25 Feb 2006 05:49:42 -0000 1.49 *************** *** 14,18 **** --- 14,22 ---- import java.util.Map; import java.util.Map.Entry; + import joeq.Class.PrimordialClassLoader; import joeq.Class.jq_Class; + import joeq.Class.jq_FakeInstanceMethod; + import joeq.Class.jq_FakeStaticMethod; + import joeq.Class.jq_InstanceMethod; import joeq.Class.jq_Method; import joeq.Class.jq_Primitive; *************** *** 24,27 **** --- 28,32 ---- import joeq.Compiler.Quad.Operand.ConditionOperand; import joeq.Compiler.Quad.Operand.IConstOperand; + import joeq.Compiler.Quad.Operand.MethodOperand; import joeq.Compiler.Quad.Operand.ParamListOperand; import joeq.Compiler.Quad.Operand.RegisterOperand; *************** *** 46,50 **** public class MethodInline implements ControlFlowGraphVisitor { ! public static final boolean TRACE = true; public static final boolean TRACE_ORACLE = false; public static final boolean TRACE_DECISIONS = false; --- 51,55 ---- public class MethodInline implements ControlFlowGraphVisitor { ! public static final boolean TRACE = false; public static final boolean TRACE_ORACLE = false; public static final boolean TRACE_DECISIONS = false; *************** *** 56,59 **** --- 61,65 ---- //private static Map fakeMethodOperand = new HashMap(); static HashMap/*<Quad, Quad>*/ newlyInserted = new HashMap(); + private static HashMap/*<jq_Method, jq_Method>*/ fakeMethodOperand = new HashMap(); public MethodInline(Oracle o) { *************** *** 120,158 **** this.callee = CodeCache.getCode(target); } ! public void inlineCall(ControlFlowGraph caller, BasicBlock bb, Quad q, boolean preserveCallSite) { /* Insert a fake replacement method call */ ! /* ! MethodOperand fakeOperand = getFakeMethodOperand(Invoke.getMethod(q).getMethod()); ! if(fakeOperand != null){ ! int len = fakeOperand.getMethod().getParamTypes().length; ! Quad fakeCallQuad = Invoke.InvokeStatic.create( ! caller.getNewQuadID(), Invoke.INVOKESTATIC_A.INSTANCE, ! (RegisterOperand) q.getOp1().copy(), (MethodOperand) fakeOperand.copy(), ! len); ! ! for(int i = 0; i < len; i++){ ! Invoke.setParam(fakeCallQuad, i, (RegisterOperand) Invoke.getParam(q, i).copy()); ! } ! bb.appendQuad(fakeCallQuad); ! // System.out.println( ! // "Replaced a call to " + Invoke.getMethod(q) + ! // " with a call to " + fakeOperand.getMethod()); ! ! // return; } ! */ ! //inlineVirtualCallSiteWithTypeCheck(caller, bb, q, callee, expectedType); if(q.getOperator() instanceof InvokeStatic) { ! inlineNonVirtualCallSite(caller, bb, q, callee, preserveCallSite); } else { ! inlineVirtualCallSiteWithTypeCheck(caller, bb, q, callee, expectedType, preserveCallSite); } - //CodeCache.invalidateBCMap(caller.getMethod()); } public String toString() { return callee.getMethod().toString(); } } ! public static class InlineSmallSingleTargetCalls implements Oracle { ! protected CallGraph cg; int bcThreshold; --- 126,158 ---- this.callee = CodeCache.getCode(target); } ! public void inlineCall(ControlFlowGraph caller, BasicBlock bb, Quad q, boolean preserveCallSite) { ! //inlineVirtualCallSiteWithTypeCheck(caller, bb, q, callee, expectedType); ! /* Insert a fake replacement method call */ ! MethodOperand fakeOperand = getFakeMethodOperand(Invoke.getMethod(q).getMethod(), mi.pa); ! Assert._assert(fakeOperand != null); ! int len = fakeOperand.getMethod().getParamTypes().length; ! Quad fakeCallQuad = Invoke.InvokeStatic.create( ! caller.getNewQuadID(), Invoke.INVOKESTATIC_A.INSTANCE, ! (RegisterOperand) (q.getOp1() != null ? q.getOp1().copy() : null), ! (MethodOperand) fakeOperand.copy(), len); ! ! for(int i = 0; i < len; i++){ ! Invoke.setParam(fakeCallQuad, i, (RegisterOperand) Invoke.getParam(q, i).copy()); } ! System.out.println( ! "Replaced a call to " + Invoke.getMethod(q) + ! " with a call to " + fakeOperand.getMethod()); ! if(q.getOperator() instanceof InvokeStatic) { ! inlineNonVirtualCallSiteReplacingCall(caller, bb, q, callee, expectedType, fakeCallQuad); } else { ! inlineVirtualCallSiteWithTypeCheckRepacingCall(caller, bb, q, callee, expectedType, fakeCallQuad); } } public String toString() { return callee.getMethod().toString(); } } ! public static class InlineSmallSingleTargetCalls implements Oracle { protected CallGraph cg; int bcThreshold; *************** *** 549,552 **** --- 549,848 ---- if (TRACE) out.println(CodeCache.getCode(callee.getMethod()).getRegisterFactory().fullDump()); } + + public static void inlineVirtualCallSiteWithTypeCheckRepacingCall(ControlFlowGraph caller, BasicBlock bb, Quad q, ControlFlowGraph callee, jq_Class type, Quad replacementQuad) { + if (TRACE) out.println("Inlining "+q+" in "+bb+" for target "+callee.getMethod()); + + int invokeLocation = bb.getQuadIndex(q); + Assert._assert(invokeLocation != -1); + + if (TRACE) out.println("Code to inline:"); + if (TRACE) out.println(callee.fullDump()); + if (TRACE) out.println(callee.getRegisterFactory().fullDump()); + + // copy the callee's control flow graph, renumbering the basic blocks, + // registers and quads, and add the exception handlers. + callee = caller.merge(callee); + + if (TRACE) out.println("After renumbering:"); + if (TRACE) out.println(callee.fullDump()); + if (TRACE) out.println(callee.getRegisterFactory().fullDump()); + callee.appendExceptionHandlers(bb.getExceptionHandlers()); + + if (TRACE) out.println("Original basic block containing invoke:"); + if (TRACE) out.println(bb.fullDump()); + + // split the basic block containing the invoke, and start splicing + // in the callee's control flow graph. + BasicBlock successor_bb = caller.createBasicBlock(callee.exit().getNumberOfPredecessors() + 1, bb.getNumberOfSuccessors(), bb.size() - invokeLocation, bb.getExceptionHandlers()); + + int bb_size = bb.size(); + for (int i=invokeLocation+1; i<bb_size; ++i) { + successor_bb.appendQuad(bb.removeQuad(invokeLocation+1)); + } + Quad invokeQuad = null; + invokeQuad = bb.removeQuad(invokeLocation); + Assert._assert(invokeQuad == q); + Assert._assert(bb.size() == invokeLocation); + + if (TRACE) out.println("Result of splitting:"); + if (TRACE) out.println(bb.fullDump()); + if (TRACE) out.println(successor_bb.fullDump()); + + // create failsafe case block + BasicBlock bb_fail = caller.createBasicBlock(1, 1, 2, bb.getExceptionHandlers()); + bb_fail.appendQuad(replacementQuad); + Quad q2 = Goto.create(caller.getNewQuadID(), + Goto.GOTO.INSTANCE, + new TargetOperand(successor_bb)); + bb_fail.appendQuad(q2); + bb_fail.addSuccessor(successor_bb); + successor_bb.addPredecessor(bb_fail); + if (TRACE) out.println("Fail-safe block:"); + if (TRACE) out.println(bb_fail.fullDump()); + + // create success case block + BasicBlock bb_success = caller.createBasicBlock(1, 1, Invoke.getParamList(q).length(), bb.getExceptionHandlers()); + + // add test. + jq_Type dis_t = Invoke.getParam(q, 0).getType(); + RegisterOperand dis_op = new RegisterOperand(Invoke.getParam(q, 0).getRegister(), dis_t); + Register res = caller.getRegisterFactory().getOrCreateStack(0, jq_Primitive.BOOLEAN); + RegisterOperand res_op = new RegisterOperand(res, jq_Primitive.BOOLEAN); + TypeOperand type_op = new TypeOperand(type); + q2 = InstanceOf.create(caller.getNewQuadID(), InstanceOf.INSTANCEOF.INSTANCE, res_op, dis_op, type_op); + bb.appendQuad(q2); + res_op = new RegisterOperand(res, jq_Primitive.BOOLEAN); + IConstOperand zero_op = new IConstOperand(0); + ConditionOperand ne_op = new ConditionOperand(BytecodeVisitor.CMP_NE); + TargetOperand success_op = new TargetOperand(bb_success); + q2 = IntIfCmp.create(caller.getNewQuadID(), IntIfCmp.IFCMP_I.INSTANCE, res_op, zero_op, ne_op, success_op); + bb.appendQuad(q2); + + // add instructions to set parameters. + ParamListOperand plo = Invoke.getParamList(q); + jq_Type[] params = callee.getMethod().getParamTypes(); + for (int i=0, j=0; i<params.length; ++i, ++j) { + Move op = Move.getMoveOp(params[i]); + Register dest_r = callee.getRegisterFactory().getOrCreateLocal(j, params[i]); + RegisterOperand dest = new RegisterOperand(dest_r, params[i]); + Register src_r = plo.get(i).getRegister(); + RegisterOperand src = new RegisterOperand(src_r, params[i]); + q2 = Move.create(caller.getNewQuadID(), op, dest, src); + bb_success.appendQuad(q2); + if (params[i].getReferenceSize() == 8) ++j; + } + if (TRACE) out.println("Success block after adding parameter moves:"); + if (TRACE) out.println(bb_success.fullDump()); + + // replace return instructions with moves and gotos, and + // finish splicing in the control flow graph. + for (ListIterator.BasicBlock it = bb.getSuccessors().basicBlockIterator(); + it.hasNext(); ) { + BasicBlock next_bb = it.nextBasicBlock(); + next_bb.removePredecessor(bb); + next_bb.addPredecessor(successor_bb); + successor_bb.addSuccessor(next_bb); + } + bb_success.addSuccessor(callee.entry().getFallthroughSuccessor()); + callee.entry().getFallthroughSuccessor().removeAllPredecessors(); + callee.entry().getFallthroughSuccessor().addPredecessor(bb_success); + bb.removeAllSuccessors(); + bb.addSuccessor(bb_fail); + bb_fail.addPredecessor(bb); + bb.addSuccessor(bb_success); + bb_success.addPredecessor(bb); + RegisterOperand dest = Invoke.getDest(q); + Register dest_r = null; + Move op = null; + if (dest != null) { + dest_r = dest.getRegister(); + op = Move.getMoveOp(callee.getMethod().getReturnType()); + } + + outer: + for (ListIterator.BasicBlock it = callee.exit().getPredecessors().basicBlockIterator(); + it.hasNext(); ) { + BasicBlock pred_bb = it.nextBasicBlock(); + while (pred_bb.size() == 0) { + if (TRACE) System.out.println("Predecessor of exit has no quads? "+pred_bb); + if (pred_bb.getNumberOfPredecessors() == 0) continue outer; + pred_bb = pred_bb.getFallthroughPredecessor(); + } + Quad lq = pred_bb.getLastQuad(); + if (lq.getOperator() instanceof Return.THROW_A) { + pred_bb.removeAllSuccessors(); pred_bb.addSuccessor(caller.exit()); + caller.exit().addPredecessor(pred_bb); + continue; + } + Assert._assert(lq.getOperator() instanceof Return); + pred_bb.removeQuad(lq); + if (dest_r != null) { + RegisterOperand ldest = new RegisterOperand(dest_r, callee.getMethod().getReturnType()); + Operand src = Return.getSrc(lq).copy(); + Quad q3 = Move.create(caller.getNewQuadID(), op, ldest, src); + pred_bb.appendQuad(q3); + } + q2 = Goto.create(caller.getNewQuadID(), + Goto.GOTO.INSTANCE, + new TargetOperand(successor_bb)); + pred_bb.appendQuad(q2); + pred_bb.removeAllSuccessors(); pred_bb.addSuccessor(successor_bb); + successor_bb.addPredecessor(pred_bb); + } + + if (TRACE) out.println("Final result:"); + if (TRACE) out.println(caller.fullDump()); + if (TRACE) out.println(caller.getRegisterFactory().fullDump()); + + if (TRACE) out.println("Original code:"); + if (TRACE) out.println(CodeCache.getCode(callee.getMethod()).fullDump()); + if (TRACE) out.println(CodeCache.getCode(callee.getMethod()).getRegisterFactory().fullDump()); + } + + public static void inlineNonVirtualCallSiteReplacingCall(ControlFlowGraph caller, BasicBlock bb, Quad q, ControlFlowGraph callee, jq_Class type, Quad replacementQuad) { + if (TRACE) out.println("Inlining "+q+" target "+callee.getMethod()+" in "+bb); + + int invokeLocation = bb.getQuadIndex(q); + Assert._assert(invokeLocation != -1); + + if (TRACE) out.println("Code to inline:"); + if (TRACE) out.println(callee.fullDump()); + if (TRACE) out.println(callee.getRegisterFactory().fullDump()); + + // copy the callee's control flow graph, renumbering the basic blocks, + // registers and quads, and add the exception handlers. + callee = caller.merge(callee); + + if (TRACE) out.println("After renumbering:"); + if (TRACE) out.println(callee.fullDump()); + if (TRACE) out.println(callee.getRegisterFactory().fullDump()); + callee.appendExceptionHandlers(bb.getExceptionHandlers()); + + if (TRACE) out.println("Original basic block containing invoke:"); + if (TRACE) out.println(bb.fullDump()); + + // split the basic block containing the invoke, and start splicing + // in the callee's control flow graph. + BasicBlock successor_bb = caller.createBasicBlock(callee.exit().getNumberOfPredecessors(), bb.getNumberOfSuccessors(), bb.size() - invokeLocation, bb.getExceptionHandlers()); + int bb_size = bb.size(); + for (int i=invokeLocation+1; i<bb_size; ++i) { + successor_bb.appendQuad(bb.removeQuad(invokeLocation+1)); + } + // remove the site + Quad invokeQuad = bb.removeQuad(invokeLocation); + Assert._assert(invokeQuad == q); + Assert._assert(bb.size() == invokeLocation); + + if (TRACE) out.println("Result of splitting:"); + if (TRACE) out.println(bb.fullDump()); + if (TRACE) out.println(successor_bb.fullDump()); + + { + // create failsafe case block + BasicBlock bb_fail = caller.createBasicBlock(1, 1, 2, bb.getExceptionHandlers()); + bb_fail.appendQuad(replacementQuad); + Quad q2 = Goto.create(caller.getNewQuadID(), + Goto.GOTO.INSTANCE, + new TargetOperand(successor_bb)); + bb_fail.appendQuad(q2); + bb_fail.addSuccessor(successor_bb); + successor_bb.addPredecessor(bb_fail); + if (TRACE) out.println("Fail-safe block:"); + if (TRACE) out.println(bb_fail.fullDump()); + + // create success case block + BasicBlock bb_success = caller.createBasicBlock(1, 1, Invoke.getParamList(q).length(), bb.getExceptionHandlers()); + + // add test. + jq_Type dis_t = PrimordialClassLoader.JavaLangString; // just a dummy type check + RegisterOperand dis_op = new RegisterOperand(caller.getRegisterFactory().get(0), dis_t); + Register res = caller.getRegisterFactory().getOrCreateStack(0, jq_Primitive.BOOLEAN); + RegisterOperand res_op = new RegisterOperand(res, jq_Primitive.BOOLEAN); + TypeOperand type_op = new TypeOperand(type); + q2 = InstanceOf.create(caller.getNewQuadID(), InstanceOf.INSTANCEOF.INSTANCE, res_op, dis_op, type_op); + bb.appendQuad(q2); + res_op = new RegisterOperand(res, jq_Primitive.BOOLEAN); + IConstOperand zero_op = new IConstOperand(0); + ConditionOperand ne_op = new ConditionOperand(BytecodeVisitor.CMP_NE); + TargetOperand success_op = new TargetOperand(bb_success); + q2 = IntIfCmp.create(caller.getNewQuadID(), IntIfCmp.IFCMP_I.INSTANCE, res_op, zero_op, ne_op, success_op); + bb.appendQuad(q2); + } + + // add instructions to set parameters. + ParamListOperand plo = Invoke.getParamList(q); + jq_Type[] params = callee.getMethod().getParamTypes(); + for (int i=0, j=0; i<params.length; ++i, ++j) { + Move op = Move.getMoveOp(params[i]); + Register dest_r = callee.getRegisterFactory().getOrCreateLocal(j, params[i]); + RegisterOperand dest = new RegisterOperand(dest_r, params[i]); + Register src_r = plo.get(i).getRegister(); + RegisterOperand src = new RegisterOperand(src_r, params[i]); + Quad q2 = Move.create(caller.getNewQuadID(), op, dest, src); + bb.appendQuad(q2); + if (params[i].getReferenceSize() == 8) ++j; + } + if (TRACE) out.println("Result after adding parameter moves:"); + if (TRACE) out.println(bb.fullDump()); + + // replace return instructions with moves and gotos, and + // finish splicing in the control flow graph. + for (ListIterator.BasicBlock it = bb.getSuccessors().basicBlockIterator(); + it.hasNext(); ) { + BasicBlock next_bb = it.nextBasicBlock(); + next_bb.removePredecessor(bb); + next_bb.addPredecessor(successor_bb); + successor_bb.addSuccessor(next_bb); + } + bb.removeAllSuccessors(); + bb.addSuccessor(callee.entry().getFallthroughSuccessor()); + callee.entry().getFallthroughSuccessor().removeAllPredecessors(); + callee.entry().getFallthroughSuccessor().addPredecessor(bb); + RegisterOperand dest = Invoke.getDest(q); + Register dest_r = null; + Move op = null; + if (dest != null) { + dest_r = dest.getRegister(); + op = Move.getMoveOp(callee.getMethod().getReturnType()); + } + outer: + for (ListIterator.BasicBlock it = callee.exit().getPredecessors().basicBlockIterator(); + it.hasNext(); ) { + BasicBlock pred_bb = it.nextBasicBlock(); + while (pred_bb.size() == 0) { + if (TRACE) System.out.println("Predecessor of exit has no quads? "+pred_bb); + if (pred_bb.getNumberOfPredecessors() == 0) continue outer; + pred_bb = pred_bb.getFallthroughPredecessor(); + } + Quad lq = pred_bb.getLastQuad(); + if (lq.getOperator() instanceof Return.THROW_A) { + pred_bb.removeAllSuccessors(); pred_bb.addSuccessor(caller.exit()); + caller.exit().addPredecessor(pred_bb); + continue; + } + Assert._assert(lq.getOperator() instanceof Return); + pred_bb.removeQuad(lq); + if (dest_r != null) { + RegisterOperand ldest = new RegisterOperand(dest_r, callee.getMethod().getReturnType()); + Operand src = Return.getSrc(lq).copy(); + Quad q3 = Move.create(caller.getNewQuadID(), op, ldest, src); + pred_bb.appendQuad(q3); + } + Quad q2 = Goto.create(caller.getNewQuadID(), + Goto.GOTO.INSTANCE, + new TargetOperand(successor_bb)); + pred_bb.appendQuad(q2); + pred_bb.removeAllSuccessors(); pred_bb.addSuccessor(successor_bb); + successor_bb.addPredecessor(pred_bb); + } + + if (TRACE) out.println("Final result:"); + if (TRACE) out.println(caller.fullDump()); + if (TRACE) out.println(caller.getRegisterFactory().fullDump()); + + if (TRACE) out.println("Original code:"); + if (TRACE) out.println(CodeCache.getCode(callee.getMethod()).fullDump()); + if (TRACE) out.println(CodeCache.getCode(callee.getMethod()).getRegisterFactory().fullDump()); + } public static void inlineVirtualCallSiteWithTypeCheck(ControlFlowGraph caller, BasicBlock bb, Quad q, ControlFlowGraph callee, jq_Class type, boolean preserveCallSite) { *************** *** 710,718 **** * Get replacement method for @param originalMethod. * This method caches the result it returns. * */ ! // private static MethodOperand getFakeMethodOperand(jq_Method originalMethod) { ! // if(fakeMethodOperand.get(originalMethod) == null){ ! // jq_Method newMethod = null; ! // // jq_Class fakeString = getClassByName("MyMockLib.MyString"); // jq_Class fakeStringBuffer = getClassByName("MyMockLib.MyStringBuffer"); --- 1006,1014 ---- * Get replacement method for @param originalMethod. * This method caches the result it returns. + * @param pa2 * */ ! private static MethodOperand getFakeMethodOperand(jq_Method originalMethod, PA pa) { ! MethodOperand op = (MethodOperand) fakeMethodOperand.get(originalMethod); ! if(op == null){ // jq_Class fakeString = getClassByName("MyMockLib.MyString"); // jq_Class fakeStringBuffer = getClassByName("MyMockLib.MyStringBuffer"); *************** *** 730,784 **** // return null; // } ! // System.out.println("Replacing " + originalMethod + " with " + newMethod); ! // ! // // cache for later reuse ! // fakeMethodOperand.put(originalMethod, new MethodOperand(newMethod)); ! // } ! // ! // return (MethodOperand) fakeMethodOperand.get(originalMethod); ! // } ! // private static jq_Class getClassByName(String className) { ! // jq_Class theClass = (jq_Class)jq_Type.parseType(className); ! // Assert._assert(theClass != null, className + " is not available."); ! // theClass.prepare(); ! // ! // return theClass; ! // } ! // /** ! // * @param fakeString ! // * @param originalMethod ! // * @return replacement method or null ! // */ ! // private static jq_Method findReplacementMethod(jq_Class fakeString, jq_Method originalMethod) { ! // for(Iterator iter = fakeString.getMembers().iterator(); iter.hasNext();){ ! // Object o = iter.next(); ! // if(!(o instanceof jq_Method)) continue; ! // jq_Method m = (jq_Method) o; ! // ! // if(!m.getName().toString().equals(originalMethod.getName().toString())){ ! // continue; ! // } ! // ! // if(m.getParamTypes().length != originalMethod.getParamTypes().length){ ! // continue; ! // } ! // ! // boolean allMatch = true; ! // for(int i = 0; i < originalMethod.getParamTypes().length; i++){ ! // if(m.getParamTypes()[i] != originalMethod.getParamTypes()[i]){ ! // allMatch = false; ! // break; ! // } ! // } ! // if(!allMatch) { ! // continue; ! // } ! // ! // // done with the tests: m is good ! // return m; ! // } ! // ! // return null; ! // } } --- 1026,1090 ---- // return null; // } ! jq_Method newMethod = null; ! if (originalMethod instanceof jq_InstanceMethod) { ! newMethod = jq_FakeInstanceMethod.fakeMethod(originalMethod.getDeclaringClass(), originalMethod.getNameAndDesc()); ! } else { ! newMethod = jq_FakeStaticMethod.fakeMethod(originalMethod.getDeclaringClass(), originalMethod.getNameAndDesc()); ! } ! if(pa != null) { ! pa.addToFakeMethods(newMethod); ! } ! System.out.println("Replacing " + originalMethod + " with " + newMethod); ! ! // cache for later reuse ! op = new MethodOperand(newMethod); ! fakeMethodOperand.put(originalMethod, op); ! } ! ! return op; ! } ! private static jq_Class getClassByName(String className) { ! jq_Class theClass = (jq_Class)jq_Type.parseType(className); ! Assert._assert(theClass != null, className + " is not available."); ! theClass.prepare(); ! ! return theClass; ! } ! /** ! * @param fakeString ! * @param originalMethod ! * @return replacement method or null ! */ ! private static jq_Method findReplacementMethod(jq_Class fakeString, jq_Method originalMethod) { ! for(Iterator iter = fakeString.getMembers().iterator(); iter.hasNext();){ ! Object o = iter.next(); ! if(!(o instanceof jq_Method)) continue; ! jq_Method m = (jq_Method) o; ! ! if(!m.getName().toString().equals(originalMethod.getName().toString())){ ! continue; ! } ! ! if(m.getParamTypes().length != originalMethod.getParamTypes().length){ ! continue; ! } ! ! boolean allMatch = true; ! for(int i = 0; i < originalMethod.getParamTypes().length; i++){ ! if(m.getParamTypes()[i] != originalMethod.getParamTypes()[i]){ ! allMatch = false; ! break; ! } ! } ! if(!allMatch) { ! continue; ! } ! ! // done with the tests: m is good ! return m; ! } ! ! return null; ! } } |