< prev index next >

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

Print this page
*** 1,7 ***
  /*
!  * Copyright (c) 2012, 2021, 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.  Oracle designates this
--- 1,7 ---
  /*
!  * Copyright (c) 2012, 2024, 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.  Oracle designates this

*** 249,10 ***
--- 249,14 ---
       * Flag for alternate metafactories indicating the lambda object requires
       * additional methods that invoke the {@code implementation}
       */
      public static final int FLAG_BRIDGES = 1 << 2;
  
+     /** Flag for {@link #altMetafactory} indicating the lambda object
+      * must be a {@code Quotable} object, inspectable using code reflection. */
+     public static final int FLAG_QUOTABLE = 1 << 3;
+ 
      private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
      private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
  
      // LambdaMetafactory bootstrap methods are startup sensitive, and may be
      // special cased in java.lang.invoke.BootstrapMethodInvoker to ensure

*** 334,11 ***
                                               Objects.requireNonNull(interfaceMethodType),
                                               Objects.requireNonNull(implementation),
                                               Objects.requireNonNull(dynamicMethodType),
                                               false,
                                               EMPTY_CLASS_ARRAY,
!                                              EMPTY_MT_ARRAY);
          mf.validateMetafactoryArgs();
          return mf.buildCallSite();
      }
  
      /**
--- 338,12 ---
                                               Objects.requireNonNull(interfaceMethodType),
                                               Objects.requireNonNull(implementation),
                                               Objects.requireNonNull(dynamicMethodType),
                                               false,
                                               EMPTY_CLASS_ARRAY,
!                                              EMPTY_MT_ARRAY,
+                                  null);
          mf.validateMetafactoryArgs();
          return mf.buildCallSite();
      }
  
      /**

*** 380,10 ***
--- 385,11 ---
       *                          int flags,
       *                          int altInterfaceCount,        // IF flags has MARKERS set
       *                          Class... altInterfaces,       // IF flags has MARKERS set
       *                          int altMethodCount,           // IF flags has BRIDGES set
       *                          MethodType... altMethods      // IF flags has BRIDGES set
+      *                          MethodHandle quotableField    // IF flags has QUOTABLE set
       *                          )
       * }</pre>
       *
       * <p>Arguments that appear in the argument list for
       * {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}

*** 403,10 ***
--- 409,14 ---
       *     the function object should implement, and is present if and only if
       *     the {@code FLAG_BRIDGES} flag is set.</li>
       *     <li>{@code altMethods} is a variable-length list of additional
       *     methods signatures to implement, whose length equals {@code altMethodCount},
       *     and is present if and only if the {@code FLAG_BRIDGES} flag is set.</li>
+      *     <li>{@code quotableField} is a
+      *     {@linkplain MethodHandles.Lookup#findGetter(Class, String, Class) getter} method handle
+      *     that is used to retrieve the string representation of the quotable lambda's associated
+      *     intermediate representation.</li>
       * </ul>
       *
       * <p>Each class named by {@code altInterfaces} is subject to the same
       * restrictions as {@code Rd}, the return type of {@code factoryType},
       * as described {@link LambdaMetafactory above}.  Each {@code MethodType}

*** 417,10 ***
--- 427,13 ---
       * will implement {@code Serializable}, and will have a {@code writeReplace}
       * method that returns an appropriate {@link SerializedLambda}.  The
       * {@code caller} class must have an appropriate {@code $deserializeLambda$}
       * method, as described in {@link SerializedLambda}.
       *
+      * <p>When FLAG_QUOTABLE is set in {@code flags}, the function objects
+      * will implement {@code Quotable}.
+      *
       * <p>When the target of the {@code CallSite} returned from this method is
       * invoked, the resulting function objects are instances of a class with
       * the following properties:
       * <ul>
       *     <li>The class implements the interface named by the return type

*** 485,10 ***
--- 498,11 ---
          MethodHandle implementation = extractArg(args, argIndex++, MethodHandle.class);
          MethodType dynamicMethodType = extractArg(args, argIndex++, MethodType.class);
          int flags = extractArg(args, argIndex++, Integer.class);
          Class<?>[] altInterfaces = EMPTY_CLASS_ARRAY;
          MethodType[] altMethods = EMPTY_MT_ARRAY;
+         MethodHandle quotableField = null;
          if ((flags & FLAG_MARKERS) != 0) {
              int altInterfaceCount = extractArg(args, argIndex++, Integer.class);
              if (altInterfaceCount < 0) {
                  throw new IllegalArgumentException("negative argument count");
              }

*** 505,10 ***
--- 519,15 ---
              if (altMethodCount > 0) {
                  altMethods = extractArgs(args, argIndex, MethodType.class, altMethodCount);
                  argIndex += altMethodCount;
              }
          }
+         if ((flags & FLAG_QUOTABLE) != 0) {
+             quotableField = extractArg(args, argIndex++, MethodHandle.class);
+             altInterfaces = Arrays.copyOf(altInterfaces, altInterfaces.length + 1);
+             altInterfaces[altInterfaces.length-1] = InnerClassLambdaMetafactory.CodeReflectionSupport.QUOTABLE_CLASS;
+         }
          if (argIndex < args.length) {
              throw new IllegalArgumentException("too many arguments");
          }
  
          boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);

*** 529,11 ***
                                                    interfaceMethodType,
                                                    implementation,
                                                    dynamicMethodType,
                                                    isSerializable,
                                                    altInterfaces,
!                                                   altMethods);
          mf.validateMetafactoryArgs();
          return mf.buildCallSite();
      }
  
      private static <T> T extractArg(Object[] args, int index, Class<T> type) {
--- 548,12 ---
                                                    interfaceMethodType,
                                                    implementation,
                                                    dynamicMethodType,
                                                    isSerializable,
                                                    altInterfaces,
!                                                   altMethods,
+                                                   quotableField);
          mf.validateMetafactoryArgs();
          return mf.buildCallSite();
      }
  
      private static <T> T extractArg(Object[] args, int index, Class<T> type) {
< prev index next >