5454 */
5555public class PatternBootstraps {
5656
57- private PatternBootstraps () {}
57+ private PatternBootstraps () {
58+ }
5859
5960 private static final Object SENTINEL = new Object ();
6061 private static final MethodHandles .Lookup LOOKUP = MethodHandles .lookup ();
@@ -67,8 +68,7 @@ private static class StaticHolders {
6768 try {
6869 SYNTHETIC_PATTERN = LOOKUP .findStatic (PatternBootstraps .class , "syntheticPattern" ,
6970 MethodType .methodType (Object .class , Method [].class , MethodHandle .class , Object .class ));
70- }
71- catch (ReflectiveOperationException e ) {
71+ } catch (ReflectiveOperationException e ) {
7272 throw new ExceptionInInitializerError (e );
7373 }
7474 }
@@ -97,13 +97,10 @@ private static class StaticHolders {
9797 * @param invocationType The invocation type of the {@code CallSite} with one parameter,
9898 * a reference type, and an {@code Object} as a return type.
9999 * @param mangledName The mangled name of the method declaration that will act as a pattern.
100- *
101100 * @return a {@code CallSite} returning the first matching element as described above
102- *
103101 * @throws NullPointerException if any argument is {@code null}
104102 * @throws IllegalArgumentException if the invocation type is not a method type of first parameter of a reference type,
105103 * and with {@code Object} as its return type,
106- *
107104 * @jvms 4.4.6 The CONSTANT_NameAndType_info Structure
108105 * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
109106 */
@@ -113,69 +110,64 @@ public static CallSite invokePattern(MethodHandles.Lookup lookup,
113110 String mangledName ) {
114111 if (invocationType .parameterCount () == 2 ) {
115112 Class <?> receiverType = invocationType .parameterType (0 );
116- Class <?> selectorType = invocationType .parameterType (1 );
113+ Class <?> matchCandidateType = invocationType .parameterType (1 );
117114 if ((!invocationType .returnType ().equals (Object .class )))
118115 throw new IllegalArgumentException ("Illegal invocation type " + invocationType );
119116
120117 MethodHandle target = null ;
121118 try {
122119 // Attempt 1: discover the pattern declaration
123- target = lookup .findStatic (receiverType , mangledName , MethodType .methodType (Object .class , receiverType , selectorType ));
120+ target = lookup .findStatic (receiverType , mangledName , MethodType .methodType (Object .class , receiverType , matchCandidateType ));
124121
125122 return new ConstantCallSite (target );
126123 } catch (Throwable t ) {
127- throw new IllegalArgumentException ("Cannot find a pattern" );
128- }
129- }
124+ // Attempt 2: synthesize the pattern declaration from the record components
125+ if (!matchCandidateType .isRecord () || !receiverType .equals (matchCandidateType )) {
126+ throw new IllegalArgumentException ("Implicit pattern invocation with erroneous match-candidate type or received type" );
127+ }
130128
131- Class <?> selectorType = invocationType .parameterType (0 );
132- if (invocationType .parameterCount () != 1
133- || (!invocationType .returnType ().equals (Object .class )))
134- throw new IllegalArgumentException ("Illegal invocation type " + invocationType );
135-
136- MethodHandle target = null ;
137- try {
138- // Attempt 1: discover the pattern declaration
139- target = lookup .findStatic (selectorType , mangledName , MethodType .methodType (Object .class , selectorType ));
140-
141- return new ConstantCallSite (target );
142- } catch (Throwable t ) {
143- // Attempt 2: synthesize the pattern declaration from the record components
144- if (!selectorType .isRecord ()) {
145- throw new IllegalArgumentException ("Cannot find a pattern" );
146- }
147-
148- String expectedMangledName = PatternBytecodeName .mangle (selectorType ,
149- Arrays .stream (selectorType .getRecordComponents ())
150- .map (RecordComponent ::getType )
151- .toArray (Class <?>[]::new ));
129+ String expectedMangledName = PatternBytecodeName .mangle (matchCandidateType ,
130+ Arrays .stream (matchCandidateType .getRecordComponents ())
131+ .map (RecordComponent ::getType )
132+ .toArray (Class <?>[]::new ));
152133
153- if (!expectedMangledName .equals (mangledName )) {
154- throw new IllegalArgumentException ("\n Unexpected pattern at use site: " + mangledName + "\n Was expecting: " + expectedMangledName );
155- }
134+ if (!expectedMangledName .equals (mangledName )) {
135+ throw new IllegalArgumentException ("Unexpected pattern at use site: " + mangledName + "(was expecting: " + expectedMangledName + ")" );
136+ }
156137
157- @ SuppressWarnings ("removal" )
158- final RecordComponent [] components = AccessController .doPrivileged (
159- (PrivilegedAction <RecordComponent []>) selectorType ::getRecordComponents );
138+ @ SuppressWarnings ("removal" )
139+ final RecordComponent [] components = AccessController .doPrivileged (
140+ (PrivilegedAction <RecordComponent []>) matchCandidateType ::getRecordComponents );
160141
161- Method [] accessors = Arrays .stream (components ).map (c -> {
162- Method accessor = c .getAccessor ();
163- accessor .setAccessible (true );
164- return accessor ;
165- }).toArray (Method []::new );
142+ Method [] accessors = Arrays .stream (components ).map (c -> {
143+ Method accessor = c .getAccessor ();
144+ accessor .setAccessible (true );
145+ return accessor ;
146+ }).toArray (Method []::new );
166147
167- Class <?>[] ctypes = Arrays .stream (components ).map (c -> c .getType ()).toArray (Class <?>[]::new );
148+ Class <?>[] ctypes = Arrays .stream (components ).map (c -> c .getType ()).toArray (Class <?>[]::new );
168149
169- Carriers .CarrierElements carrierElements = Carriers .CarrierFactory .of (ctypes );
150+ Carriers .CarrierElements carrierElements = Carriers .CarrierFactory .of (ctypes );
170151
171- MethodHandle initializingConstructor = carrierElements .initializingConstructor ();
152+ MethodHandle initializingConstructor = carrierElements .initializingConstructor ();
172153
173- MethodHandle carrierCreator = initializingConstructor .asSpreader (Object [].class , ctypes .length );
154+ MethodHandle carrierCreator = initializingConstructor .asSpreader (Object [].class , ctypes .length );
174155
175- target = MethodHandles .insertArguments (StaticHolders .SYNTHETIC_PATTERN , 0 , accessors , carrierCreator ).asType (invocationType );
156+ target =
157+ MethodHandles .dropArguments (
158+ MethodHandles .insertArguments (StaticHolders .SYNTHETIC_PATTERN ,
159+ 0 ,
160+ accessors ,
161+ carrierCreator ),
162+ 1 ,
163+ Object .class ).asType (invocationType );
176164
177- return new ConstantCallSite (target );
165+ return new ConstantCallSite (target );
166+ }
178167 }
168+
169+ // todo: static patterns will expect one parameter
170+ throw new IllegalStateException ("Pattern Invocation Illegal State" );
179171 }
180172
181173 /**
@@ -184,9 +176,8 @@ public static CallSite invokePattern(MethodHandles.Lookup lookup,
184176 *
185177 * @param matchCandidateInstance the receiver of a pattern
186178 * @param matchCandidateType the type of the match candidate
187- * @return initialized carrier object
188- *
189- * @throws Throwable throws if invocation of synthetic pattern fails
179+ * @return initialized carrier object
180+ * @throws Throwable throws if invocation of synthetic pattern fails
190181 */
191182 private static Object syntheticPattern (Method [] accessors , MethodHandle carrierCreator , Object matchCandidateInstance ) throws Throwable {
192183 Object [] extracted = Arrays .stream (accessors ).map (accessor -> {
0 commit comments