use of org.apache.bcel.generic.InstructionHandle 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.InstructionHandle in project jop by jop-devel.
the class WCETAnalysis method runBlockingTimeAnalysis.
private void runBlockingTimeAnalysis(MethodInfo targetMethod) throws InvalidFlowFactException, LpSolveException, UnsupportedCacheModelException {
GlobalAnalysis an = new GlobalAnalysis(wcetTool, ipetConfig);
CacheCostCalculationMethod requestedCacheApprox = IPETConfig.getRequestedCacheApprox(config);
/* Find all synchronized segments */
Segment target = Segment.methodSegment(targetMethod, CallString.EMPTY, wcetTool, wcetTool.getCallstringLength(), wcetTool);
ArrayList<SynchronizedBlockResult> sBlocks = new ArrayList<SynchronizedBlockResult>();
for (ContextCFG ccfg : target.getCallGraphNodes()) {
for (CFGNode cfgNode : ccfg.getCfg().vertexSet()) {
if (cfgNode.getBasicBlock() == null)
continue;
for (InstructionHandle ih : cfgNode.getBasicBlock().getInstructions()) {
if (ih.getInstruction() instanceof MONITORENTER) {
/* compute synchronized block WCET */
Segment synchronizedSegment = Segment.synchronizedSegment(ccfg, cfgNode, ih, wcetTool, wcetTool.getCallstringLength(), wcetTool);
wcet = an.computeWCET(targetMethod.getShortName(), synchronizedSegment, requestedCacheApprox);
sBlocks.add(new SynchronizedBlockResult(sBlocks.size(), synchronizedSegment, cfgNode, ih, wcet));
}
}
}
}
/* check nested synchronized blocks */
for (SynchronizedBlockResult sBlock : sBlocks) {
for (SynchronizedBlockResult otherBlock : sBlocks) {
if (sBlock == otherBlock)
continue;
for (SuperGraphEdge entryEdge : otherBlock.synchronizedSegment.getEntryEdges()) {
if (sBlock.synchronizedSegment.includesEdge(entryEdge)) {
sBlock.nested.add(otherBlock);
break;
}
}
}
}
System.out.println("=== Synchronized Blocks ===");
for (SynchronizedBlockResult sBlock : sBlocks) {
sBlock.dump(System.out);
}
}
use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class PeepholeOptimizer method optimizeBoolExpressions.
/**
* Optimize some boolean expressions.
* <p>
* This code is taken directly from the BCEL manual, chapter 3.3.8.
* </p>
*
* @param il the instruction list to optimize.
*/
private void optimizeBoolExpressions(InstructionList il) {
InstructionFinder f = new InstructionFinder(il);
String pat = "IfInstruction ICONST_0 GOTO ICONST_1 NOP(IFEQ|IFNE)";
CodeConstraint constraint = new CodeConstraint() {
@Override
public boolean checkCode(InstructionHandle[] match) {
IfInstruction if1 = (IfInstruction) match[0].getInstruction();
GOTO g = (GOTO) match[2].getInstruction();
return (if1.getTarget() == match[3]) && (g.getTarget() == match[4]);
}
};
for (Iterator e = f.search(pat, constraint); e.hasNext(); ) {
InstructionHandle[] match = (InstructionHandle[]) e.next();
IfInstruction if1 = (IfInstruction) match[0].getInstruction();
IfInstruction if2 = (IfInstruction) match[5].getInstruction();
// Update target
if1.setTarget(if2.getTarget());
try {
il.delete(match[1], match[5]);
} catch (TargetLostException ex) {
for (InstructionHandle target : ex.getTargets()) {
for (InstructionTargeter t : target.getTargeters()) {
t.updateTarget(target, match[0]);
}
}
}
matchBoolExpressions++;
}
}
use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class MethodCacheAnalysis method getMissCost.
/**
* Get miss cost for an edge accessing the method cache
* @param accessEdge either a SuperInvoke or SuperReturn edge, or an entry edge of the segment analyzed
* @return maximum miss penalty (in cycles)
*/
private long getMissCost(SuperGraphEdge accessEdge) {
SuperGraphNode accessed = accessEdge.getTarget();
ControlFlowGraph cfg = accessed.getCfg();
if (accessEdge instanceof SuperReturnEdge) {
/* return edge: return cost */
Type returnType = accessEdge.getSource().getCfg().getMethodInfo().getType();
return methodCache.getMissPenaltyOnReturn(cfg.getNumberOfWords(), returnType);
} else if (accessEdge instanceof SuperInvokeEdge) {
InstructionHandle invokeIns = ((SuperInvokeEdge) accessEdge).getInvokeNode().getInvokeSite().getInstructionHandle();
return methodCache.getMissPenaltyOnInvoke(cfg.getNumberOfWords(), invokeIns.getInstruction());
} else {
/* entry edge of the segment: can be invoke or return cost */
return methodCache.getMissPenalty(cfg.getNumberOfWords(), false);
}
}
use of org.apache.bcel.generic.InstructionHandle 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;
}
Aggregations