changeset 256:21cd08a886cd

Generators: do preemptive field access to fold null pointer checks.
author shade
date Mon, 16 May 2016 19:55:04 +0300
parents 99385f86b4f6
children 6e1413cbb7e0
files jcstress-core/src/main/java/org/openjdk/jcstress/infra/processors/JCStressTestProcessor.java
diffstat 1 files changed, 61 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/infra/processors/JCStressTestProcessor.java	Fri May 13 22:26:42 2016 +0300
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/infra/processors/JCStressTestProcessor.java	Mon May 16 19:55:04 2016 +0300
@@ -268,11 +268,18 @@
             throw new GenerationException("IOException: " + e.getMessage(), info.getTest());
         }
 
+        boolean isStateItself = info.getState().equals(info.getTest());
+
         String t = info.getTest().getSimpleName().toString();
-        String s = info.getState().getSimpleName().toString();
-        String r = info.getResult().getSimpleName().toString();
+        String s = isStateItself ?
+                        info.getState().getSimpleName().toString() :
+                        getGeneratedName(info.getState());
+        String r = getGeneratedName(info.getResult());
 
-        boolean isStateItself = info.getState().equals(info.getTest());
+        generateTrapSubclass(info.getResult());
+        if (!isStateItself) {
+            generateTrapSubclass(info.getState());
+        }
 
         int actorsCount = info.getActors().size();
 
@@ -440,10 +447,25 @@
             pw.println();
             pw.println("            for (Pair p : pairs) {");
 
+            // Try to access both state and result fields early. This will help
+            // compiler to avoid null-pointer checks in the workload, which will
+            // free it to choose alternative load/store orders.
+            //
+            // For results, we can touch the synthetic "trap" field.
+            // For states that are passed as arguments we can do the same.
+            // For states that are receivers themselves, we already have the NP-check.
+
+            if (hasResultArgs(a)) {
+                pw.println("                " + r + " r = p.r;");
+                pw.println("                r.trap = 0;");
+            }
+
             if (isStateItself) {
-                emitMethod(pw, a, "                p.s." + a.getSimpleName(), "p.s", "p.r", true);
+                emitMethod(pw, a, "                p.s." + a.getSimpleName(), "p.s", "r", true);
             } else {
-                emitMethod(pw, a, "                lt." + a.getSimpleName(), "p.s", "p.r", true);
+                pw.println("                " + s + " s = p.s;");
+                pw.println("                s.trap = 0;");
+                emitMethod(pw, a, "                lt." + a.getSimpleName(), "s", "r", true);
             }
 
             pw.println("            }");
@@ -477,6 +499,28 @@
         pw.close();
     }
 
+    private void generateTrapSubclass(TypeElement el) {
+        String name = getGeneratedName(el);
+
+        PrintWriter pw;
+        try {
+            Writer writer = processingEnv.getFiler().createSourceFile(getPackageName(el) + "." + name).openWriter();
+            pw = new PrintWriter(writer);
+        } catch (IOException e) {
+            // may happen when file is already generated
+            return;
+        }
+
+        pw.println("package " + getPackageName(el) + ";");
+        pw.println("public class " + name + " extends " + el.getQualifiedName() + "{ ");
+        pw.println("    @sun.misc.Contended");
+        pw.println("    @jdk.internal.vm.annotation.Contended");
+        pw.println("    public int trap;");
+        pw.println("}");
+
+        pw.close();
+    }
+
     private String getDefaultVal(VariableElement var) {
         String type = var.asType().toString();
         String val;
@@ -669,6 +713,16 @@
         pw.close();
     }
 
+    private boolean hasResultArgs(ExecutableElement el) {
+        for (VariableElement var : el.getParameters()) {
+            TypeElement paramClass = (TypeElement) processingEnv.getTypeUtils().asElement(var.asType());
+            if (paramClass.getAnnotation(Result.class) != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void emitMethod(PrintWriter pw, ExecutableElement el, String lvalue, String stateAccessor, String resultAccessor, boolean terminate) {
         pw.print(lvalue + "(");
 
@@ -729,11 +783,11 @@
         }
         pw.println("import " + info.getTest().getQualifiedName() + ";");
         if (info.getResult() != null) {
-            pw.println("import " + info.getResult().getQualifiedName() + ";");
+            pw.println("import " + info.getResult().getQualifiedName() + "_jcstress;");
         }
         if (!info.getTest().equals(info.getState())) {
             if (info.getState() != null) {
-                pw.println("import " + info.getState().getQualifiedName() + ";");
+                pw.println("import " + getPackageName(info.getState()) + "." + getGeneratedName(info.getState()) + ";");
             }
         }