Search in sources :

Example 1 with VisibleForTesting

use of co.paralleluniverse.common.util.VisibleForTesting in project quasar by puniverse.

the class QuasarInstrumentor method instrumentClass.

@VisibleForTesting
byte[] instrumentClass(ClassLoader loader, String className, InputStream is, boolean forceInstrumentation) throws IOException {
    className = className != null ? className.replace('.', '/') : null;
    byte[] cb = toByteArray(is);
    MethodDatabase db = getMethodDatabase(loader);
    if (className != null) {
        log(LogLevel.INFO, "TRANSFORM: %s %s", className, (db.getClassEntry(className) != null && db.getClassEntry(className).requiresInstrumentation()) ? "request" : "");
        examine(className, "quasar-1-preinstr", cb);
    } else {
        log(LogLevel.INFO, "TRANSFORM: null className");
    }
    // Phase 1, add a label before any suspendable calls, event API is enough
    final ClassReader r1 = new ClassReader(cb);
    final ClassWriter cw1 = new ClassWriter(r1, 0);
    final LabelSuspendableCallSitesClassVisitor ic1 = new LabelSuspendableCallSitesClassVisitor(cw1, db);
    r1.accept(ic1, 0);
    cb = cw1.toByteArray();
    examine(className, "quasar-2", cb);
    // Phase 2, instrument, tree API
    final ClassReader r2 = new ClassReader(cb);
    final ClassWriter cw2 = new DBClassWriter(db, r2);
    final ClassVisitor cv2 = (check && EXAMINED_CLASS == null) ? new CheckClassAdapter(cw2) : cw2;
    final InstrumentClass ic2 = new InstrumentClass(cv2, db, forceInstrumentation);
    try {
        r2.accept(ic2, ClassReader.SKIP_FRAMES);
        cb = cw2.toByteArray();
    } catch (final Exception e) {
        if (ic2.hasSuspendableMethods()) {
            error("Unable to instrument class " + className, e);
            throw e;
        } else {
            if (!MethodDatabase.isProblematicClass(className))
                log(LogLevel.DEBUG, "Unable to instrument class " + className);
            return null;
        }
    }
    examine(className, "quasar-4", cb);
    // Phase 4, fill suspendable call offsets, event API is enough
    final OffsetClassReader r3 = new OffsetClassReader(cb);
    final ClassWriter cw3 = new ClassWriter(r3, 0);
    final SuspOffsetsAfterInstrClassVisitor ic3 = new SuspOffsetsAfterInstrClassVisitor(cw3, db);
    r3.accept(ic3, 0);
    cb = cw3.toByteArray();
    // DEBUG
    if (EXAMINED_CLASS != null) {
        examine(className, "quasar-5-final", cb);
        if (check) {
            ClassReader r4 = new ClassReader(cb);
            ClassVisitor cv4 = new CheckClassAdapter(new TraceClassVisitor(null), true);
            r4.accept(cv4, 0);
        }
    }
    return cb;
}
Also used : TraceClassVisitor(org.objectweb.asm.util.TraceClassVisitor) ClassVisitor(org.objectweb.asm.ClassVisitor) ClassWriter(org.objectweb.asm.ClassWriter) TraceClassVisitor(org.objectweb.asm.util.TraceClassVisitor) CheckClassAdapter(org.objectweb.asm.util.CheckClassAdapter) ClassReader(org.objectweb.asm.ClassReader) VisibleForTesting(co.paralleluniverse.common.util.VisibleForTesting)

Aggregations

VisibleForTesting (co.paralleluniverse.common.util.VisibleForTesting)1 ClassReader (org.objectweb.asm.ClassReader)1 ClassVisitor (org.objectweb.asm.ClassVisitor)1 ClassWriter (org.objectweb.asm.ClassWriter)1 CheckClassAdapter (org.objectweb.asm.util.CheckClassAdapter)1 TraceClassVisitor (org.objectweb.asm.util.TraceClassVisitor)1