/** * Count stores, loads, and increments of local variables in method whose * CFG is given. * * @param localStoreCount * counts of local stores (indexed by local) * @param localLoadCount * counts of local loads (indexed by local) * @param localIncrementCount * counts of local increments (indexed by local) * @param cfg * control flow graph (CFG) of method */ private void countLocalStoresLoadsAndIncrements(int[] localStoreCount, int[] localLoadCount, int[] localIncrementCount, CFG cfg) { for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) { Location location = i.next(); if (location.getBasicBlock().isExceptionHandler()) continue; boolean isStore = isStore(location); boolean isLoad = isLoad(location); if (!isStore && !isLoad) continue; IndexedInstruction ins = (IndexedInstruction) location.getHandle().getInstruction(); int local = ins.getIndex(); if (ins instanceof IINC) { localStoreCount[local]++; localLoadCount[local]++; localIncrementCount[local]++; } else if (isStore) localStoreCount[local]++; else localLoadCount[local]++; } }
@Override public void visitIINC(IINC obj) { if (obj.getIncrement() == 0) { // A no-op. return; } // IINC is a special case because its input and output are not on the // stack. // However, we still want to use the value number cache to ensure that // this operation is modeled consistently. (If we do nothing, we miss // the fact that the referenced local is modified.) int local = obj.getIndex(); ValueNumber[] input = new ValueNumber[] { getFrame().getValue(local) }; ValueNumberCache.Entry entry = new ValueNumberCache.Entry(handle, input); ValueNumber[] output = cache.lookupOutputValues(entry); if (output == null) { output = new ValueNumber[] { factory.createFreshValue() }; cache.addOutputValues(entry, output); } getFrame().setValue(local, output[0]); }
void removeUnusedLocals(Method mOrig, MethodGen m) { InstructionList il = m.getInstructionList(); InstructionHandle[] ins = il.getInstructionHandles(); for (int i = 0; i < ins.length; i++) { Instruction in = ins[i].getInstruction(); if (in instanceof LocalVariableInstruction) { LocalVariableInstruction curr = (LocalVariableInstruction) in; if (mtab.getLocal(m, curr, ins[i].getPosition()) != null && curr.getIndex() < m.getMaxLocals() - 5 && !mtab.isLocalUsedInInlet(mOrig, curr.getIndex())) { if (curr instanceof IINC) { ins[i].setInstruction(new NOP()); } else if (curr instanceof LSTORE || curr instanceof DSTORE) { ins[i].setInstruction(new POP2()); } else if (curr instanceof StoreInstruction) { ins[i].setInstruction(new POP()); } else if (curr instanceof ALOAD) { ins[i].setInstruction(new ACONST_NULL()); } else if (curr instanceof FLOAD) { ins[i].setInstruction(new FCONST((float) 0.0)); } else if (curr instanceof ILOAD) { ins[i].setInstruction(new ICONST(0)); } else if (curr instanceof DLOAD) { ins[i].setInstruction(new DCONST(0.0)); } else if (curr instanceof LLOAD) { ins[i].setInstruction(new LCONST(0L)); } else { System.out.println("unhandled ins in " + "removeUnusedLocals: " + curr); System.exit(1); } } } } }
@SuppressWarnings("unused") // Called using reflection private Instruction createInstructionIinc(Element inst) { int index = Integer.parseInt(inst.getAttributeValue("index")); int incr = Integer.parseInt(inst.getAttributeValue("incr")); return new IINC(index, incr); }
@Override public void visitIINC(IINC obj) { // System.out.println("before iinc: " + getFrame()); int v = obj.getIndex(); int amount = obj.getIncrement(); ConstantFrame f = getFrame(); Constant c = f.getValue(v); if (c.isConstantInteger()) f.setValue(v, new Constant(c.getConstantInt() + amount)); else f.setValue(v, Constant.NOT_CONSTANT); // System.out.println("after iinc: " + getFrame()); }
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitIINC(IINC o){ int idx = o.getIndex(); if (idx < 0){ constraintViolated(o, "Index '"+idx+"' must be non-negative."); } else{ int maxminus1 = max_locals()-1; if (idx > maxminus1){ constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); } } }
public void visitLocalVariableInstruction( LocalVariableInstruction i ) { short opcode = i.getOpcode(); Type type = i.getType(_cp); if (opcode == Constants.IINC) { _out.println("il.append(new IINC(" + i.getIndex() + ", " + ((IINC) i).getIncrement() + "));"); } else { String kind = (opcode < Constants.ISTORE) ? "Load" : "Store"; _out.println("il.append(_factory.create" + kind + "(" + BCELifier.printType(type) + ", " + i.getIndex() + "));"); } }
private boolean isStore(Location location) { Instruction ins = location.getHandle().getInstruction(); return (ins instanceof StoreInstruction) || (ins instanceof IINC); }
private boolean isLoad(Location location) { Instruction ins = location.getHandle().getInstruction(); return (ins instanceof LoadInstruction) || (ins instanceof IINC); }
private void emitIINC(Element xml_inst, IINC inst) { xml_inst.setAttribute("index", java.lang.String.valueOf(inst.getIndex())); xml_inst.setAttribute("incr", java.lang.String.valueOf(inst.getIncrement())); }
/** * Is instruction at given location a store? * * @param location * the location * @return true if instruction at given location is a store, false if not */ private boolean isStore(Location location) { Instruction ins = location.getHandle().getInstruction(); return (ins instanceof StoreInstruction) || (ins instanceof IINC); }
/** * Is instruction at given location a load? * * @param location * the location * @return true if instruction at given location is a load, false if not */ private boolean isLoad(Location location) { Instruction ins = location.getHandle().getInstruction(); return (ins instanceof LoadInstruction) || (ins instanceof IINC); }