use of org.hotswap.agent.javassist.bytecode.CodeIterator in project HotswapAgent by HotswapProjects.
the class SubroutineScanner method scan.
public Subroutine[] scan(MethodInfo method) throws BadBytecode {
CodeAttribute code = method.getCodeAttribute();
CodeIterator iter = code.iterator();
subroutines = new Subroutine[code.getCodeLength()];
subTable.clear();
done.clear();
scan(0, iter, null);
ExceptionTable exceptions = code.getExceptionTable();
for (int i = 0; i < exceptions.size(); i++) {
int handler = exceptions.handlerPc(i);
// If an exception is thrown in subroutine, the handler
// is part of the same subroutine.
scan(handler, iter, subroutines[exceptions.startPc(i)]);
}
return subroutines;
}
use of org.hotswap.agent.javassist.bytecode.CodeIterator in project HotswapAgent by HotswapProjects.
the class Analyzer method mergeRet.
private void mergeRet(IntQueue queue, CodeIterator iter, int pos, Frame frame, Subroutine subroutine) throws BadBytecode {
if (subroutine == null)
throw new BadBytecode("Ret on no subroutine! [pos = " + pos + "]");
Iterator callerIter = subroutine.callers().iterator();
while (callerIter.hasNext()) {
int caller = ((Integer) callerIter.next()).intValue();
int returnLoc = getNext(iter, caller, pos);
boolean changed = false;
Frame old = frames[returnLoc];
if (old == null) {
old = frames[returnLoc] = frame.copyStack();
changed = true;
} else {
changed = old.mergeStack(frame);
}
for (Iterator i = subroutine.accessed().iterator(); i.hasNext(); ) {
int index = ((Integer) i.next()).intValue();
Type oldType = old.getLocal(index);
Type newType = frame.getLocal(index);
if (oldType != newType) {
old.setLocal(index, newType);
changed = true;
}
}
if (!old.isRetMerged()) {
old.setRetMerged(true);
changed = true;
}
if (changed && old.isJsrMerged())
queue.add(returnLoc);
}
}
use of org.hotswap.agent.javassist.bytecode.CodeIterator in project HotswapAgent by HotswapProjects.
the class FieldInitLink method modifyClassConstructor.
private void modifyClassConstructor(ClassFile cf, Bytecode code, int stacksize, int localsize) throws CannotCompileException {
MethodInfo m = cf.getStaticInitializer();
if (m == null) {
code.add(Bytecode.RETURN);
code.setMaxStack(stacksize);
code.setMaxLocals(localsize);
m = new MethodInfo(cf.getConstPool(), "<clinit>", "()V");
m.setAccessFlags(AccessFlag.STATIC);
m.setCodeAttribute(code.toCodeAttribute());
cf.addMethod(m);
CtMember.Cache cache = hasMemberCache();
if (cache != null)
cache.addConstructor(new CtConstructor(m, this));
} else {
CodeAttribute codeAttr = m.getCodeAttribute();
if (codeAttr == null)
throw new CannotCompileException("empty <clinit>");
try {
CodeIterator it = codeAttr.iterator();
int pos = it.insertEx(code.get());
it.insert(code.getExceptionTable(), pos);
int maxstack = codeAttr.getMaxStack();
if (maxstack < stacksize)
codeAttr.setMaxStack(stacksize);
int maxlocals = codeAttr.getMaxLocals();
if (maxlocals < localsize)
codeAttr.setMaxLocals(localsize);
} catch (BadBytecode e) {
throw new CannotCompileException(e);
}
}
try {
m.rebuildStackMapIf6(classPool, cf);
} catch (BadBytecode e) {
throw new CannotCompileException(e);
}
}
use of org.hotswap.agent.javassist.bytecode.CodeIterator in project HotswapAgent by HotswapProjects.
the class TransformAccessArrayField method initialize.
public void initialize(ConstPool cp, CtClass clazz, MethodInfo minfo) throws CannotCompileException {
/*
* This transformer must be isolated from other transformers, since some
* of them affect the local variable and stack maximums without updating
* the code attribute to reflect the changes. This screws up the
* data-flow analyzer, since it relies on consistent code state. Even
* if the attribute values were updated correctly, we would have to
* detect it, and redo analysis, which is not cheap. Instead, we are
* better off doing all changes in initialize() before everyone else has
* a chance to muck things up.
*/
CodeIterator iterator = minfo.getCodeAttribute().iterator();
while (iterator.hasNext()) {
try {
int pos = iterator.next();
int c = iterator.byteAt(pos);
if (c == AALOAD)
initFrames(clazz, minfo);
if (c == AALOAD || c == BALOAD || c == CALOAD || c == DALOAD || c == FALOAD || c == IALOAD || c == LALOAD || c == SALOAD) {
pos = replace(cp, iterator, pos, c, getLoadReplacementSignature(c));
} else if (c == AASTORE || c == BASTORE || c == CASTORE || c == DASTORE || c == FASTORE || c == IASTORE || c == LASTORE || c == SASTORE) {
pos = replace(cp, iterator, pos, c, getStoreReplacementSignature(c));
}
} catch (Exception e) {
throw new CannotCompileException(e);
}
}
}
use of org.hotswap.agent.javassist.bytecode.CodeIterator in project HotswapAgent by HotswapProjects.
the class Analyzer method analyze.
/**
* Performs data-flow analysis on a method and returns an array, indexed by
* instruction position, containing the starting frame state of all reachable
* instructions. Non-reachable code, and illegal code offsets are represented
* as a null in the frame state array. This can be used to detect dead code.
*
* If the method does not contain code (it is either native or abstract), null
* is returned.
*
* @param clazz the declaring class of the method
* @param method the method to analyze
* @return an array, indexed by instruction position, of the starting frame state,
* or null if this method doesn't have code
* @throws BadBytecode if the bytecode does not comply with the JVM specification
*/
public Frame[] analyze(CtClass clazz, MethodInfo method) throws BadBytecode {
this.clazz = clazz;
CodeAttribute codeAttribute = method.getCodeAttribute();
// Native or Abstract
if (codeAttribute == null)
return null;
int maxLocals = codeAttribute.getMaxLocals();
int maxStack = codeAttribute.getMaxStack();
int codeLength = codeAttribute.getCodeLength();
CodeIterator iter = codeAttribute.iterator();
IntQueue queue = new IntQueue();
exceptions = buildExceptionInfo(method);
subroutines = scanner.scan(method);
Executor executor = new Executor(clazz.getClassPool(), method.getConstPool());
frames = new Frame[codeLength];
frames[iter.lookAhead()] = firstFrame(method, maxLocals, maxStack);
queue.add(iter.next());
while (!queue.isEmpty()) {
analyzeNextEntry(method, iter, queue, executor);
}
return frames;
}
Aggregations