use of org.objectweb.asm.tree.AnnotationNode in project sling by apache.
the class GenerateAdapterMetadataMojo method parseAdaptableAnnotation.
@SuppressWarnings("unchecked")
private void parseAdaptableAnnotation(final AnnotationNode annotation, final ClassNode annotatedClass, final Map<String, Object> descriptor) throws JsonException {
String adaptableClassName = null;
List<AnnotationNode> adapters = null;
final List<?> values = annotation.values;
final Iterator<?> it = values.iterator();
while (it.hasNext()) {
Object name = it.next();
Object value = it.next();
if ("adaptableClass".equals(name)) {
adaptableClassName = ((Type) value).getClassName();
} else if ("adapters".equals(name)) {
adapters = (List<AnnotationNode>) value;
}
}
if (adaptableClassName == null || adapters == null) {
throw new IllegalArgumentException("Adaptable annotation is malformed. Expecting a classname and a list of adapter annotation.");
}
Map<String, Object> adaptableDescription;
if (descriptor.containsKey(adaptableClassName)) {
adaptableDescription = (Map<String, Object>) descriptor.get(adaptableClassName);
} else {
adaptableDescription = new HashMap<>();
descriptor.put(adaptableClassName, adaptableDescription);
}
for (final AnnotationNode adapter : adapters) {
parseAdapterAnnotation(adapter, annotatedClass, adaptableDescription);
}
}
use of org.objectweb.asm.tree.AnnotationNode in project sling by apache.
the class GenerateAdapterMetadataMojo method parseAdaptablesAnnotation.
private void parseAdaptablesAnnotation(final AnnotationNode annotation, final ClassNode classNode, final Map<String, Object> descriptor) throws JsonException {
final Iterator<?> it = annotation.values.iterator();
while (it.hasNext()) {
Object name = it.next();
Object value = it.next();
if ("value".equals(name)) {
@SuppressWarnings("unchecked") final List<AnnotationNode> annotations = (List<AnnotationNode>) value;
for (final AnnotationNode innerAnnotation : annotations) {
if (ADAPTABLE_DESC.equals(innerAnnotation.desc)) {
parseAdaptableAnnotation(innerAnnotation, classNode, descriptor);
}
}
}
}
}
use of org.objectweb.asm.tree.AnnotationNode in project quasar by puniverse.
the class InstrumentMethod method accept.
public void accept(MethodVisitor mv, boolean hasAnnotation) {
db.log(LogLevel.INFO, "Instrumenting method %s:%s#%s%s", sourceName, className, mn.name, mn.desc);
if (mn.name.charAt(0) == '<')
throw new UnableToInstrumentException("special method", className, mn.name, mn.desc);
collectCallsites();
final boolean skipInstrumentation = canInstrumentationBeSkipped(suspCallsBcis);
emitInstrumentedAnn(db, mv, mn, sourceName, className, skipInstrumentation, startSourceLine, endSourceLine, suspCallsSourceLines, suspCallsNames, null);
if (skipInstrumentation) {
db.log(LogLevel.INFO, "[OPTIMIZE] Skipping instrumentation for method %s:%s#%s%s", sourceName, className, mn.name, mn.desc);
// Dump
mn.accept(mv);
return;
}
// Else instrument
// Must be called first, sets flags & state used below
collectCodeBlocks();
// noinspection ConstantConditions
final boolean handleProxyInvocations = HANDLE_PROXY_INVOCATIONS && callsSuspendableSupers;
mv.visitCode();
Label lMethodStart = new Label();
Label lMethodStart2 = new Label();
Label lMethodEnd = new Label();
Label lCatchSEE = new Label();
Label lCatchUTE = new Label();
Label lCatchAll = new Label();
Label[] lMethodCalls = new Label[numCodeBlocks - 1];
Label[][] refInvokeTryCatch;
for (int i = 1; i < numCodeBlocks; i++) lMethodCalls[i - 1] = new Label();
mv.visitInsn(Opcodes.ACONST_NULL);
mv.visitVarInsn(Opcodes.ASTORE, lvarInvocationReturnValue);
// if (verifyInstrumentation) {
// mv.visitInsn(Opcodes.ICONST_0);
// mv.visitVarInsn(Opcodes.ISTORE, lvarSuspendableCalled);
// }
mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchSEE, SUSPEND_EXECUTION_NAME);
mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchSEE, RUNTIME_SUSPEND_EXECUTION_NAME);
if (handleProxyInvocations)
mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchUTE, UNDECLARED_THROWABLE_NAME);
// Prepare visitTryCatchBlocks for InvocationTargetException.
// With reflective invocations, the SuspendExecution exception will be wrapped in InvocationTargetException. We need to catch it and unwrap it.
// Note that the InvocationTargetException will be regenrated on every park, adding further overhead on top of the reflective call.
// This must be done here, before all other visitTryCatchBlock, because the exception's handler
// will be matched according to the order of in which visitTryCatchBlock has been called. Earlier calls take precedence.
refInvokeTryCatch = new Label[numCodeBlocks - 1][];
for (int i = 1; i < numCodeBlocks; i++) {
final FrameInfo fi = codeBlocks[i];
final AbstractInsnNode in = mn.instructions.get(fi.endInstruction);
if (mn.instructions.get(fi.endInstruction) instanceof MethodInsnNode) {
MethodInsnNode min = (MethodInsnNode) in;
if (isReflectInvocation(min.owner, min.name)) {
Label[] ls = new Label[3];
for (int k = 0; k < 3; k++) ls[k] = new Label();
refInvokeTryCatch[i - 1] = ls;
mv.visitTryCatchBlock(ls[0], ls[1], ls[2], "java/lang/reflect/InvocationTargetException");
}
}
}
// Output try-catch blocks
for (final Object o : mn.tryCatchBlocks) {
final TryCatchBlockNode tcb = (TryCatchBlockNode) o;
if (// we allow catch of SuspendExecution only in methods annotated with @Suspendable and in lambda-generated ones.
SUSPEND_EXECUTION_NAME.equals(tcb.type) && !hasAnnotation && !mn.name.startsWith(Classes.LAMBDA_METHOD_PREFIX))
throw new UnableToInstrumentException("catch for SuspendExecution", className, mn.name, mn.desc);
if (// we allow catch of SuspendExecution in method annotated with @Suspendable.
handleProxyInvocations && UNDECLARED_THROWABLE_NAME.equals(tcb.type))
throw new UnableToInstrumentException("catch for UndeclaredThrowableException", className, mn.name, mn.desc);
// if (INTERRUPTED_EXCEPTION_NAME.equals(tcb.type))
// throw new UnableToInstrumentException("catch for " + InterruptedException.class.getSimpleName(), className, mn.name, mn.desc);
tcb.accept(mv);
}
// Output parameter annotations
if (mn.visibleParameterAnnotations != null)
dumpParameterAnnotations(mv, mn.visibleParameterAnnotations, true);
if (mn.invisibleParameterAnnotations != null)
dumpParameterAnnotations(mv, mn.invisibleParameterAnnotations, false);
// Output method annotations
if (mn.visibleAnnotations != null) {
for (Object o : mn.visibleAnnotations) {
AnnotationNode an = (AnnotationNode) o;
an.accept(mv.visitAnnotation(an.desc, true));
}
}
mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchAll, null);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, STACK_NAME, "getStack", "()L" + STACK_NAME + ";", false);
mv.visitInsn(Opcodes.DUP);
mv.visitVarInsn(Opcodes.ASTORE, lvarStack);
// println(mv, "STACK: ", lvarStack);
// dumpStack(mv);
// DUAL
mv.visitJumpInsn(Opcodes.IFNULL, lMethodStart);
mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
// we'll assume we have been resumed
emitStoreResumed(mv, true);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "nextMethodEntry", "()I", false);
mv.visitTableSwitchInsn(1, numCodeBlocks - 1, lMethodStart2, lMethodCalls);
mv.visitLabel(lMethodStart2);
// the following code handles the case of an instrumented method called not as part of a suspendable code path
// isFirstInStack will return false in that case.
mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "isFirstInStackOrPushed", "()Z", false);
// if true
mv.visitJumpInsn(Opcodes.IFNE, lMethodStart);
// This will reset the fiber stack local if isFirstStack returns false.
mv.visitInsn(Opcodes.ACONST_NULL);
mv.visitVarInsn(Opcodes.ASTORE, lvarStack);
mv.visitLabel(lMethodStart);
// no, we have not been resumed
emitStoreResumed(mv, false);
dumpCodeBlock(mv, 0, 0);
// Blocks leading to suspendable calls
for (int i = 1; i < numCodeBlocks; i++) {
final FrameInfo fi = codeBlocks[i];
// Emit instrumented call
final AbstractInsnNode min = mn.instructions.get(fi.endInstruction);
final String owner = getMethodOwner(min), name = getMethodName(min), desc = getMethodDesc(min);
if (isYieldMethod(owner, name)) {
// special case - call to yield
if (min.getOpcode() != Opcodes.INVOKESTATIC)
throw new UnableToInstrumentException("invalid call to suspending method.", className, mn.name, mn.desc);
final int numYieldArgs = TypeAnalyzer.getNumArguments(desc);
final boolean yieldReturnsValue = (Type.getReturnType(desc) != Type.VOID_TYPE);
// we preserve the arguments for the call to yield on the operand stack
emitStoreState(mv, i, fi, numYieldArgs);
// we have not been resumed
emitStoreResumed(mv, false);
// emitSuspendableCalled(mv);
// we call the yield method
min.accept(mv);
if (yieldReturnsValue)
// we ignore the returned value...
mv.visitInsn(Opcodes.POP);
// we resume AFTER the call
mv.visitLabel(lMethodCalls[i - 1]);
final Label afterPostRestore = new Label();
mv.visitVarInsn(Opcodes.ILOAD, lvarResumed);
mv.visitJumpInsn(Opcodes.IFEQ, afterPostRestore);
emitPostRestore(mv);
mv.visitLabel(afterPostRestore);
emitRestoreState(mv, i, fi, numYieldArgs);
if (yieldReturnsValue)
// ... and replace the returned value with the value of resumed
mv.visitVarInsn(Opcodes.ILOAD, lvarResumed);
// See #211: if Fiber.park() is the last call before catch, ASM generates
// empty handlers (start_pc = end_pc) that won't pass ASM's nor JVM's bytecode checker because of
// exception_table's spec here: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.3
mv.visitInsn(Opcodes.NOP);
dumpCodeBlock(mv, i, 1);
} else {
final Label lbl = new Label();
// DUAL
mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
mv.visitJumpInsn(Opcodes.IFNULL, lbl);
// normal case - call to a suspendable method - resume before the call
emitStoreState(mv, i, fi, 0);
// we have not been resumed
emitStoreResumed(mv, false);
// emitPreemptionPoint(mv, PREEMPTION_CALL);
mv.visitLabel(lMethodCalls[i - 1]);
emitRestoreState(mv, i, fi, 0);
// DUAL
mv.visitLabel(lbl);
if (isReflectInvocation(owner, name)) {
// We catch the InvocationTargetException and unwrap it if it wraps a SuspendExecution exception.
Label[] ls = refInvokeTryCatch[i - 1];
final Label startTry = ls[0];
final Label endTry = ls[1];
final Label startCatch = ls[2];
final Label endCatch = new Label();
final Label notSuspendExecution = new Label();
// mv.visitTryCatchBlock(startTry, endTry, startCatch, "java/lang/reflect/InvocationTargetException");
// try {
mv.visitLabel(startTry);
// method.invoke()
min.accept(mv);
// save return value
mv.visitVarInsn(Opcodes.ASTORE, lvarInvocationReturnValue);
// }
mv.visitLabel(endTry);
mv.visitJumpInsn(Opcodes.GOTO, endCatch);
// catch(InvocationTargetException ex) {
mv.visitLabel(startCatch);
mv.visitInsn(Opcodes.DUP);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;", false);
mv.visitTypeInsn(Opcodes.INSTANCEOF, SUSPEND_EXECUTION_NAME);
mv.visitJumpInsn(Opcodes.IFEQ, notSuspendExecution);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;", false);
mv.visitLabel(notSuspendExecution);
mv.visitInsn(Opcodes.ATHROW);
mv.visitLabel(endCatch);
// restore return value
mv.visitVarInsn(Opcodes.ALOAD, lvarInvocationReturnValue);
dumpCodeBlock(mv, i, 1);
} else {
// emitSuspendableCalled(mv);
dumpCodeBlock(mv, i, 0);
}
}
}
// Emit catchall's catch section
mv.visitLabel(lMethodEnd);
if (handleProxyInvocations) {
mv.visitLabel(lCatchUTE);
mv.visitInsn(Opcodes.DUP);
// println(mv, "CTCH: ");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;", false);
// println(mv, "CAUSE: ");
mv.visitTypeInsn(Opcodes.INSTANCEOF, SUSPEND_EXECUTION_NAME);
mv.visitJumpInsn(Opcodes.IFEQ, lCatchAll);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;", false);
mv.visitJumpInsn(Opcodes.GOTO, lCatchSEE);
}
mv.visitLabel(lCatchAll);
emitPopMethod(mv);
mv.visitLabel(lCatchSEE);
// println(mv, "THROW: ");
// rethrow shared between catchAll and catchSSE
mv.visitInsn(Opcodes.ATHROW);
if (mn.localVariables != null) {
for (Object o : mn.localVariables) ((LocalVariableNode) o).accept(mv);
}
// Needed by ASM analysis
mv.visitMaxs(mn.maxStack + ADD_OPERANDS, mn.maxLocals + NUM_LOCALS + additionalLocals);
mv.visitEnd();
}
use of org.objectweb.asm.tree.AnnotationNode in project MinecraftForge by MinecraftForge.
the class EventSubscriberTransformer method transform.
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
if (basicClass == null)
return null;
ClassNode classNode = new ClassNode();
new ClassReader(basicClass).accept(classNode, 0);
boolean isSubscriber = false;
for (MethodNode methodNode : classNode.methods) {
List<AnnotationNode> anns = methodNode.visibleAnnotations;
if (anns != null && Iterables.any(anns, SubscribeEventPredicate.INSTANCE)) {
if (Modifier.isPrivate(methodNode.access)) {
String msg = "Cannot apply @SubscribeEvent to private method %s/%s%s";
throw new RuntimeException(String.format(msg, classNode.name, methodNode.name, methodNode.desc));
}
methodNode.access = toPublic(methodNode.access);
isSubscriber = true;
}
}
if (isSubscriber) {
classNode.access = toPublic(classNode.access);
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classNode.accept(writer);
return writer.toByteArray();
}
return basicClass;
}
use of org.objectweb.asm.tree.AnnotationNode in project spring-loaded by spring-projects.
the class SpringLoadedTests method toStringField.
@SuppressWarnings("unchecked")
protected String toStringField(byte[] classdata, String fieldname) {
StringBuilder sb = new StringBuilder();
FieldNode fieldNode = getField(classdata, fieldname);
if (fieldNode == null) {
return null;
}
List<AnnotationNode> annos = fieldNode.visibleAnnotations;
if (annos != null) {
sb.append("vis(").append(toStringAnnotations(annos)).append(") ");
}
annos = fieldNode.invisibleAnnotations;
if (annos != null) {
sb.append("invis(").append(toStringAnnotations(annos)).append(") ");
}
// will need implementing at some point:
// List<Attribute> attrs = fieldNode.attrs;
// if (attrs = !null) {
// sb.append("attrs(").append(toStringAttributes(attrs)).append(") ");
// }
sb.append("0x").append(Integer.toHexString(fieldNode.access)).append("(").append(ClassPrinter.toAccessForMember(fieldNode.access)).append(") ");
sb.append(fieldNode.name).append(" ");
sb.append(fieldNode.desc).append(" ");
if (fieldNode.signature != null) {
sb.append(fieldNode.signature).append(" ");
}
if (fieldNode.value != null) {
sb.append(fieldNode.value).append(" ");
}
return sb.toString().trim();
}
Aggregations