Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ public Frame<V>[] analyze(final String owner, final MethodNode method) throws An
if (newControlFlowExceptionEdge(insnIndex, tryCatchBlock)) {
Frame<V> handler = newFrame(oldFrame);
handler.clearStack();
handler.push(interpreter.newValue(catchType));
handler.push(interpreter.newExceptionValue(tryCatchBlock, handler, catchType));
merge(insnList.indexOf(tryCatchBlock.handler), handler, subroutine);
}
}
Expand Down Expand Up @@ -379,24 +379,30 @@ private void findSubroutine(
* @param method the method to be analyzed.
* @return the initial execution stack frame of the 'method'.
*/

private Frame<V> computeInitialFrame(final String owner, final MethodNode method) {
Frame<V> frame = newFrame(method.maxLocals, method.maxStack);
int currentLocal = 0;
if ((method.access & ACC_STATIC) == 0) {
boolean isInstanceMethod = (method.access & ACC_STATIC) == 0;
if (isInstanceMethod) {
Type ownerType = Type.getObjectType(owner);
frame.setLocal(currentLocal++, interpreter.newValue(ownerType));
frame.setLocal(currentLocal, interpreter.newParameterValue(isInstanceMethod, currentLocal, ownerType));
currentLocal++;
}
Type[] argumentTypes = Type.getArgumentTypes(method.desc);
for (int i = 0; i < argumentTypes.length; ++i) {
frame.setLocal(currentLocal++, interpreter.newValue(argumentTypes[i]));
frame.setLocal(currentLocal, interpreter.newParameterValue(isInstanceMethod, currentLocal, argumentTypes[i]));
currentLocal++;
if (argumentTypes[i].getSize() == 2) {
frame.setLocal(currentLocal++, interpreter.newValue(null));
frame.setLocal(currentLocal, interpreter.newEmptyValueAfterSize2Local(currentLocal));
currentLocal++;
}
}
while (currentLocal < method.maxLocals) {
frame.setLocal(currentLocal++, interpreter.newValue(null));
frame.setLocal(currentLocal, interpreter.newEmptyNonParameterLocalValue(currentLocal));
currentLocal++;
}
frame.setReturn(interpreter.newValue(Type.getReturnType(method.desc)));
frame.setReturn(interpreter.newReturnTypeValue(Type.getReturnType(method.desc)));
return frame;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,12 +265,12 @@ public void execute(final AbstractInsnNode insn, final Interpreter<V> interprete
var = ((VarInsnNode) insn).var;
setLocal(var, value1);
if (value1.getSize() == 2) {
setLocal(var + 1, interpreter.newValue(null));
setLocal(var + 1, interpreter.newEmptyValueAfterSize2Local(var + 1));
}
if (var > 0) {
Value local = getLocal(var - 1);
if (local != null && local.getSize() == 2) {
setLocal(var - 1, interpreter.newValue(null));
setLocal(var - 1, interpreter.newEmptyValueForPreviousSize2Local(var - 1));
}
}
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.TryCatchBlockNode;

/**
* A semantic bytecode interpreter. More precisely, this interpreter only manages the computation of
Expand Down Expand Up @@ -68,6 +69,14 @@ protected Interpreter(final int api) {
* <p>Called for method parameters (including <code>this</code>), exception handler variable and
* with <code>null</code> type for variables reserved by long and double types.
*
* An interpreter may choose to implement one or more of {@link Interpreter#newReturnTypeValue(Type)},
* {@link Interpreter#newParameterValue(boolean, int, Type)},
* {@link Interpreter#newEmptyNonParameterLocalValue(int)},
* {@link Interpreter#newEmptyValueAfterSize2Local(int)},
* {@link Interpreter#newEmptyValueForPreviousSize2Local(int)},
* {@link Interpreter#newExceptionValue(TryCatchBlockNode, Frame, Type)} to distinguish
* different types of new value.
*
* @param type a primitive or reference type, or <tt>null</tt> to represent an uninitialized
* value.
* @return a value that represents the given type. The size of the returned value must be equal to
Expand All @@ -89,6 +98,108 @@ protected Interpreter(final int api) {
*/
public abstract V newOperation(AbstractInsnNode insn) throws AnalyzerException;


/**
* Called by the analyzer for initializing the return type value of a frame.
*
* By default, calls <code>newValue(type)</code>.
*
* @param type a primitive or reference type, or <tt>null</tt> to represent an uninitialized
* value.
* @return a value that represents the given type. The size of the returned value must be equal to
* the size of the given type.
*
* @since ASM 1.7
*/
public V newReturnTypeValue(Type type) {
return newValue(type);
}

/**
* Called by the analyzer when initializing the value of a parameter in a frame.
*
* By default, calls <code>newValue(type)</code>.
*
* @param isInstanceMethod <tt>true</tt> if the owner of the parameter is is non-static method, a
* primitive or reference type, or <tt>false</tt> otherwise. value.
* @param type a primitive or reference type, or <tt>null</tt> to represent an uninitialized value.
* @return a value that represents the given type. The size of the returned value must be equal
* to the size of the given type.
* @since ASM 1.7
*/
public V newParameterValue(boolean isInstanceMethod, int local, Type type) {
return newValue(type);
}

/**
* Called by the analyzer when initializing a non-parameter local in a frame.
* This method has to return a size-1 value representing an empty slot.
*
* By default, calls <code>newValue(null)</code>.
*
* @param local The index of the local in the frame.
* @return a value that represents the given type. The size of the returned value must be equal
* to the size of the given type.
*
* @since ASM 1.7
*/
public V newEmptyNonParameterLocalValue(int local) {
return newValue(null);
}

/**
* Called by the analyzer and the interpreter. When initializing or setting the value of a
* size-2 local, the value of the subsequent slot is reset using this method.
* This method has to return a size-1 value representing an empty slot.
*
* By default, calls <code>newValue(null)</code>.
*
* @param local The index of the local in the frame.
* @return a value that represents the given type. The size of the returned value must be equal
* to the size of the given type.
*
* @since ASM 1.7
*/
public V newEmptyValueAfterSize2Local(int local) {
return newValue(null);
}

/**
* Called by the interpreter. When setting the value of a local variable, the interpreter checks
* whether the current value stored at the preceding index is of size-2. In this case, the
* preceding size-2 value is no longer valid and reset using this method.
* This method has to return a size-1 value representing an empty slot.
*
* By default, calls <code>newValue(null)</code>.
*
* @param local The index of the local in the frame.
* @return a value that represents the given type. The size of the returned value must be equal
* to the size of the given type.
*
* @since ASM 1.7
*/
public V newEmptyValueForPreviousSize2Local(int local) {
return newValue(null);
}

/**
* Called by the analyzer when initializing the exception value on the call stack at the entry
* of an exception handler.
*
* By default, calls <code>newValue(exceptionType)</code>.
*
* @param tryCatchBlockNode The exception handler
* @param handlerFrame The frame of the handler catching an exception from the current instruction
* @param exceptionType The excption type handled by this handler.
* @return a value that represents the given type. The size of the returned value must be equal
* to the size of the given type.
*
* @since ASM 1.7
*/
public V newExceptionValue(TryCatchBlockNode tryCatchBlockNode, Frame handlerFrame, Type exceptionType) {
return newValue(exceptionType);
}

/**
* Interprets a bytecode instruction that moves a value on the stack or to or from local
* variables. This method is called for the following opcodes:
Expand Down