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

Print this page

        

@@ -122,11 +122,17 @@
     @Stable final Name[] names;
     final String debugName;
     MemberName vmentry;   // low-level behavior, or null if not yet prepared
     private boolean isCompiled;
 
-    Object transformCache;  // managed by LambdaFormEditor
+    volatile Object transformCache;  // managed by LambdaFormEditor
+
+    // non-null only if this is a derived LF that is cached in
+    // baseLambdaForm.transformCache. this is necessary so that base LF
+    // this LF was derived from is not GC-ed for as long as this LF is retained.
+    // no program logic is dependent on this field. just GC.
+    private final LambdaForm baseLambdaForm;
 
     public static final int VOID_RESULT = -1, LAST_RESULT = -2;
 
     enum BasicType {
         L_TYPE('L', Object.class, Wrapper.OBJECT),  // all reference types

@@ -239,13 +245,14 @@
             assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
             return true;
         }
     }
 
-    LambdaForm(String debugName,
+    LambdaForm(LambdaForm baseLambdaForm, String debugName,
                int arity, Name[] names, int result) {
         assert(namesOK(arity, names));
+        this.baseLambdaForm = baseLambdaForm;
         this.arity = arity;
         this.result = fixResult(result, names);
         this.names = names.clone();
         this.debugName = fixDebugName(debugName);
         int maxOutArity = normalize();

@@ -255,10 +262,15 @@
             compileToBytecode();
         }
     }
 
     LambdaForm(String debugName,
+               int arity, Name[] names, int result) {
+        this(null, debugName, arity, names, result);
+    }
+
+    LambdaForm(String debugName,
                int arity, Name[] names) {
         this(debugName,
              arity, names, LAST_RESULT);
     }
 

@@ -281,10 +293,11 @@
     private LambdaForm(String sig) {
         // Make a blank lambda form, which returns a constant zero or null.
         // It is used as a template for managing the invocation of similar forms that are non-empty.
         // Called only from getPreparedForm.
         assert(isValidSignature(sig));
+        this.baseLambdaForm = null;
         this.arity = signatureArity(sig);
         this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity);
         this.names = buildEmptyNames(arity, sig);
         this.debugName = "LF.zero";
         assert(nameRefsAreLegal());