Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / mcr-controller / src / edu / tamu / aser / profile / ProfileInstrumentor.java
diff --git a/JMCR-Stable/mcr-controller/src/edu/tamu/aser/profile/ProfileInstrumentor.java b/JMCR-Stable/mcr-controller/src/edu/tamu/aser/profile/ProfileInstrumentor.java
new file mode 100644 (file)
index 0000000..ab32e89
--- /dev/null
@@ -0,0 +1,188 @@
+package edu.tamu.aser.profile;
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+
+import edu.tamu.aser.profile.ProfileClassTransformer;
+import edu.tamu.aser.profile.ProfileRunTime;
+import edu.tamu.aser.reexecution.Scheduler;
+import edu.tamu.aser.rvinstrumentation.ExtendedClassWriter;
+import edu.tamu.aser.rvinstrumentation.MCRProperties;
+
+public class ProfileInstrumentor {
+    private static final String SLASH = "/";
+    private static final String DOT = ".";
+    private static final String SEMICOLON = ";";
+    
+    public static String logClass = "edu/tamu/aser/profile/ProfileRunTime";
+
+    
+    private static final String JUC_DOTS = "java.util.concurrent";
+
+    private static final String INSTUMENTATION_DEBUG_DEFAULT = "false";
+    private static final String INSTRUMENTATION_PACKAGES_DEFAULT = "default";
+
+    public static final String INSTR_EVENTS_RECEIVER = Scheduler.class.getName().replace(DOT, SLASH);
+
+    public static Set<String> packagesThatWereInstrumented = new HashSet<String>();
+    public static Set<String> packagesThatWereNOTInstrumented = new HashSet<String>();
+
+    private static final Set<String> pckgPrefixesToIgnore = new HashSet<String>();
+    private static final Set<String> pckgsToIgnore = new HashSet<String>();
+    private static final Set<String> classPrefixesToIgnore = new HashSet<String>();
+    private static final Set<String> classesToIgnore = new HashSet<String>();
+    private static final Set<String> pckgPrefixesToAllow = new HashSet<String>();
+    private static final Set<String> pckgsToAllow = new HashSet<String>();
+    private static final Set<String> classPrefixesToAllow = new HashSet<String>();
+    private static final Set<String> classesToAllow = new HashSet<String>();
+
+    private static void storePropertyValues(String values, Set<String> toSet) {
+        if (values != null) {
+            String[] split = values.split(SEMICOLON);
+            for (String val : split) {
+                val = val.replace(DOT, SLASH).trim();
+                if (!val.isEmpty()) {
+                    toSet.add(val);
+                }
+            }
+        }
+    }
+
+    private static boolean shouldInstrumentClass(String name) {
+
+        String pckgName = INSTRUMENTATION_PACKAGES_DEFAULT;
+        int lastSlashIndex = name.lastIndexOf(SLASH);
+        // Non-default package
+        if (lastSlashIndex != -1) {
+            pckgName = name.substring(0, lastSlashIndex);
+        }
+
+        // Phase 1 - check if explicitly allowed
+        if (classesToAllow.contains(name)) {
+            packagesThatWereInstrumented.add(pckgName);
+            return true;
+        }
+
+        // Phase 2 - check if prefix is allowed
+        for (String classPrefix : classPrefixesToAllow) {
+            if (name.startsWith(classPrefix)) {
+                packagesThatWereInstrumented.add(pckgName);
+                return true;
+            }
+        }
+
+        // Phase 3 - check if package is allowed
+        if (pckgsToAllow.contains(pckgName)) {
+            packagesThatWereInstrumented.add(pckgName);
+            return true;
+        }
+
+        // Phase 4 - check if package is allowed via prefix matching
+        for (String pckgPrefix : pckgPrefixesToAllow) {
+            if (pckgName.startsWith(pckgPrefix)) {
+                packagesThatWereInstrumented.add(pckgName);
+                return true;
+            }
+        }
+
+        // Phase 5 - check for any ignores
+        if (classesToIgnore.contains(name)) {
+            packagesThatWereNOTInstrumented.add(pckgName);
+            return false;
+        }
+        if (pckgsToIgnore.contains(pckgName)) {
+            packagesThatWereNOTInstrumented.add(pckgName);
+            return false;
+        }
+        for (String classPrefix : classPrefixesToIgnore) {
+            if (name.startsWith(classPrefix)) {
+                packagesThatWereNOTInstrumented.add(pckgName);
+                return false;
+            }
+        }
+        for (String pckgPrefix : pckgPrefixesToIgnore) {
+            //System.out.println(pckgPrefix);
+            if (pckgName.startsWith(pckgPrefix)) {
+                packagesThatWereNOTInstrumented.add(pckgName);
+                return false;
+            }
+        }
+
+        // Otherwise instrument by default
+        packagesThatWereInstrumented.add(pckgName);
+        return true;
+    }
+
+    public static void premain(String agentArgs, Instrumentation inst) {
+        MCRProperties mcrProps = MCRProperties.getInstance();
+        storePropertyValues(mcrProps.getProperty(MCRProperties.INSTRUMENTATION_PACKAGES_IGNORE_PREFIXES_KEY), pckgPrefixesToIgnore);
+        storePropertyValues(mcrProps.getProperty(MCRProperties.INSTRUMENTATION_PACKAGES_IGNORE_KEY), pckgsToIgnore);
+        storePropertyValues(mcrProps.getProperty(MCRProperties.INSTRUMENTATION_CLASSES_IGNORE_PREFIXES_KEY), classPrefixesToIgnore);
+        storePropertyValues(mcrProps.getProperty(MCRProperties.INSTRUMENTATION_CLASSES_IGNORE_KEY), classesToIgnore);
+        storePropertyValues(mcrProps.getProperty(MCRProperties.INSTRUMENTATION_PACKAGES_ALLOW_PREFIXES_KEY), pckgPrefixesToAllow);
+        storePropertyValues(mcrProps.getProperty(MCRProperties.INSTRUMENTATION_PACKAGES_ALLOW_KEY), pckgsToAllow);
+        storePropertyValues(mcrProps.getProperty(MCRProperties.INSTRUMENTATION_CLASSES_ALLOW_PREFIXES_KEY), classPrefixesToAllow);
+        storePropertyValues(mcrProps.getProperty(MCRProperties.INSTRUMENTATION_CLASSES_ALLOW_KEY), classesToAllow);
+
+        /* Should instrumentation debug messages be enabled? */
+        final boolean debugIntrumentation = Boolean.parseBoolean(mcrProps.getProperty(MCRProperties.INSTRUMENTATION_DEBUG_KEY,
+                INSTUMENTATION_DEBUG_DEFAULT));
+
+        ProfileRunTime.init();
+        
+        inst.addTransformer(new ClassFileTransformer() {
+            public byte[] transform(ClassLoader l, String name, Class<?> c, ProtectionDomain d, byte[] bytes) throws IllegalClassFormatException {
+                try {
+                    /*
+                     * If the package is included in the packages to instrument,
+                     * or the class is included in the classes to instrument,
+                     * instrument the class
+                     */
+                    if (shouldInstrumentClass(name)) {
+                        if (debugIntrumentation)
+                        {
+                            System.out.println("Instrumenting " + name);
+                        }
+
+                        ClassReader classReader = new ClassReader(bytes);
+                        ClassWriter classWriter = new ExtendedClassWriter(classReader, ClassWriter.COMPUTE_FRAMES);
+
+                            ProfileClassTransformer transformer = new ProfileClassTransformer(classWriter);
+                            classReader.accept(transformer, ClassReader.EXPAND_FRAMES);
+                            bytes = classWriter.toByteArray();
+                     
+                        
+                    }
+                } catch (Throwable th) {
+                    th.printStackTrace();
+                }
+                return bytes;
+            }
+        }, true);
+
+        /* Re-transform already loaded java.util.concurrent classes */
+        try {
+            List<Class<?>> classesToReTransform = new ArrayList<Class<?>>();
+            for (Class<?> loadedClass : inst.getAllLoadedClasses()) {
+                if (inst.isModifiableClass(loadedClass) && loadedClass.getPackage().getName().startsWith(JUC_DOTS)) {
+                    classesToReTransform.add(loadedClass);
+                }
+            }
+            inst.retransformClasses(classesToReTransform.toArray(new Class<?>[classesToReTransform.size()]));
+        } catch (UnmodifiableClassException e) {
+            e.printStackTrace();
+            System.err.println("Unable to modify a pre-loaded java.util.concurrent class!");
+            System.exit(2);
+        }
+    }
+}