Skip to content

Commit 78251fd

Browse files
committed
Add extra parameter for initialized carrier
1 parent 6dd8924 commit 78251fd

File tree

10 files changed

+100
-82
lines changed

10 files changed

+100
-82
lines changed

src/java.base/share/classes/java/lang/Class.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,11 +2157,14 @@ public Deconstructor<?>[] getDeclaredDeconstructors() throws SecurityException {
21572157
}
21582158

21592159
private Deconstructor<?>[] getDeclaredDeconstructors0(Class<?>[] params, int which) {
2160-
ArrayList<Deconstructor<?>> decs = new ArrayList<>();
21612160
if (this.isPrimitive()) return new Deconstructor<?>[0];
2162-
try(InputStream is = ClassLoader.getSystemResourceAsStream(getResourcePath())) {
2163-
byte[] bytes = is.readAllBytes();
2161+
try (var in = (getClassLoader() != null)
2162+
? getClassLoader().getResourceAsStream(getResourcePath())
2163+
: ClassLoader.getSystemResourceAsStream(getResourcePath())) {
2164+
if (in == null) throw new RuntimeException("Resource not found: " + name);
2165+
byte[] bytes = in.readAllBytes();
21642166
ClassModel cm = ClassFile.of().parse(bytes);
2167+
ArrayList<Deconstructor<?>> decs = new ArrayList<>();
21652168
for (MethodModel mm : cm.methods()) {
21662169
PatternAttribute pa = mm.findAttribute(Attributes.pattern()).orElse(null);
21672170
if (pa != null) {
@@ -2182,8 +2185,8 @@ private Deconstructor<?>[] getDeclaredDeconstructors0(Class<?>[] params, int whi
21822185
descriptorFilter = MethodTypeDesc.of(CD_void, paramDescs).descriptorString();
21832186
}
21842187

2185-
if ((params.length == 0 || (params.length != 0 && pa.patternTypeSymbol().descriptorString().equals(descriptorFilter))) &&
2186-
(which == Member.DECLARED || mm.flags().has(AccessFlag.PUBLIC))) {
2188+
if ((params.length == 0 || pa.patternTypeSymbol().descriptorString().equals(descriptorFilter)) &&
2189+
(which == Member.DECLARED || mm.flags().has(AccessFlag.PUBLIC))) {
21872190
// binding annotations
21882191
RuntimeVisibleAnnotationsAttribute rva = mm.findAttribute(Attributes.runtimeVisibleAnnotations()).orElse(null);
21892192
ByteBuffer assembled_rva = getAnnotationContents(rva != null, (BoundAttribute) rva);
@@ -2226,11 +2229,10 @@ private Deconstructor<?>[] getDeclaredDeconstructors0(Class<?>[] params, int whi
22262229
}
22272230
}
22282231
}
2232+
return decs.toArray(new Deconstructor<?>[decs.size()]);
22292233
} catch (IOException | ReflectiveOperationException e) {
22302234
throw new RuntimeException(e);
22312235
}
2232-
2233-
return decs.toArray(new Deconstructor<?>[decs.size()]);
22342236
}
22352237

22362238
private String getResourcePath() {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3361,7 +3361,7 @@ public MethodHandle unreflectDeconstructor(Deconstructor<?> d) throws IllegalAcc
33613361
return unreflect(
33623362
ownerType.getDeclaredMethod(
33633363
SharedSecrets.getJavaLangReflectAccess().getMangledName(d),
3364-
ownerType
3364+
ownerType, MethodHandle.class
33653365
)
33663366
);
33673367
} catch (NoSuchMethodException | SecurityException ex) {

src/java.base/share/classes/java/lang/reflect/MemberPattern.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import sun.reflect.generics.scope.MemberPatternScope;
3535

3636
import java.lang.annotation.Annotation;
37+
import java.lang.invoke.MethodHandle;
3738
import java.lang.invoke.MethodType;
3839
import java.lang.runtime.Carriers;
3940
import java.util.ArrayList;
@@ -401,18 +402,17 @@ public Object[] invoke(Object matchCandidate)
401402
String underlyingName = getMangledName();
402403

403404
try {
404-
Method method = getDeclaringClass().getDeclaredMethod(underlyingName, matchCandidate.getClass());
405+
Method method = getDeclaringClass().getDeclaredMethod(underlyingName, matchCandidate.getClass(), MethodHandle.class);
405406
method.setAccessible(override);
406-
return (Object[])Carriers.boxedComponentValueArray(
407-
MethodType.methodType(
407+
MethodType bindingMT = MethodType.methodType(
408408
Object.class,
409409
Arrays.stream(this.getPatternBindings())
410-
.map(PatternBinding::getType)
411-
.toArray(Class[]::new)
412-
)
413-
).invoke(
414-
method.invoke(matchCandidate, matchCandidate)
410+
.map(PatternBinding::getType)
411+
.toArray(Class[]::new)
415412
);
413+
MethodHandle initializingConstructor = Carriers.initializingConstructor(bindingMT);
414+
415+
return (Object[])Carriers.boxedComponentValueArray(bindingMT).invoke(method.invoke(matchCandidate, matchCandidate, initializingConstructor));
416416
} catch (Throwable e) {
417417
throw new MatchException(e.getMessage(), e);
418418
}

src/java.base/share/classes/java/lang/runtime/PatternBootstraps.java

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ private static class StaticHolders {
5959
static {
6060
try {
6161
SYNTHETIC_PATTERN = LOOKUP.findStatic(PatternBootstraps.class, "syntheticPattern",
62-
MethodType.methodType(Object.class, Method[].class, MethodHandle.class, Object.class));
62+
MethodType.methodType(Object.class, Method[].class, MethodHandle.class, Object.class, MethodHandle.class));
6363
} catch (ReflectiveOperationException e) {
6464
throw new ExceptionInInitializerError(e);
6565
}
@@ -107,7 +107,7 @@ public static CallSite invokePattern(MethodHandles.Lookup lookup,
107107
Class<?> matchCandidateType = invocationType.parameterType(0);
108108
try {
109109
// Attempt 1: discover the deconstructor
110-
target = lookup.findStatic(matchCandidateType, mangledName, MethodType.methodType(Object.class, matchCandidateType));
110+
target = lookup.findStatic(matchCandidateType, mangledName, MethodType.methodType(Object.class, matchCandidateType, MethodHandle.class));
111111
} catch (Throwable t) {
112112
// Attempt 2: synthesize the pattern declaration from the record components
113113
if (!matchCandidateType.isRecord()) {
@@ -130,7 +130,7 @@ public static CallSite invokePattern(MethodHandles.Lookup lookup,
130130
Class<?> receiverType = invocationType.parameterType(0);
131131
Class<?> matchCandidateType = invocationType.parameterType(1);
132132
try {
133-
target = lookup.findVirtual(receiverType, mangledName, MethodType.methodType(Object.class, matchCandidateType));
133+
target = lookup.findVirtual(receiverType, mangledName, MethodType.methodType(Object.class, matchCandidateType, MethodHandle.class));
134134
}
135135
catch (Throwable t) {
136136
throw new IllegalArgumentException("Unexpected instance pattern: " + mangledName + " (type: " + invocationType + ")");
@@ -139,7 +139,7 @@ public static CallSite invokePattern(MethodHandles.Lookup lookup,
139139
case StaticPattern -> {
140140
Class<?> matchCandidateType = invocationType.parameterType(0);
141141
try {
142-
target = lookup.findStatic(matchCandidateType, mangledName, MethodType.methodType(Object.class, matchCandidateType));
142+
target = lookup.findStatic(matchCandidateType, mangledName, MethodType.methodType(Object.class, matchCandidateType, MethodHandle.class));
143143
}
144144
catch (Throwable t) {
145145
throw new IllegalArgumentException("Unexpected static pattern: " + mangledName + " (type: " + invocationType + ")");
@@ -162,16 +162,12 @@ private static MethodHandle calculateSyntheticPatternMT(MethodType invocationTyp
162162

163163
Class<?>[] ctypes = Arrays.stream(components).map(c -> c.getType()).toArray(Class<?>[]::new);
164164

165-
Carriers.CarrierElements carrierElements = Carriers.CarrierFactory.of(ctypes);
166-
167-
MethodHandle initializingConstructor = carrierElements.initializingConstructor();
168-
169-
MethodHandle carrierCreator = initializingConstructor.asSpreader(Object[].class, ctypes.length);
165+
MethodHandle spreaderInvoker = MethodHandles.spreadInvoker(MethodType.methodType(Object.class, ctypes), 0);
170166

171167
return MethodHandles.insertArguments(StaticHolders.SYNTHETIC_PATTERN,
172168
0,
173169
accessors,
174-
carrierCreator).asType(invocationType);
170+
spreaderInvoker).asType(invocationType);
175171
}
176172

177173
enum PatternUseSite {
@@ -181,11 +177,11 @@ enum PatternUseSite {
181177
}
182178
static PatternUseSite detectPatternUseSite(MethodType invocationType,
183179
String mangledName) {
184-
if (invocationType.parameterCount() == 1 && mangledName.startsWith(DINIT + ':')) {
180+
if (invocationType.parameterCount() == 2 && mangledName.startsWith(DINIT + ':')) {
185181
return PatternUseSite.Deconstructor;
186-
} else if (invocationType.parameterCount() == 1) {
187-
return PatternUseSite.StaticPattern;
188182
} else if (invocationType.parameterCount() == 2) {
183+
return PatternUseSite.StaticPattern;
184+
} else if (invocationType.parameterCount() == 3) {
189185
return PatternUseSite.InstancePattern;
190186
} else if ((!invocationType.returnType().equals(Object.class))) {
191187
throw new IllegalArgumentException("Illegal return type: " + invocationType);
@@ -203,7 +199,7 @@ static PatternUseSite detectPatternUseSite(MethodType invocationType,
203199
* @return initialized carrier object
204200
* @throws Throwable throws if invocation of synthetic pattern fails
205201
*/
206-
private static Object syntheticPattern(Method[] accessors, MethodHandle carrierCreator, Object matchCandidateInstance) throws Throwable {
202+
private static Object syntheticPattern(Method[] accessors, MethodHandle spreaderInvoker, Object matchCandidateInstance, MethodHandle carrierCreator) throws Throwable {
207203
Object[] extracted = Arrays.stream(accessors).map(accessor -> {
208204
try {
209205
return accessor.invoke(matchCandidateInstance);
@@ -214,8 +210,8 @@ private static Object syntheticPattern(Method[] accessors, MethodHandle carrierC
214210
}
215211
}).toArray();
216212

217-
Object carrier = carrierCreator.invoke(extracted);
213+
Object initializedCarrier = spreaderInvoker.invoke(carrierCreator, extracted);
218214

219-
return carrier;
215+
return initializedCarrier;
220216
}
221217
}

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2661,6 +2661,14 @@ public void visitMethodDef(JCMethodDecl tree) {
26612661
tree.sym.flags_field |= SYNTHETIC;
26622662
tree.mods.flags |= SYNTHETIC;
26632663

2664+
// add carrier as the last parameter
2665+
JCVariableDecl carrier = make_at(tree.pos()).
2666+
Param(names.fromString("carrierMH"), syms.methodHandleType, tree.sym);
2667+
carrier.mods.flags |= SYNTHETIC;
2668+
carrier.sym.flags_field |= SYNTHETIC;
2669+
tree.params = tree.params.prepend(carrier);
2670+
tree.sym.params = tree.sym.params.prepend(carrier.sym);
2671+
26642672
// match-candidate parameter
26652673
if (tree.sym.isInstancePattern() || tree.sym.isStaticPattern()) {
26662674
JCVariableDecl implicitThatParam = tree.getMatchCandidateParameter();
@@ -2691,6 +2699,7 @@ public void visitMethodDef(JCMethodDecl tree) {
26912699
if (tree.sym.isDeconstructor()) {
26922700
argtypes = argtypes.prepend(tree.sym.owner.type);
26932701
}
2702+
argtypes = argtypes.append(syms.methodHandleType);
26942703

26952704
if (tree.sym.isStaticPattern() || tree.sym.isDeconstructor()) {
26962705
tree.mods.flags |= STATIC;
@@ -2704,6 +2713,17 @@ public void visitMethodDef(JCMethodDecl tree) {
27042713
syms.methodClass);
27052714

27062715
m.erasure_field = mt;
2716+
2717+
// create the call carrier.invoke(<carrier arguments>) to initialize the carrier
2718+
// those argument are precalculated by the TransPatterns:visitMatch
2719+
JCMethodInvocation invokeMethodCall = makeCall(
2720+
make.Ident(carrier),
2721+
names.fromString("invoke"),
2722+
tree.carrierArguments);
2723+
2724+
tree.body.stats = tree.body.stats.appendList(List.of(
2725+
make.Return(invokeMethodCall),
2726+
make.Throw(makeNewClass(syms.matchExceptionType, List.of(makeNull(), makeNull())))));
27072727
}
27082728

27092729
Type prevRestype = currentRestype;

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
import com.sun.tools.javac.code.Kinds;
3333
import com.sun.tools.javac.code.Kinds.Kind;
3434

35-
import static com.sun.tools.javac.code.TypeTag.*;
36-
3735
import com.sun.tools.javac.code.Preview;
3836
import com.sun.tools.javac.code.Source;
3937
import com.sun.tools.javac.code.Symbol;
@@ -410,13 +408,31 @@ private UnrolledRecordPattern unrollRecordPattern(JCRecordPattern recordPattern)
410408
Assert.check(recordPattern.patternDeclaration != null);
411409

412410
if (allowPatternDeclarations) {
411+
// Generate:
412+
// 1. calculate the returnType MethodType as Constant_MethodType_info
413+
// 2. generate factory code on carrier for the types we want (e.g., Object carrier = Carriers.initializingConstructor(returnType);)
414+
// 3. generate invoke call to pass the bindings (e.g, return carrier.invoke(x, y);)
415+
MethodSymbol factoryMethodSym =
416+
rs.resolveInternalMethod(recordPattern.pos(),
417+
env,
418+
syms.carriersType,
419+
names.fromString("initializingConstructor"),
420+
List.of(syms.methodTypeType),
421+
List.nil());
422+
DynamicVarSymbol factoryMethodDynamicVar =
423+
(DynamicVarSymbol) invokeMethodWrapper(
424+
names.fromString("carrier"),
425+
recordPattern.pos(),
426+
factoryMethodSym.asHandle(),
427+
new MethodType(recordPattern.patternDeclaration.type.getBindingTypes(), syms.objectType, List.nil(), syms.methodClass));
428+
413429
mSymbol = new BindingSymbol(Flags.SYNTHETIC,
414430
names.fromString(target.syntheticNameChar() + "m" + target.syntheticNameChar() + variableIndex++), syms.objectType,
415431
currentMethodSym);
416432
JCVariableDecl mVar = make.VarDef(mSymbol, null);
417433

418434
firstLevelChecks = make.TypeTest(
419-
generatePatternCall(recordPattern, tempBind),
435+
generatePatternCall(recordPattern, tempBind, factoryMethodDynamicVar),
420436
make.BindingPattern(mVar).setType(mSymbol.type)).setType(syms.booleanType);
421437

422438
// Resolve Carriers.component(methodType, index) for subsequent constant dynamic call results
@@ -534,7 +550,7 @@ private UnrolledRecordPattern unrollRecordPattern(JCRecordPattern recordPattern)
534550
return new UnrolledRecordPattern((JCBindingPattern) make.BindingPattern(recordBindingVar).setType(recordBinding.type), guard);
535551
}
536552

537-
private JCMethodInvocation generatePatternCall(JCRecordPattern recordPattern, BindingSymbol matchCandidate) {
553+
private JCMethodInvocation generatePatternCall(JCRecordPattern recordPattern, BindingSymbol matchCandidate, DynamicVarSymbol factoryMethodDynamicVar) {
538554
List<Type> staticArgTypes = List.of(syms.methodHandleLookupType,
539555
syms.stringType,
540556
syms.methodTypeType,
@@ -549,16 +565,16 @@ private JCMethodInvocation generatePatternCall(JCRecordPattern recordPattern, Bi
549565

550566
// deconstructors, instance patterns and static patterns
551567
if (recordPattern.deconstructor instanceof JCFieldAccess acc && !TreeInfo.isStaticSelector(acc.selected, names)) {
552-
/*receiver , match candidate */
553-
invocationParamTypes = List.of(acc.selected.type , recordPattern.type);
554-
invocationParams = List.of(acc.selected , make.Ident(matchCandidate));
568+
/*receiver , match candidate carrier method handle */
569+
invocationParamTypes = List.of(acc.selected.type , recordPattern.type, factoryMethodDynamicVar.type);
570+
invocationParams = List.of(acc.selected , make.Ident(matchCandidate), make.Ident(factoryMethodDynamicVar));
555571
} else if (!recordPattern.patternDeclaration.isStatic() && !recordPattern.patternDeclaration.isDeconstructor()) {
556-
invocationParamTypes = List.of(recordPattern.type , recordPattern.type);
557-
invocationParams = List.of(make.Ident(matchCandidate), make.Ident(matchCandidate));
572+
invocationParamTypes = List.of(recordPattern.type , recordPattern.type, factoryMethodDynamicVar.type);
573+
invocationParams = List.of(make.Ident(matchCandidate), make.Ident(matchCandidate), make.Ident(factoryMethodDynamicVar));
558574
}
559575
else {
560-
invocationParams = List.of(make.Ident(matchCandidate));
561-
invocationParamTypes = List.of(recordPattern.type);
576+
invocationParamTypes = List.of(recordPattern.type, factoryMethodDynamicVar.type);
577+
invocationParams = List.of(make.Ident(matchCandidate), make.Ident(factoryMethodDynamicVar) );
562578
}
563579
MethodType indyType = new MethodType(
564580
invocationParamTypes,
@@ -1006,7 +1022,6 @@ private Symbol.DynamicVarSymbol makeBooleanConstant(DiagnosticPosition pos, int
10061022
* <pre>{@code
10071023
* binding1 = arg1;
10081024
* binding2 = arg2;
1009-
* return carrier.invoke(binding1, binding2);
10101025
* }</pre>
10111026
*
10121027
*/
@@ -1019,27 +1034,10 @@ public void visitMatch(JCMatch tree) {
10191034

10201035
ListBuffer<JCStatement> stats = new ListBuffer<>();
10211036

1022-
// Generate:
1023-
// 1. calculate the returnType MethodType as Constant_MethodType_info
1024-
// 2. generate factory code on carrier for the types we want (e.g., Object carrier = Carriers.initializingConstructor(returnType);)
1025-
// 3. generate invoke call to pass the bindings (e.g, return carrier.invoke(x, y);)
1026-
MethodSymbol factoryMethodSym =
1027-
rs.resolveInternalMethod(tree.pos(),
1028-
env,
1029-
syms.carriersType,
1030-
names.fromString("initializingConstructor"),
1031-
List.of(syms.methodTypeType),
1032-
List.nil());
1033-
1034-
DynamicVarSymbol factoryMethodDynamicVar =
1035-
(DynamicVarSymbol) invokeMethodWrapper(
1036-
names.fromString("carrier"),
1037-
tree.pos(),
1038-
factoryMethodSym.asHandle(),
1039-
new MethodType(tree.meth.type.getBindingTypes(), syms.objectType, List.nil(), syms.methodClass));
1040-
1037+
// force the evaluation of each parameter to match
10411038
// Generate:
10421039
// parameter1 = arg1;
1040+
// ...
10431041
while (matchArguments.nonEmpty() && bindings.nonEmpty() && bindingTypes.nonEmpty()) {
10441042
JCExpressionStatement stat =
10451043
make.Exec(make.Assign(make.Ident(bindings.head),
@@ -1053,12 +1051,10 @@ public void visitMatch(JCMatch tree) {
10531051
matchArguments = matchArguments.tail;
10541052
}
10551053

1056-
JCIdent factoryMethodCall = make.Ident(factoryMethodDynamicVar);
1054+
// the same parameters must be passed to the carrier.invoke(<carrier arguments>)
1055+
// that is emitted in Lower:visitMethodDef
1056+
tree.meth.carrierArguments = invokeMethodParam;
10571057

1058-
JCMethodInvocation invokeMethodCall =
1059-
makeApply(factoryMethodCall, names.fromString("invoke"), invokeMethodParam);
1060-
1061-
stats = stats.append(make.Return(invokeMethodCall));
10621058
result = make.at(tree.pos).Block(0, stats.toList());
10631059
}
10641060

@@ -1456,10 +1452,6 @@ public void visitMethodDef(JCMethodDecl tree) {
14561452
currentMethodSym = tree.sym;
14571453
variableIndex = 0;
14581454
deconstructorCalls = null;
1459-
if (tree.sym.isPattern()) {
1460-
tree.body.stats = tree.body.stats.append(
1461-
make.Throw(makeNewClass(syms.matchExceptionType, List.of(makeNull(), makeNull()))));
1462-
}
14631455
super.visitMethodDef(tree);
14641456
preparePatternMatchingCatchIfNeeded(tree.body);
14651457
} finally {

0 commit comments

Comments
 (0)