use of org.apache.bcel.generic.InvokeInstruction in project jop by jop-devel.
the class InvokeSite method getInvokeeRef.
/**
* Get the MethodRef to the referenced method. If the instruction is handled in java, return a reference
* to the method which implements the instruction.
* <p>
* The MethodRef refers to the actual reference. {@link MethodRef#getMethodInfo()} resolves the actual
* MethodInfo, which might be defined in a super class of the referenced method, if the method is inherited.
* For invokespecial, the implementing method might even be defined in a subclass of the referenced method,
* if resolveSuper is set to false, see {@link #isInvokeSuper()} for details.
* </p>
* <p>To find all possible implementations if the invocation is a virtual invoke (see {@link #isVirtual()}),
* use {@link AppInfo#findImplementations(InvokeSite)}.</p>
*
* @see #isInvokeSuper()
* @see AppInfo#findImplementations(InvokeSite)
* @param resolveSuper if true, try to resolve the super method reference (see {@link #isInvokeSuper()}),
* else return a reference to the method as it is defined by the instruction.
* @return a method reference to the invokee method.
*/
public MethodRef getInvokeeRef(boolean resolveSuper) {
Instruction instr = instruction.getInstruction();
AppInfo appInfo = AppInfo.getSingleton();
if (instr instanceof InvokeInstruction) {
MethodRef ref = getReferencedMethod(invoker, (InvokeInstruction) instr);
// need to check isInvokeSpecial here, since it is not checked by isSuperMethod!
if (resolveSuper && isInvokeSpecial() && isSuperMethod(ref)) {
ref = resolveInvokeSuper(ref);
}
return ref;
}
if (appInfo.getProcessorModel().isImplementedInJava(invoker, instr)) {
return appInfo.getProcessorModel().getJavaImplementation(appInfo, invoker, instr).getMethodRef();
}
throw new JavaClassFormatError("InvokeSite handle does not refer to an invoke instruction: " + toString());
}
use of org.apache.bcel.generic.InvokeInstruction in project jop by jop-devel.
the class BasicBlock method getTheInvokeInstruction.
/**
* Get the invoke instruction of the basic block (which must be
* the only instruction in the basic block)
*
* @return the invoke instruction, or <code>null</code>, if the basic block doesn't
* contain an invoke instruction or if it is a special invoke.
* @throws ControlFlowGraph.ControlFlowError
* if there is more than one invoke instruction in the block.
* @see ProcessorModel#isSpecialInvoke(MethodInfo, Instruction)
*/
public InstructionHandle getTheInvokeInstruction() {
InstructionHandle theInvInstr = null;
for (InstructionHandle ih : this.instructions) {
if (!(ih.getInstruction() instanceof InvokeInstruction))
continue;
InvokeInstruction inv = (InvokeInstruction) ih.getInstruction();
if (this.getAppInfo().getProcessorModel().isSpecialInvoke(methodCode.getMethodInfo(), inv)) {
continue;
}
if (theInvInstr != null) {
throw new ControlFlowGraph.ControlFlowError("More than one invoke instruction in a basic block");
}
theInvInstr = ih;
}
return theInvInstr;
}
use of org.apache.bcel.generic.InvokeInstruction in project jop by jop-devel.
the class ReplaceNativeAndCPIdx method replace.
private Method replace(Method method) {
MethodGen mg = new MethodGen(method, clazz.getClassName(), cpoolgen);
InstructionList il = mg.getInstructionList();
InstructionFinder f = new InstructionFinder(il);
String methodId = method.getName() + method.getSignature();
OldMethodInfo mi = getCli().getMethodInfo(methodId);
// find invokes first and replace call to Native by
// JOP native instructions.
String invokeStr = "InvokeInstruction";
for (Iterator i = f.search(invokeStr); i.hasNext(); ) {
InstructionHandle[] match = (InstructionHandle[]) i.next();
InstructionHandle first = match[0];
InvokeInstruction ii = (InvokeInstruction) first.getInstruction();
if (ii.getClassName(cpoolgen).equals(JOPizer.nativeClass)) {
short opid = (short) JopInstr.getNative(ii.getMethodName(cpoolgen));
if (opid == -1) {
System.err.println(method.getName() + ": cannot locate " + ii.getMethodName(cpoolgen) + ". Replacing with NOP.");
first.setInstruction(new NOP());
} else {
first.setInstruction(new NativeInstruction(opid, (short) 1));
((JOPizer) ai).outTxt.println("\t" + first.getPosition());
// then we remove pc+2 and pc+1 from the MGCI info
if (JOPizer.dumpMgci) {
il.setPositions();
int pc = first.getPosition();
// important: take the high one first
GCRTMethodInfo.removePC(pc + 2, mi);
GCRTMethodInfo.removePC(pc + 1, mi);
}
}
}
if (ii instanceof INVOKESPECIAL) {
// not an initializer
if (!ii.getMethodName(cpoolgen).equals("<init>")) {
// check if this is a super invoke
// TODO this is just a hack, use InvokeSite.isInvokeSuper() when this is ported to the new framework!
boolean isSuper = false;
String declaredType = ii.getClassName(cpoolgen);
JopClassInfo cls = getCli();
OldClassInfo superClass = cls.superClass;
while (superClass != null) {
if (superClass.clazz.getClassName().equals(declaredType)) {
isSuper = true;
break;
}
if ("java.lang.Object".equals(superClass.clazz.getClassName())) {
break;
}
superClass = superClass.superClass;
}
if (isSuper) {
Integer idx = ii.getIndex();
int new_index = getCli().cpoolUsed.indexOf(idx) + 1;
first.setInstruction(new JOPSYS_INVOKESUPER((short) new_index));
// System.err.println("invokesuper "+ii.getClassName(cpoolgen)+"."+ii.getMethodName(cpoolgen));
}
}
}
}
if (JOPizer.CACHE_INVAL) {
f = new InstructionFinder(il);
// find volatile reads and insert cache invalidation bytecode
String fieldInstr = "GETFIELD|GETSTATIC|PUTFIELD|PUTSTATIC";
for (Iterator i = f.search(fieldInstr); i.hasNext(); ) {
InstructionHandle[] match = (InstructionHandle[]) i.next();
InstructionHandle ih = match[0];
FieldInstruction fi = (FieldInstruction) ih.getInstruction();
JavaClass jc = JOPizer.jz.cliMap.get(fi.getClassName(cpoolgen)).clazz;
Field field = null;
while (field == null) {
Field[] fields = jc.getFields();
for (int k = 0; k < fields.length; k++) {
if (fields[k].getName().equals(fi.getFieldName(cpoolgen))) {
field = fields[k];
break;
}
}
if (field == null) {
try {
jc = jc.getSuperClass();
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new Error();
}
}
}
if (field.isVolatile()) {
if (field.getType().getSize() < 2) {
if (fi instanceof GETFIELD || fi instanceof GETSTATIC) {
ih.setInstruction(new InvalidateInstruction());
ih = il.append(ih, fi);
}
} else {
// this only works because we do not throw a
// NullPointerException for monitorenter/-exit!
ih.setInstruction(new ACONST_NULL());
ih = il.append(ih, new MONITORENTER());
ih = il.append(ih, fi);
ih = il.append(ih, new ACONST_NULL());
ih = il.append(ih, new MONITOREXIT());
}
}
}
}
f = new InstructionFinder(il);
// find instructions that access the constant pool
// and replace the index by the new value from ClassInfo
String cpInstr = "CPInstruction";
for (Iterator it = f.search(cpInstr); it.hasNext(); ) {
InstructionHandle[] match = (InstructionHandle[]) it.next();
InstructionHandle ih = match[0];
CPInstruction cpii = (CPInstruction) ih.getInstruction();
int index = cpii.getIndex();
// we have to grab the information before we change
// the CP index.
FieldInstruction fi = null;
Type ft = null;
if (cpii instanceof FieldInstruction) {
fi = (FieldInstruction) ih.getInstruction();
ft = fi.getFieldType(cpoolgen);
}
Integer idx = new Integer(index);
// pos is the new position in the reduced constant pool
// idx is the position in the 'original' unresolved cpool
int pos = getCli().cpoolUsed.indexOf(idx);
int new_index = pos + 1;
// and putfield and by address for getstatic and putstatic
if (cpii instanceof GETFIELD || cpii instanceof PUTFIELD || cpii instanceof GETSTATIC || cpii instanceof PUTSTATIC) {
// we use the offset instead of the CP index
new_index = getFieldOffset(cp, index);
} else {
if (pos == -1) {
System.out.println("Error: constant " + index + " " + cpoolgen.getConstant(index) + " not found");
System.out.println("new cpool: " + getCli().cpoolUsed);
System.out.println("original cpool: " + cpoolgen);
System.exit(-1);
}
}
// set new index, position starts at
// 1 as cp points to the length of the pool
cpii.setIndex(new_index);
if (cpii instanceof FieldInstruction) {
boolean isRef = ft instanceof ReferenceType;
boolean isLong = ft == BasicType.LONG || ft == BasicType.DOUBLE;
if (fi instanceof GETSTATIC) {
if (isRef) {
ih.setInstruction(new GETSTATIC_REF((short) new_index));
} else if (isLong) {
ih.setInstruction(new GETSTATIC_LONG((short) new_index));
}
} else if (fi instanceof PUTSTATIC) {
if (isRef) {
if (!com.jopdesign.build.JOPizer.USE_RTTM) {
ih.setInstruction(new PUTSTATIC_REF((short) new_index));
}
} else if (isLong) {
ih.setInstruction(new PUTSTATIC_LONG((short) new_index));
}
} else if (fi instanceof GETFIELD) {
if (isRef) {
ih.setInstruction(new GETFIELD_REF((short) new_index));
} else if (isLong) {
ih.setInstruction(new GETFIELD_LONG((short) new_index));
}
} else if (fi instanceof PUTFIELD) {
if (isRef) {
if (!com.jopdesign.build.JOPizer.USE_RTTM) {
ih.setInstruction(new PUTFIELD_REF((short) new_index));
}
} else if (isLong) {
ih.setInstruction(new PUTFIELD_LONG((short) new_index));
}
}
}
}
Method m = mg.getMethod();
il.dispose();
return m;
}
use of org.apache.bcel.generic.InvokeInstruction in project jop by jop-devel.
the class SimpleInliner method analyzeInvokee.
/**
* @param cs the callstring from the invoker to the invoke to inline (if recursive). Used to check DFA results.
* @param invokee the invoked method to analyze
* @param inlineData the map to populate with the parameters and the instructions to inline.
* @return true if inlining is possible
*/
private boolean analyzeInvokee(CallString cs, MethodInfo invokee, InlineData inlineData) {
// we allow loading of parameters, loading of constants, some instruction, and a return
ValueMapAnalysis values = new ValueMapAnalysis(invokee);
values.loadParameters();
InstructionList il = invokee.getCode().getInstructionList(true, false);
InstructionHandle ih = il.getStart();
// we should at least have a return instruction, so even for empty methods we should fall through
// generate the parameter mapping
int count = 0;
while (true) {
Instruction instruction = ih.getInstruction();
if (instruction instanceof PushInstruction || instruction instanceof NOP) {
values.transfer(instruction);
ih = ih.getNext();
count++;
} else {
break;
}
}
// store the mapping
for (ValueInfo value : values.getValueTable().getStack()) {
inlineData.addParam(value);
}
inlineData.setInlineStart(count);
// if we do not need an NP check, we can also inline code which does not throw an exception in the same way
boolean needsNPCheck = helper.needsNullpointerCheck(cs, invokee, false);
boolean hasNPCheck = false;
// we allow up to 5 instructions and one return before assuming that the resulting code will be too large
for (int i = 0; i < 6; i++) {
// now lets see what we have here as non-push instructions
Instruction instruction = ih.getInstruction();
if (instruction instanceof InvokeInstruction) {
if (inlineData.getInvokeSite() != null) {
// only inline at most one invoke
return false;
}
InvokeSite is = invokee.getCode().getInvokeSite(ih);
inlineData.setInvokeSite(is);
hasNPCheck |= !is.isInvokeStatic();
} else if (instruction instanceof FieldInstruction) {
if (instruction instanceof GETFIELD) {
hasNPCheck |= values.getValueTable().top().isThisReference();
}
if (instruction instanceof PUTFIELD) {
int down = values.getValueTable().top().isContinued() ? 2 : 1;
hasNPCheck |= values.getValueTable().top(down).isThisReference();
}
} else if (instruction instanceof ArithmeticInstruction || instruction instanceof ConversionInstruction || instruction instanceof StackInstruction || instruction instanceof LDC || instruction instanceof LDC2_W || instruction instanceof ARRAYLENGTH || instruction instanceof CHECKCAST || instruction instanceof NOP) {
// nothing to do, just copy them
} else if (instruction instanceof ReturnInstruction) {
if (needsNPCheck && !hasNPCheck) {
// We were nearly finished.. but NP check test failed
this.requiresNPCheck++;
if (logger.isTraceEnabled()) {
logger.trace("Not inlining " + invokee + " because it requires a NP check.");
}
return false;
}
// else we need to add pop instructions
if (instruction instanceof RETURN) {
// we do not return anything, so we must empty the stack
while (values.getValueTable().getStackSize() > 0) {
Instruction pop;
if (values.getValueTable().top().isContinued()) {
pop = new POP2();
} else {
pop = new POP();
}
inlineData.addEpilogue(pop);
values.transfer(pop);
}
return true;
} else {
Type type = ((ReturnInstruction) instruction).getType();
// javac anyway)
return values.getValueTable().getStackSize() == type.getSize();
}
} else {
// if we encounter an instruction which we do not handle, we do not inline
unhandledInstructions++;
if (logger.isTraceEnabled()) {
logger.trace("Not inlining " + invokee + " because of unhandled instruction " + instruction.toString(invokee.getClassInfo().getConstantPoolGen().getConstantPool()));
}
return false;
}
// update the stack map since we need it to handle RETURN
values.transfer(instruction);
ih = ih.getNext();
}
// too many instructions, do not inline
return false;
}
Aggregations