use of org.apache.bcel.generic.FieldInstruction 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;
}
use of org.apache.bcel.generic.FieldInstruction in project jop by jop-devel.
the class ObjectCacheAnalysis method extractAccessesAndCosts.
/** Traverse vertex set.
* <p>Add vertex to access set of referenced addresses
* For references whose type cannot be fully resolved, add a
* cost of 1.</p>
* <p>FIXME: We should deal with subtyping (or better use storage based alias-analysis)</p>
*
* @param nodes
* @param usedRefs the results of the local points-to analysis, or {@code null} for always miss costs
* @param costModel
*/
private AccessCostInfo extractAccessesAndCosts(Iterable<SuperGraphNode> nodes, LocalPointsToResult usedRefs, ObjectCacheCostModel costModel) {
AccessCostInfo aci = new AccessCostInfo();
for (SuperGraphNode node : nodes) {
/* Compute cost for basic block */
BasicBlock bb = node.getCFGNode().getBasicBlock();
if (bb == null)
continue;
long bypassCost = 0;
long alwaysMissCost = 0;
CallString cs = node.getContextCFG().getCallString();
for (InstructionHandle ih : bb.getInstructions()) {
String handleType = getHandleType(project, node.getCfg(), ih);
if (handleType == null)
continue;
/* No getfield/handle access */
int fieldIndex = getFieldIndex(project, node.getCfg(), ih);
int blockIndex = getBlockIndex(fieldIndex);
if (fieldIndex > this.maxCachedFieldIndex) {
bypassCost += costModel.getFieldAccessCostBypass();
continue;
}
BoundedSet<SymbolicAddress> refs = null;
if (usedRefs != null) {
if (!usedRefs.containsKey(ih)) {
usedRefs = null;
WCETTool.logger.error("No DFA results for: " + ih.getInstruction() + " with field " + ((FieldInstruction) ih.getInstruction()).getFieldName(bb.cpg()));
} else {
refs = usedRefs.get(ih, cs);
if (refs.isSaturated())
refs = null;
}
}
if (refs == null) {
alwaysMissCost += costModel.getReplaceLineCost() + costModel.getLoadCacheBlockCost();
} else {
for (SymbolicAddress ref : refs.getSet()) {
aci.addRefAccess(ref, node);
aci.addBlockAccess(ref.accessArray(blockIndex), node);
// Handle getfield_long / getfield_double
if (getCachedType(project, node.getCfg(), ih) == Type.LONG || getCachedType(project, node.getCfg(), ih) == Type.DOUBLE) {
if (blockIndex + 1 > this.maxCachedFieldIndex) {
bypassCost += costModel.getFieldAccessCostBypass();
} else {
aci.addBlockAccess(ref.accessArray(blockIndex + 1), node);
}
}
}
}
}
aci.putBypassCost(node, bypassCost);
aci.putStaticCost(node, bypassCost + alwaysMissCost);
}
return aci;
}
use of org.apache.bcel.generic.FieldInstruction in project jop by jop-devel.
the class ObjectCacheAnalysis method getFieldIndex.
/**
* @return the index of the field accessed by the instruction, or 0 if the instruction
* does not access a field
*/
private static int getFieldIndex(WCETTool p, ControlFlowGraph cfg, InstructionHandle ih) {
ConstantPoolGen constPool = cfg.getMethodInfo().getConstantPoolGen();
Instruction instr = ih.getInstruction();
if (instr instanceof FieldInstruction) {
FieldInstruction fieldInstr = (FieldInstruction) instr;
ReferenceType refType = fieldInstr.getReferenceType(constPool);
if (!(refType instanceof ObjectType)) {
throw new RuntimeException("getFieldIndex(): Unsupported object kind: " + refType.getClass());
}
ObjectType objType = (ObjectType) refType;
String klassName = objType.getClassName();
String fieldName = fieldInstr.getFieldName(constPool);
String fieldSig = fieldInstr.getSignature(constPool);
return p.getLinkerInfo().getFieldIndex(klassName, fieldName + fieldSig);
} else {
return 0;
}
}
Aggregations