use of org.objectweb.asm.tree.LabelNode in project jphp by jphp-compiler.
the class TryCatchCompiler method write.
@Override
public void write(TryStmtToken token) {
if (token.getBody() == null || token.getBody().getInstructions().isEmpty()) {
if (token.getFinally() != null)
expr.write(BodyStmtToken.class, token.getFinally());
return;
}
expr.writeDefineVariables(token.getLocal());
LabelNode tryStart = expr.writeLabel(node, token.getMeta().getStartLine());
LabelNode tryEnd = new LabelNode();
LabelNode catchStart = new LabelNode();
LabelNode catchEnd = new LabelNode();
LabelNode returnLabel = new LabelNode();
method.node.tryCatchBlocks.add(0, new TryCatchBlockNode(tryStart, tryEnd, catchStart, Type.getInternalName(BaseBaseException.class)));
if (token.getFinally() != null) {
method.getTryStack().push(new MethodStmtCompiler.TryCatchItem(token, returnLabel));
}
expr.write(BodyStmtToken.class, token.getBody());
if (token.getFinally() != null) {
method.getTryStack().pop();
}
add(tryEnd);
add(new JumpInsnNode(GOTO, catchEnd));
add(catchStart);
LocalVariable exception = method.addLocalVariable("~catch~" + method.nextStatementIndex(BaseException.class), catchStart, BaseBaseException.class);
exception.setEndLabel(catchEnd);
expr.makeVarStore(exception);
LabelNode nextCatch = null;
int i = 0, size = token.getCatches().size();
LocalVariable local = null;
LabelNode catchFail = new LabelNode();
for (CatchStmtToken _catch : token.getCatches()) {
if (nextCatch != null) {
add(nextCatch);
}
if (i == size - 1) {
nextCatch = catchFail;
} else {
nextCatch = new LabelNode();
}
local = method.getLocalVariable(_catch.getVariable().getName());
List<FulledNameToken> catchExceptions = _catch.getExceptions();
LabelNode bodyLabel = new LabelNode();
LabelNode nextCatchLocal = new LabelNode();
int j = 0;
for (FulledNameToken catchException : catchExceptions) {
if (j > 0) {
add(nextCatchLocal);
nextCatchLocal = new LabelNode();
}
expr.writePushEnv();
expr.writeVarLoad(exception);
expr.writePushConstString(catchException.toName());
expr.writePushConstString(catchException.toName().toLowerCase());
expr.writeSysDynamicCall(Environment.class, "__throwCatch", Memory.class, BaseBaseException.class, String.class, String.class);
expr.writeVarAssign(local, _catch.getVariable(), true, false);
expr.writePopBoolean();
add(new JumpInsnNode(IFEQ, j == catchExceptions.size() - 1 ? nextCatch : nextCatchLocal));
expr.stackPop();
if (catchExceptions.size() > 1) {
add(new JumpInsnNode(GOTO, bodyLabel));
}
j++;
}
if (catchExceptions.size() > 1) {
add(bodyLabel);
}
expr.write(BodyStmtToken.class, _catch.getBody());
add(new JumpInsnNode(GOTO, catchEnd));
i++;
}
add(catchFail);
if (token.getFinally() != null) {
expr.write(BodyStmtToken.class, token.getFinally());
}
/*if (method.getTryStack().empty()) {
expr.writePushEnv();
expr.writeVarLoad(exception);
expr.writeSysDynamicCall(Environment.class, "__throwFailedCatch", void.class, BaseException.class);
} else {*/
expr.makeVarLoad(exception);
add(new InsnNode(ATHROW));
// }
add(catchEnd);
if (token.getFinally() != null) {
LabelNode skip = new LabelNode();
add(new JumpInsnNode(GOTO, skip));
// finally for return
add(returnLabel);
expr.write(BodyStmtToken.class, token.getFinally());
if (method.getTryStack().empty()) {
// all finally blocks are done
LocalVariable retVar = method.getOrAddLocalVariable("~result~", null, Memory.class);
expr.writeVarLoad(retVar);
add(new InsnNode(ARETURN));
expr.stackPop();
} else {
// goto next finally block
add(new JumpInsnNode(GOTO, method.getTryStack().peek().getReturnLabel()));
}
add(skip);
// other finally
expr.write(BodyStmtToken.class, token.getFinally());
}
expr.writeUndefineVariables(token.getLocal());
method.prevStatementIndex(BaseBaseException.class);
}
use of org.objectweb.asm.tree.LabelNode in project jacoco by jacoco.
the class KotlinWhenFilter method ignoreDefaultBranch.
private static void ignoreDefaultBranch(final AbstractInsnNode switchNode, final IFilterOutput output) {
final List<LabelNode> labels;
if (switchNode.getOpcode() == Opcodes.LOOKUPSWITCH) {
labels = ((LookupSwitchInsnNode) switchNode).labels;
} else {
labels = ((TableSwitchInsnNode) switchNode).labels;
}
final Set<AbstractInsnNode> newTargets = new HashSet<AbstractInsnNode>();
for (final LabelNode label : labels) {
newTargets.add(AbstractMatcher.skipNonOpcodes(label));
}
output.replaceBranches(switchNode, newTargets);
}
use of org.objectweb.asm.tree.LabelNode in project evosuite by EvoSuite.
the class BranchPool method registerTableSwitchCases.
private void registerTableSwitchCases(BytecodeInstruction v, TableSwitchInsnNode tableSwitchNode) {
int num = 0;
for (int i = tableSwitchNode.min; i <= tableSwitchNode.max; i++) {
LabelNode targetLabel = (LabelNode) tableSwitchNode.labels.get(num);
Branch switchBranch = createSwitchCaseBranch(v, i, targetLabel);
if (!switchBranch.isSwitchCaseBranch() || !switchBranch.isActualCase())
throw new IllegalStateException("expect created branch to be an actual case branch of a switch");
num++;
}
}
use of org.objectweb.asm.tree.LabelNode in project evosuite by EvoSuite.
the class BranchPool method registerLookupSwitchCases.
private void registerLookupSwitchCases(BytecodeInstruction v, LookupSwitchInsnNode lookupSwitchNode) {
for (int i = 0; i < lookupSwitchNode.keys.size(); i++) {
LabelNode targetLabel = (LabelNode) lookupSwitchNode.labels.get(i);
Branch switchBranch = createSwitchCaseBranch(v, (Integer) lookupSwitchNode.keys.get(i), targetLabel);
if (!switchBranch.isSwitchCaseBranch() || !switchBranch.isActualCase())
throw new IllegalStateException("expect created branch to be an actual case branch of a switch");
}
}
use of org.objectweb.asm.tree.LabelNode in project evosuite by EvoSuite.
the class Instrumenter method wrapMethod.
/**
* public int myMethod(int i)
* {
* try
* {
* return _sw_prototype_original_myMethod(i)
* }
* finally
* {
* Capturer.enable();
* }
* }
*
* @param classNode
* @param className
* @param methodNode
*/
@SuppressWarnings("unchecked")
private MethodNode wrapMethod(final ClassNode classNode, final String className, final MethodNode methodNode) {
methodNode.maxStack += 4;
// create wrapper for original method
final MethodNode wrappingMethodNode = new MethodNode(methodNode.access, methodNode.name, methodNode.desc, methodNode.signature, (String[]) methodNode.exceptions.toArray(new String[methodNode.exceptions.size()]));
wrappingMethodNode.maxStack = methodNode.maxStack;
// assign annotations to wrapping method
wrappingMethodNode.visibleAnnotations = methodNode.visibleAnnotations;
wrappingMethodNode.visibleParameterAnnotations = methodNode.visibleParameterAnnotations;
// remove annotations from wrapped method to avoid wrong behavior controlled by annotations
methodNode.visibleAnnotations = null;
methodNode.visibleParameterAnnotations = null;
// rename original method
methodNode.access = TransformerUtil.modifyVisibility(methodNode.access, Opcodes.ACC_PRIVATE);
final LabelNode l0 = new LabelNode();
final LabelNode l1 = new LabelNode();
final LabelNode l2 = new LabelNode();
final InsnList wInstructions = wrappingMethodNode.instructions;
if ("<init>".equals(methodNode.name)) {
// wrap a constructor
methodNode.name = WRAP_NAME_PREFIX + "init" + WRAP_NAME_PREFIX;
// move call to other constructors to new method
AbstractInsnNode ins = null;
ListIterator<AbstractInsnNode> iter = methodNode.instructions.iterator();
// number of invokespecial calls before actual constructor call
int numInvokeSpecials = 0;
while (iter.hasNext()) {
ins = iter.next();
iter.remove();
wInstructions.add(ins);
if (ins instanceof MethodInsnNode) {
MethodInsnNode mins = (MethodInsnNode) ins;
if (ins.getOpcode() == Opcodes.INVOKESPECIAL) {
if (mins.name.startsWith("<init>")) {
if (numInvokeSpecials == 0) {
break;
} else {
numInvokeSpecials--;
}
}
}
} else if (ins instanceof TypeInsnNode) {
TypeInsnNode typeIns = (TypeInsnNode) ins;
if (typeIns.getOpcode() == Opcodes.NEW || typeIns.getOpcode() == Opcodes.NEWARRAY) {
numInvokeSpecials++;
}
}
}
} else {
methodNode.name = WRAP_NAME_PREFIX + methodNode.name;
}
int varReturnValue = 0;
final Type returnType = Type.getReturnType(methodNode.desc);
if (returnType.equals(Type.VOID_TYPE)) {
wrappingMethodNode.tryCatchBlocks.add(new TryCatchBlockNode(l0, l1, l1, "java/lang/Throwable"));
} else {
wrappingMethodNode.tryCatchBlocks.add(new TryCatchBlockNode(l0, l1, l2, "java/lang/Throwable"));
if (!TransformerUtil.isStatic(methodNode.access)) {
// load "this"
varReturnValue++;
}
// consider method arguments to find right variable index
final Type[] argTypes = Type.getArgumentTypes(methodNode.desc);
for (int i = 0; i < argTypes.length; i++) {
varReturnValue++;
// long/double take two registers
if (argTypes[i].equals(Type.LONG_TYPE) || argTypes[i].equals(Type.DOUBLE_TYPE)) {
varReturnValue++;
}
}
// push NULL on the stack and initialize variable for return value for it
wInstructions.add(new InsnNode(Opcodes.ACONST_NULL));
wInstructions.add(new VarInsnNode(Opcodes.ASTORE, varReturnValue));
}
int var = 0;
// --- L0
wInstructions.add(l0);
wInstructions.add(this.addCaptureCall(TransformerUtil.isStatic(methodNode.access), className, wrappingMethodNode.name, wrappingMethodNode.desc, Type.getArgumentTypes(methodNode.desc)));
if (!TransformerUtil.isStatic(methodNode.access)) {
// load "this" to call method
wInstructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
var++;
}
final Type[] argTypes = Type.getArgumentTypes(methodNode.desc);
for (int i = 0; i < argTypes.length; i++) {
this.addLoadInsn(wInstructions, argTypes[i], var++);
// long/double take two registers
if (argTypes[i].equals(Type.LONG_TYPE) || argTypes[i].equals(Type.DOUBLE_TYPE)) {
var++;
}
}
if (TransformerUtil.isStatic(methodNode.access)) {
wInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, classNode.name, methodNode.name, methodNode.desc));
} else {
wInstructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, classNode.name, methodNode.name, methodNode.desc));
}
var++;
if (returnType.equals(Type.VOID_TYPE)) {
wInstructions.add(new JumpInsnNode(Opcodes.GOTO, l2));
// --- L1
wInstructions.add(l1);
wInstructions.add(new FrameNode(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" }));
wInstructions.add(new VarInsnNode(Opcodes.ASTORE, --var));
this.addCaptureEnableStatement(className, methodNode, wInstructions, -1);
wInstructions.add(new VarInsnNode(Opcodes.ALOAD, var));
wInstructions.add(new InsnNode(Opcodes.ATHROW));
// FIXME <--- DUPLICATE CODE
// --- L2
wInstructions.add(l2);
wInstructions.add(new FrameNode(Opcodes.F_SAME, 0, null, 0, null));
this.addCaptureEnableStatement(className, methodNode, wInstructions, -1);
wInstructions.add(new InsnNode(Opcodes.RETURN));
} else {
// construct store of the wrapped method call's result
this.addBoxingStmt(wInstructions, returnType);
wInstructions.add(new VarInsnNode(Opcodes.ASTORE, varReturnValue));
wInstructions.add(new VarInsnNode(Opcodes.ALOAD, varReturnValue));
this.addUnBoxingStmt(wInstructions, returnType);
final int storeOpcode = returnType.getOpcode(Opcodes.ISTORE);
// might be only var
wInstructions.add(new VarInsnNode(storeOpcode, ++var));
// --- L1
wInstructions.add(l1);
this.addCaptureEnableStatement(className, methodNode, wInstructions, varReturnValue);
// construct load of the wrapped method call's result
int loadOpcode = returnType.getOpcode(Opcodes.ILOAD);
wInstructions.add(new VarInsnNode(loadOpcode, var));
// construct return of the wrapped method call's result
this.addReturnInsn(wInstructions, returnType);
// ---- L2
wInstructions.add(l2);
wInstructions.add(new FrameNode(Opcodes.F_FULL, 2, new Object[] { className, this.getInternalName(returnType) }, 1, new Object[] { "java/lang/Throwable" }));
wInstructions.add(new VarInsnNode(Opcodes.ASTORE, --var));
this.addCaptureEnableStatement(className, methodNode, wInstructions, varReturnValue);
wInstructions.add(new VarInsnNode(Opcodes.ALOAD, var));
wInstructions.add(new InsnNode(Opcodes.ATHROW));
}
transformWrapperCalls(methodNode);
return wrappingMethodNode;
}
Aggregations