< prev index next >

src/java.base/share/classes/java/lang/constant/ConstantUtils.java

Print this page
rev 52749 : Bootstrap method consolidation
* clean up and simplify JDK support code for BSM invocation
* simplify JVM bootstrap handshake: use BootstrapCallInfo only
* remove unused JVM paths and data fields
* move bootstrap argument processing from MethodHandleNatives to ConstantPool
* remove ConstantGroup; merge argument access into BootstrapCallInfo
* adjust BSM argument access: remove copyArguments, add argumentRef API
* add metadata-free BSM modes, including symbolic arguments from CP


  55      * validates a member name
  56      * @param name the name of the member
  57      * @return the name passed if valid
  58      */
  59     public static String validateMemberName(String name) {
  60         requireNonNull(name);
  61         if (name.length() == 0)
  62             throw new IllegalArgumentException("zero-length member name");
  63         for (int i=0; i<name.length(); i++) {
  64             char ch = name.charAt(i);
  65             if (ch == '.' || ch == ';' || ch == '[' || ch == '/')
  66                 throw new IllegalArgumentException("Invalid member name: " + name);
  67             if (ch == '<' || ch == '>') {
  68                 if (!pointyNames.contains(name))
  69                     throw new IllegalArgumentException("Invalid member name: " + name);
  70             }
  71         }
  72         return name;
  73     }
  74 


































  75     static void validateClassOrInterface(ClassDesc clazz) {
  76         if (!clazz.isClassOrInterface())
  77             throw new IllegalArgumentException("not a class or interface type: " + clazz);
  78     }
  79 
  80     static int arrayDepth(String descriptorString) {
  81         int depth = 0;
  82         while (descriptorString.charAt(depth) == '[')
  83             depth++;
  84         return depth;
  85     }
  86 
  87     static String binaryToInternal(String name) {
  88         return name.replace('.', '/');
  89     }
  90 
  91     static String internalToBinary(String name) {
  92         return name.replace('/', '.');
  93     }
  94 
  95     static String dropLastChar(String s) {
  96         return s.substring(0, s.length() - 1);
  97     }
  98 
  99     static String dropFirstAndLastChar(String s) {
 100         return s.substring(1, s.length() - 1);
 101     }
 102 
 103     /**
 104      * Produce an {@code Optional<DynamicConstantDesc<T>>} describing the invocation
 105      * of the specified bootstrap with the specified arguments.  The arguments will
 106      * be converted to nominal descriptors using the provided lookup.  Helper
 107      * method for implementing {@link Constable#describeConstable()}.
 108      *
 109      * @param <T> the type of the resulting constant
 110      * @param bootstrap nominal descriptor for the bootstrap method
 111      * @param type nominal descriptor for the type of the resulting constant
 112      * @param args nominal descriptors for the bootstrap arguments
 113      * @return the nominal descriptor for the dynamic constant
 114      */
 115     public static<T> Optional<DynamicConstantDesc<T>> symbolizeHelper(MethodHandleDesc bootstrap,
 116                                                                       ClassDesc type,
 117                                                                       Constable<?>... args) {
 118         requireNonNull(bootstrap);
 119         requireNonNull(type);
 120         requireNonNull(args);
 121         try {
 122             ConstantDesc<?>[] quotedArgs = new ConstantDesc<?>[args.length + 1];
 123             quotedArgs[0] = bootstrap;
 124             for (int i=0; i<args.length; i++)
 125                 quotedArgs[i+1] = args[i].describeConstable().orElseThrow();
 126             return Optional.of(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE,
 127                                                            ConstantDescs.DEFAULT_NAME,
 128                                                            type, quotedArgs));
 129         }
 130         catch (NoSuchElementException e) {
 131             return Optional.empty();
 132         }
 133     }
 134 
 135     /**
 136      * Parse a method descriptor string, and return a list of field descriptor
 137      * strings, return type first, then parameter types
 138      *
 139      * @param descriptor the descriptor string
 140      * @return the list of types
 141      * @throws IllegalArgumentException if the descriptor string is not valid
 142      */
 143     static List<String> parseMethodDescriptor(String descriptor) {
 144         int cur = 0, end = descriptor.length();
 145         ArrayList<String> ptypes = new ArrayList<>();
 146 
 147         if (cur >= end || descriptor.charAt(cur) != '(')
 148             throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
 149 
 150         ++cur;  // skip '('
 151         while (cur < end && descriptor.charAt(cur) != ')') {
 152             int len = matchSig(descriptor, cur, end);
 153             if (len == 0 || descriptor.charAt(cur) == 'V')
 154                 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
 155             ptypes.add(descriptor.substring(cur, cur + len));




  55      * validates a member name
  56      * @param name the name of the member
  57      * @return the name passed if valid
  58      */
  59     public static String validateMemberName(String name) {
  60         requireNonNull(name);
  61         if (name.length() == 0)
  62             throw new IllegalArgumentException("zero-length member name");
  63         for (int i=0; i<name.length(); i++) {
  64             char ch = name.charAt(i);
  65             if (ch == '.' || ch == ';' || ch == '[' || ch == '/')
  66                 throw new IllegalArgumentException("Invalid member name: " + name);
  67             if (ch == '<' || ch == '>') {
  68                 if (!pointyNames.contains(name))
  69                     throw new IllegalArgumentException("Invalid member name: " + name);
  70             }
  71         }
  72         return name;
  73     }
  74 
  75     /**
  76      * validates a bootstrap method: must have a leading Lookup parameter, or else be a valid expression-mode BSM
  77      * @param bootstrapMethod the method to validate
  78      * @param constantName the name associated with the proposed {@code CONSTANT_Dynamic} constant
  79      * @return the method passed if valid
  80      */
  81     public static DirectMethodHandleDesc validateBootstrapMethod(DirectMethodHandleDesc bootstrapMethod, String constantName) {
  82         if (hasLeadingLookupParameter(bootstrapMethod)) return bootstrapMethod;
  83         switch (constantName) {
  84         case ConstantDescs.INVOKE_NAME:
  85         case ConstantDescs.SYMBOLIC_NAME:
  86             return bootstrapMethod;
  87         }
  88         throw new IllegalArgumentException("Invalid bootstrap method: " + bootstrapMethod + " with reserved invocation name " + constantName);
  89     }
  90 
  91     /**
  92      * validates an expression-mode bootstrap method: must not have a leading Lookup parameter
  93      * @param bootstrapMethod the method to validate
  94      * @param constantName the name associated with the proposed {@code CONSTANT_Dynamic} constant
  95      * @return the method passed if valid
  96      */
  97     public static DirectMethodHandleDesc validateExpressionModeBootstrapMethod(DirectMethodHandleDesc bootstrapMethod, String constantName) {
  98         if (hasLeadingLookupParameter(bootstrapMethod)) {
  99                 throw new IllegalArgumentException("Bootstrap method has leading Lookup parameter: " + bootstrapMethod);
 100         }
 101         return validateBootstrapMethod(bootstrapMethod, constantName);
 102     }
 103 
 104     private static boolean hasLeadingLookupParameter(DirectMethodHandleDesc bootstrapMethod) {
 105         MethodTypeDesc type = bootstrapMethod.methodType();
 106         return (type.parameterCount() > 0 && type.parameterType(0).equals(ConstantDescs.CR_MethodHandles_Lookup));
 107     }
 108 
 109     static void validateClassOrInterface(ClassDesc clazz) {
 110         if (!clazz.isClassOrInterface())
 111             throw new IllegalArgumentException("not a class or interface type: " + clazz);
 112     }
 113 
 114     static int arrayDepth(String descriptorString) {
 115         int depth = 0;
 116         while (descriptorString.charAt(depth) == '[')
 117             depth++;
 118         return depth;
 119     }
 120 
 121     static String binaryToInternal(String name) {
 122         return name.replace('.', '/');
 123     }
 124 
 125     static String internalToBinary(String name) {
 126         return name.replace('/', '.');
 127     }
 128 
 129     static String dropLastChar(String s) {
 130         return s.substring(0, s.length() - 1);
 131     }
 132 
 133     static String dropFirstAndLastChar(String s) {
 134         return s.substring(1, s.length() - 1);
 135     }
 136 
 137     /**
































 138      * Parse a method descriptor string, and return a list of field descriptor
 139      * strings, return type first, then parameter types
 140      *
 141      * @param descriptor the descriptor string
 142      * @return the list of types
 143      * @throws IllegalArgumentException if the descriptor string is not valid
 144      */
 145     static List<String> parseMethodDescriptor(String descriptor) {
 146         int cur = 0, end = descriptor.length();
 147         ArrayList<String> ptypes = new ArrayList<>();
 148 
 149         if (cur >= end || descriptor.charAt(cur) != '(')
 150             throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
 151 
 152         ++cur;  // skip '('
 153         while (cur < end && descriptor.charAt(cur) != ')') {
 154             int len = matchSig(descriptor, cur, end);
 155             if (len == 0 || descriptor.charAt(cur) == 'V')
 156                 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
 157             ptypes.add(descriptor.substring(cur, cur + len));


< prev index next >