< prev index next >

src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java

Print this page
rev 12972 : 8131129: Attempt to define a duplicate BMH$Species class

@@ -394,23 +394,25 @@
             SpeciesData d = lookupCache(types);
             if (!d.isPlaceholder())
                 return d;
             synchronized (d) {
                 // Use synch. on the placeholder to prevent multiple instantiation of one species.
-                // Creating this class forces a recursive call to getForClass.
-                if (lookupCache(types).isPlaceholder())
-                    Factory.generateConcreteBMHClass(types);
-            }
-            // Reacquire cache lock.
-            d = lookupCache(types);
-            // Class loading must have upgraded the cache.
-            assert(d != null && !d.isPlaceholder());
+                SpeciesData d2 = lookupCache(types);
+                if (d2.isPlaceholder()) {
+                    Class<? extends BoundMethodHandle> bmhcl = Factory.generateConcreteBMHClass(types);
+                    // install new SpeciesData into cache
+                    d2 = Factory.speciesDataFromConcreteBMHClass(bmhcl);
+                    assert(!d2.isPlaceholder());
+                    updateCache(d2.typeChars, d2);
+                }
+                d = d2;
+            }
             return d;
         }
         static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
             // clazz is a new class which is initializing its SPECIES_DATA field
-            return updateCache(types, new SpeciesData(types, clazz));
+            return new SpeciesData(types, clazz);
         }
         private static synchronized SpeciesData lookupCache(String types) {
             SpeciesData d = CACHE.get(types);
             if (d != null)  return d;
             d = new SpeciesData(types);

@@ -434,11 +436,11 @@
                     if (rootCls.isAssignableFrom(c)) {
                         final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
                         SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
                         assert(d != null) : cbmh.getName();
                         assert(d.clazz == cbmh);
-                        assert(d == lookupCache(d.typeChars));
+                        updateCache(d.typeChars, d);
                     }
                 }
             } catch (Throwable e) {
                 throw newInternalError(e);
             }

@@ -584,24 +586,21 @@
             mv = cw.visitMethod(ACC_PRIVATE, "<init>", makeSignature(types, true), null, null);
             mv.visitCode();
             mv.visitVarInsn(ALOAD, 0); // this
             mv.visitVarInsn(ALOAD, 1); // type
             mv.visitVarInsn(ALOAD, 2); // form
-
             mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true), false);
-
             for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
                 // i counts the arguments, j counts corresponding argument slots
                 char t = types.charAt(i);
                 mv.visitVarInsn(ALOAD, 0);
                 mv.visitVarInsn(typeLoadOp(t), j + 3); // parameters start at 3
                 mv.visitFieldInsn(PUTFIELD, className, makeFieldName(types, i), typeSig(t));
                 if (t == 'J' || t == 'D') {
                     ++j; // adjust argument register access
                 }
             }
-
             mv.visitInsn(RETURN);
             mv.visitMaxs(0, 0);
             mv.visitEnd();
 
             // emit implementation of speciesData()

@@ -622,10 +621,11 @@
                 mv.visitIntInsn(SIPUSH, fc);
             }
             mv.visitInsn(IRETURN);
             mv.visitMaxs(0, 0);
             mv.visitEnd();
+
             // emit make()  ...factory method wrapping constructor
             mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_STATIC, "make", makeSignature(types, false), null, null);
             mv.visitCode();
             // make instance
             mv.visitTypeInsn(NEW, className);

@@ -640,11 +640,10 @@
                 mv.visitVarInsn(typeLoadOp(t), j + 2); // parameters start at 3
                 if (t == 'J' || t == 'D') {
                     ++j; // adjust argument register access
                 }
             }
-
             // finally, invoke the constructor and return
             mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false);
             mv.visitInsn(ARETURN);
             mv.visitMaxs(0, 0);
             mv.visitEnd();
< prev index next >