8026286: Improper locking of annotation queues causes assertion failures.
authoremc
Wed, 16 Oct 2013 16:33:04 -0400
changeset 21043 3b000be15694
parent 21042 2b4b55bc044d
child 21044 ffba9cdeff1a
8026286: Improper locking of annotation queues causes assertion failures. 8026063: Calls to annotate.flush() cause incorrect type annotations to be generated. Summary: Fix locking in ClassReader.java Reviewed-by: jfranck
langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java
langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java
langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
langtools/test/tools/javac/annotations/typeAnnotations/TestAnonInnerInstance1.java
langtools/test/tools/javac/annotations/typeAnnotations/classfile/T8008762.java
--- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Wed Oct 16 10:47:21 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Wed Oct 16 16:33:04 2013 -0400
@@ -97,7 +97,6 @@
     final Symtab syms;
     final Annotate annotate;
     final Attr attr;
-    private final boolean typeAnnoAsserts;
 
     protected TypeAnnotations(Context context) {
         context.put(typeAnnosKey, this);
@@ -107,7 +106,6 @@
         annotate = Annotate.instance(context);
         attr = Attr.instance(context);
         Options options = Options.instance(context);
-        typeAnnoAsserts = options.isSet("TypeAnnotationAsserts");
     }
 
     /**
@@ -1042,11 +1040,7 @@
         @Override
         public void visitMethodDef(final JCMethodDecl tree) {
             if (tree.sym == null) {
-                if (typeAnnoAsserts) {
-                    Assert.error("Visiting tree node before memberEnter");
-                } else {
-                return;
-            }
+                Assert.error("Visiting tree node before memberEnter");
             }
             if (sigOnly) {
                 if (!tree.mods.annotations.isEmpty()) {
@@ -1150,10 +1144,7 @@
                 // Nothing to do for separateAnnotationsKinds if
                 // there are no annotations of either kind.
             } else if (tree.sym == null) {
-                if (typeAnnoAsserts) {
-                    Assert.error("Visiting tree node before memberEnter");
-                }
-                // Something is wrong already. Quietly ignore.
+                Assert.error("Visiting tree node before memberEnter");
             } else if (tree.sym.getKind() == ElementKind.PARAMETER) {
                 // Parameters are handled in visitMethodDef or visitLambda.
             } else if (tree.sym.getKind() == ElementKind.FIELD) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java	Wed Oct 16 10:47:21 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java	Wed Oct 16 16:33:04 2013 -0400
@@ -129,6 +129,12 @@
         flush();
     }
 
+    /** Variant which allows for a delayed flush of annotations.
+     * Needed by ClassReader */
+    public void enterDoneWithoutFlush() {
+        enterCount--;
+    }
+
     public void flush() {
         if (enterCount != 0) return;
         enterCount++;
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Wed Oct 16 10:47:21 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Wed Oct 16 16:33:04 2013 -0400
@@ -2405,8 +2405,6 @@
             return c;
     }
 
-    private boolean suppressFlush = false;
-
     /** Completion for classes to be loaded. Before a class is loaded
      *  we make sure its enclosing class (if any) is loaded.
      */
@@ -2414,13 +2412,14 @@
         if (sym.kind == TYP) {
             ClassSymbol c = (ClassSymbol)sym;
             c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
-            boolean saveSuppressFlush = suppressFlush;
-            suppressFlush = true;
+            annotate.enterStart();
             try {
                 completeOwners(c.owner);
                 completeEnclosing(c);
             } finally {
-                suppressFlush = saveSuppressFlush;
+                // The flush needs to happen only after annotations
+                // are filled in.
+                annotate.enterDoneWithoutFlush();
             }
             fillIn(c);
         } else if (sym.kind == PCK) {
@@ -2431,7 +2430,7 @@
                 throw new CompletionFailure(sym, ex.getLocalizedMessage()).initCause(ex);
             }
         }
-        if (!filling && !suppressFlush)
+        if (!filling)
             annotate.flush(); // finish attaching annotations
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/TestAnonInnerInstance1.java	Wed Oct 16 16:33:04 2013 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026286
+ * @summary This test previously forced an assertion to fail, due to
+ *          TypeAnnotationPosition visiting a tree node prior to
+ *          memberEnter.
+ * @compile TestAnonInnerInstance1.java
+ */
+
+import java.lang.annotation.*;
+import static java.lang.annotation.RetentionPolicy.*;
+import static java.lang.annotation.ElementType.*;
+import java.util.List;
+
+class TestAnonInnerInstance1<T> {
+    Object mtest(TestAnonInnerInstance1<T> t){ return null; }
+    Object mmtest(TestAnonInnerInstance1<T> t){ return null; }
+
+    public void test() {
+
+        mtest(new TestAnonInnerInstance1<T>() {
+                  class InnerAnon<U> { // Test1$1$InnerAnon.class
+                      @A @B @C @D String ia_m1(){ return null; };
+                  }
+    //If this is commented out, annotations are attributed correctly
+                  InnerAnon<String> IA = new InnerAnon< String>();
+              });
+   }
+}
+
+@Retention(RUNTIME) @Target({TYPE_USE,FIELD}) @interface A { }
+@Retention(RUNTIME) @Target({TYPE_USE,METHOD}) @interface B { }
+@Retention(CLASS) @Target({TYPE_USE,FIELD}) @interface C { }
+@Retention(CLASS) @Target({TYPE_USE,METHOD}) @interface D { }
--- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/T8008762.java	Wed Oct 16 10:47:21 2013 -0700
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/T8008762.java	Wed Oct 16 16:33:04 2013 -0400
@@ -24,7 +24,6 @@
 /*
  * @test
  * @bug 8008762
- * @ignore 8013409: test failures for type annotations
  * @summary Type annotation on inner class in anonymous class
  *          shows up as regular annotation
  */