Skip to content

Commit

Permalink
Compiler Implementation for Matchers
Browse files Browse the repository at this point in the history
Co-authored-by: Jan Lahoda <[email protected]>
Co-authored-by: Angelos Bimpoudis <[email protected]>
  • Loading branch information
biboudis and lahodaj committed Sep 6, 2023
1 parent 024133b commit a91ed49
Show file tree
Hide file tree
Showing 41 changed files with 1,020 additions and 150 deletions.
10 changes: 8 additions & 2 deletions src/java.base/share/classes/java/lang/reflect/AccessFlag.java
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,7 @@ public Set<Location> apply(ClassFileFormatVersion cffv) {
return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
Location.SET_CLASS:
Location.EMPTY_SET;}
})
;
});

// May want to override toString for a different enum constant ->
// name mapping.
Expand Down Expand Up @@ -532,6 +531,11 @@ public enum Location {
*/
METHOD,

/**
* Matcher location.
*/
MATCHER,

/**
* Inner class location.
* @jvms 4.7.6 The InnerClasses Attribute
Expand Down Expand Up @@ -585,6 +589,8 @@ public enum Location {
Set.of(FIELD, METHOD);
private static final Set<Location> SET_FIELD_METHOD_INNER_CLASS =
Set.of(FIELD, METHOD, INNER_CLASS);
private static final Set<Location> SET_MATCHER = Set.of(MATCHER);

private static final Set<Location> SET_METHOD = Set.of(METHOD);
private static final Set<Location> SET_METHOD_PARAM = Set.of(METHOD_PARAMETER);
private static final Set<Location> SET_FIELD = Set.of(FIELD);
Expand Down
17 changes: 14 additions & 3 deletions src/java.base/share/classes/java/lang/runtime/Carriers.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
* Warning: This class is part of PreviewFeature.Feature.STRING_TEMPLATES.
* Do not rely on its availability.
*/
final class Carriers {
public final class Carriers {
/**
* Maximum number of components in a carrier (based on the maximum
* number of args to a constructor.)
Expand Down Expand Up @@ -926,6 +926,17 @@ static Class<?> carrierClass(MethodType methodType) {
return CarrierFactory.of(methodType).carrierClass();
}

/**
* XXX
*
* @param methodType {@link MethodType} whose parameter types supply the shape of the
* carrier's components
* @return the factory for the carrier of the given shape
*/
public static MethodHandle factory(MethodType methodType) {
return initializingConstructor(methodType);
}

/**
* {@return the constructor {@link MethodHandle} for the carrier representing {@code
* methodType}. The carrier constructor will always have a return type of {@link Object} }
Expand Down Expand Up @@ -976,7 +987,7 @@ static MethodHandle initializingConstructor(MethodType methodType) {
* @param methodType {@link MethodType} whose parameter types supply the shape of the
* carrier's components
*/
static List<MethodHandle> components(MethodType methodType) {
public static List<MethodHandle> components(MethodType methodType) {
return CarrierFactory
.of(methodType)
.components()
Expand All @@ -996,7 +1007,7 @@ static List<MethodHandle> components(MethodType methodType) {
*
* @throws IllegalArgumentException if {@code i} is out of bounds
*/
static MethodHandle component(MethodType methodType, int i) {
public static MethodHandle component(MethodType methodType, int i) {
MethodHandle component = CarrierFactory.of(methodType).component(i);
component = component.asType(component.type().changeParameterType(0, Object.class));
return component;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ static AccessFlags ofClass(int mask) {
return new AccessFlagsImpl(AccessFlag.Location.CLASS, mask);
}

/**
* {@return an {@linkplain AccessFlags} for a matcher}
* @param mask the flags to be set, as a bit mask
*/
static AccessFlags ofMatcher(int mask) {
return new AccessFlagsImpl(AccessFlag.Location.MATCHER, mask);
}

/**
* {@return an {@linkplain AccessFlags} for a class}
* @param flags the flags to be set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import jdk.internal.classfile.attribute.LineNumberTableAttribute;
import jdk.internal.classfile.attribute.LocalVariableTableAttribute;
import jdk.internal.classfile.attribute.LocalVariableTypeTableAttribute;
import jdk.internal.classfile.attribute.MatcherAttribute;
import jdk.internal.classfile.attribute.MethodParametersAttribute;
import jdk.internal.classfile.attribute.ModuleAttribute;
import jdk.internal.classfile.attribute.ModuleHashesAttribute;
Expand Down Expand Up @@ -81,7 +82,7 @@ public sealed interface Attribute<A extends Attribute<A>>
ConstantValueAttribute, DeprecatedAttribute, EnclosingMethodAttribute,
ExceptionsAttribute, InnerClassesAttribute, LineNumberTableAttribute,
LocalVariableTableAttribute, LocalVariableTypeTableAttribute,
MethodParametersAttribute, ModuleAttribute, ModuleHashesAttribute,
MatcherAttribute, MethodParametersAttribute, ModuleAttribute, ModuleHashesAttribute,
ModuleMainClassAttribute, ModulePackagesAttribute, ModuleResolutionAttribute,
ModuleTargetAttribute, NestHostAttribute, NestMembersAttribute,
PermittedSubclassesAttribute,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.List;
import java.util.Optional;

import jdk.internal.classfile.attribute.MatcherAttribute;
import jdk.internal.classfile.attribute.RecordComponentInfo;
import jdk.internal.classfile.impl.AbstractUnboundModel;

Expand All @@ -36,7 +37,7 @@
* as a class, field, method, code attribute, or record component.
*/
public sealed interface AttributedElement extends ClassfileElement
permits ClassModel, CodeModel, FieldModel, MethodModel,
permits ClassModel, CodeModel, FieldModel, MethodModel, MatcherAttribute,
RecordComponentInfo, AbstractUnboundModel {

/**
Expand Down
22 changes: 22 additions & 0 deletions src/java.base/share/classes/jdk/internal/classfile/Attributes.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import jdk.internal.classfile.attribute.LocalVariableTableAttribute;
import jdk.internal.classfile.attribute.LocalVariableTypeInfo;
import jdk.internal.classfile.attribute.LocalVariableTypeTableAttribute;
import jdk.internal.classfile.attribute.MatcherAttribute;
import jdk.internal.classfile.attribute.MethodParameterInfo;
import jdk.internal.classfile.attribute.MethodParametersAttribute;
import jdk.internal.classfile.attribute.ModuleAttribute;
Expand Down Expand Up @@ -131,6 +132,9 @@ public class Attributes {
/** LocalVariableTypeTable */
public static final String NAME_LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable";

/** Matcher */
public static final String NAME_MATCHER = "Matcher";

/** MethodParameters */
public static final String NAME_METHOD_PARAMETERS = "MethodParameters";

Expand Down Expand Up @@ -423,6 +427,23 @@ protected void writeBody(BufWriter buf, LocalVariableTypeTableAttribute attr) {
}
};

/** Attribute mapper for the {@code Matcher} attribute */
public static final AttributeMapper<MatcherAttribute>
MATCHER = new AbstractAttributeMapper<>(NAME_MATCHER, Classfile.JAVA_22_VERSION) {
@Override
public MatcherAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundMatcherAttribute(cf, this, p);
}

@Override
protected void writeBody(BufWriter buf, MatcherAttribute attr) {
buf.writeIndex(attr.matcherName());
buf.writeU2(attr.matcherFlagsMask());
buf.writeIndex(attr.matcherMethodType());
buf.writeList(attr.attributes());
}
};

/** Attribute mapper for the {@code MethodParameters} attribute */
public static final AttributeMapper<MethodParametersAttribute>
METHOD_PARAMETERS = new AbstractAttributeMapper<>(NAME_METHOD_PARAMETERS, Classfile.JAVA_8_VERSION) {
Expand Down Expand Up @@ -822,6 +843,7 @@ public static AttributeMapper<?> standardAttribute(Utf8Entry name) {
LINE_NUMBER_TABLE,
LOCAL_VARIABLE_TABLE,
LOCAL_VARIABLE_TYPE_TABLE,
MATCHER,
METHOD_PARAMETERS,
MODULE,
MODULE_HASHES,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,9 @@ default byte[] transform(ClassModel model, ClassDesc newClassName, ClassTransfor
/** 0x40 */
int ACC_STATIC_PHASE = 0x40;

int PAT_TOTAL = 0x0001;
int PAT_DECONSTRUCTOR = 0x0002;

/** 0x0001 */
int CRT_STATEMENT = 0x0001;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import jdk.internal.classfile.attribute.AnnotationDefaultAttribute;
import jdk.internal.classfile.attribute.DeprecatedAttribute;
import jdk.internal.classfile.attribute.ExceptionsAttribute;
import jdk.internal.classfile.attribute.MatcherAttribute;
import jdk.internal.classfile.attribute.MethodParametersAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleParameterAnnotationsAttribute;
Expand All @@ -46,7 +47,7 @@ public sealed interface MethodElement
extends ClassfileElement
permits AccessFlags, CodeModel, CustomAttribute,
AnnotationDefaultAttribute, DeprecatedAttribute,
ExceptionsAttribute, MethodParametersAttribute,
ExceptionsAttribute, MatcherAttribute, MethodParametersAttribute,
RuntimeInvisibleAnnotationsAttribute, RuntimeInvisibleParameterAnnotationsAttribute,
RuntimeInvisibleTypeAnnotationsAttribute, RuntimeVisibleAnnotationsAttribute,
RuntimeVisibleParameterAnnotationsAttribute, RuntimeVisibleTypeAnnotationsAttribute,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright (c) 2022, 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
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package jdk.internal.classfile.attribute;

import jdk.internal.classfile.AccessFlags;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.AttributedElement;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.constantpool.IntegerEntry;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;

import java.lang.constant.MethodTypeDesc;
import java.lang.reflect.AccessFlag;
import java.util.List;
import java.util.Set;

/**
* Models the {@code Matcher} attribute {@jvms X.X.XX}, which can
* appear on matchers, and records additional information about the
* nature of this matcher represented as a method.
*
* TODO
* Delivered as a {@link MethodElement} when
* traversing the elements of a {@link jdk.internal.classfile.MethodModel}.
*/
public sealed interface MatcherAttribute
extends Attribute<MatcherAttribute>, MethodElement, AttributedElement
permits BoundAttribute.BoundMatcherAttribute,
UnboundAttribute.UnboundMatcherAttribute {

/**
* {@return the the module flags of the module, as a bit mask}
*/
int matcherFlagsMask();

/**
* {@return the the module flags of the module, as a set of enum constants}
*/
default Set<AccessFlag> matcherFlags() {
return AccessFlag.maskToAccessFlags(matcherFlagsMask(), AccessFlag.Location.MATCHER);
}

/** {@return the name of this method} */
Utf8Entry matcherName();

/** {@return the method descriptor of this method} */
Utf8Entry matcherMethodType();

/** {@return the method descriptor of this method, as a symbolic descriptor} */
default MethodTypeDesc matcherTypeSymbol() {
return MethodTypeDesc.ofDescriptor(matcherMethodType().stringValue());
}

static MatcherAttribute of(String matcherName,
int matcherFlags,
MethodTypeDesc matcherDescriptor,
List<Attribute<?>> matcherAttributes) {
return new UnboundAttribute.UnboundMatcherAttribute(
TemporaryConstantPool.INSTANCE.utf8Entry(matcherName),
matcherFlags,
TemporaryConstantPool.INSTANCE.utf8Entry(matcherDescriptor.descriptorString()),
matcherAttributes);
}

static MatcherAttribute of(Utf8Entry matcherName,
int matcherFlags,
Utf8Entry matcherDescriptor,
List<Attribute<?>> matcherAttributes) {
return new UnboundAttribute.UnboundMatcherAttribute(matcherName, matcherFlags, matcherDescriptor, matcherAttributes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,20 @@

package jdk.internal.classfile.impl;

import java.lang.constant.MethodTypeDesc;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;

import jdk.internal.classfile.*;
import jdk.internal.classfile.attribute.*;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.constantpool.ConstantPool;
import jdk.internal.classfile.constantpool.ConstantValueEntry;
import jdk.internal.classfile.constantpool.LoadableConstantEntry;
import jdk.internal.classfile.constantpool.ModuleEntry;
import jdk.internal.classfile.constantpool.NameAndTypeEntry;
import jdk.internal.classfile.constantpool.PackageEntry;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.constantpool.*;
import jdk.internal.access.SharedSecrets;

import static jdk.internal.classfile.Attributes.CONSTANT_VALUE;

public abstract sealed class BoundAttribute<T extends Attribute<T>>
extends AbstractElement
implements Attribute<T> {
Expand Down Expand Up @@ -348,6 +345,48 @@ public List<LocalVariableTypeInfo> localVariableTypes() {
}
}

public static final class BoundMatcherAttribute extends BoundAttribute<MatcherAttribute>
implements MatcherAttribute {
private MethodTypeDesc mDesc;
private List<Attribute<?>> attributes;

public BoundMatcherAttribute(ClassReader cf, AttributeMapper<MatcherAttribute> mapper, int pos) {
super(cf, mapper, pos);
}

@Override
public Utf8Entry matcherName() {
return classReader.readUtf8Entry(payloadStart);
}

@Override
public int matcherFlagsMask() {
return classReader.readU2(payloadStart + 2);
}

@Override
public Utf8Entry matcherMethodType() {
// cast will be elided after we get the typed variant for entryByIndex
return ((MethodTypeEntry) classReader.entryByIndex(classReader.readU2(payloadStart + 4))).descriptor();
}

@Override
public MethodTypeDesc matcherTypeSymbol() {
if (mDesc == null) {
mDesc = MethodTypeDesc.ofDescriptor(matcherMethodType().stringValue());
}
return mDesc;
}

@Override
public List<Attribute<?>> attributes() {
if (attributes == null) {
attributes = BoundAttribute.readAttributes(null, classReader, payloadStart + 6, classReader.customAttributes());
}
return attributes;
}
}

public static final class BoundMethodParametersAttribute extends BoundAttribute<MethodParametersAttribute>
implements MethodParametersAttribute {
private List<MethodParameterInfo> parameters = null;
Expand Down
Loading

0 comments on commit a91ed49

Please sign in to comment.