Skip to content

Commit

Permalink
Update DowncallMethodType
Browse files Browse the repository at this point in the history
  • Loading branch information
squid233 committed Nov 9, 2024
1 parent 8fb735c commit f70e8eb
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 98 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.run/
run/
*.class

.gradle
build/
Expand Down
16 changes: 9 additions & 7 deletions src/main/java/overrun/marshal/Downcall.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
import java.lang.classfile.ClassFile;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.TypeKind;
import java.lang.constant.*;
import java.lang.constant.ClassDesc;
import java.lang.constant.DynamicCallSiteDesc;
import java.lang.constant.DynamicConstantDesc;
import java.lang.constant.MethodTypeDesc;
import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
Expand Down Expand Up @@ -384,7 +387,7 @@ private static Map.Entry<byte[], DirectAccessData> buildBytecode(MethodHandles.L
entrypoint,
MethodTypeDesc.of(cd_returnType, downcallClassDescList),
DCD_classData_DirectAccessData,
Objects.requireNonNullElse(StringCharset.getCharset(method), NULL),
downcallMethodType.describeConstable().orElseThrow(),
hasMemoryStack ? TRUE : FALSE
));
boolean returnVoid = returnType == void.class;
Expand Down Expand Up @@ -549,7 +552,7 @@ private static DirectAccessData generateData(
DescriptorTransformer.getInstance().process(new DescriptorTransformer.Context(method,
methodData.descriptorSkipFirstParameter(),
methodData.parameters(),
methodData.methodType()));
downcallMethodType));
}
descriptorMap1.put(entrypoint, descriptor);

Expand All @@ -558,10 +561,9 @@ private static DirectAccessData generateData(
final Optional<MemorySegment> optional = lookup.find(entrypoint);
if (optional.isPresent()) {
// linker options
final Linker.Option[] options;
final Critical critical = method.getDeclaredAnnotation(Critical.class);
if (critical != null) {
options = critical.allowHeapAccess() ? OPTION_CRITICAL_TRUE : OPTION_CRITICAL_FALSE;
Linker.Option[] options;
if (downcallMethodType.critical()) {
options = downcallMethodType.criticalAllowHeapAccess() ? OPTION_CRITICAL_TRUE : OPTION_CRITICAL_FALSE;
} else {
options = NO_OPTION;
}
Expand Down
16 changes: 11 additions & 5 deletions src/main/java/overrun/marshal/DowncallFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ public static CallSite downcallCallSite(
String entrypoint,
MethodType type,
DirectAccessData data,
String methodCharset,
DowncallMethodType downcallMethodType,
boolean popStack
) {
MethodHandle methodHandle = data.methodHandle(entrypoint);
Class<?> returnType = type.returnType();
methodHandle = ReturnValueTransformer.getInstance().process(methodHandle, new ReturnValueTransformer.Context(returnType, methodCharset));
methodHandle = ReturnValueTransformer.getInstance().process(methodHandle, new ReturnValueTransformer.Context(returnType, downcallMethodType));
methodHandle = MethodHandles.catchException(methodHandle, Throwable.class, MethodHandles.insertArguments(MH_throwISE.asType(MH_throwISE.type().changeReturnType(returnType)), 1, caller.lookupClass(), entrypoint, type));
if (popStack) {
if (returnType == void.class) {
Expand Down Expand Up @@ -96,22 +96,27 @@ public static DowncallMethodParameter createDowncallMethodParameter(
MethodHandles.Lookup lookup,
String name,
Class<?> type,
Class<?> parameterType,
boolean byValue,
boolean ref,
long sized,
String charset
String charset,
String canonicalType
) {
return new DowncallMethodParameter(type, ref, sized, charset);
return new DowncallMethodParameter(parameterType, byValue, ref, sized, charset, canonicalType);
}

public static DowncallMethodType createDowncallMethodType(
MethodHandles.Lookup lookup,
String entrypoint,
Class<?> type,
Class<?> returnType,
boolean byValue,
boolean critical,
boolean criticalAllowHeapAccess,
long sized,
String charset,
String canonicalType,
Object... args
) {
return new DowncallMethodType(entrypoint,
Expand All @@ -121,6 +126,7 @@ public static DowncallMethodType createDowncallMethodType(
critical,
criticalAllowHeapAccess,
sized,
charset);
charset,
canonicalType);
}
}
44 changes: 38 additions & 6 deletions src/main/java/overrun/marshal/gen/DowncallMethodParameter.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
package overrun.marshal.gen;

import overrun.marshal.internal.Constants;
import overrun.marshal.struct.ByValue;

import java.lang.constant.*;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Parameter;
import java.util.Optional;

/**
Expand All @@ -28,18 +30,39 @@
*/
public record DowncallMethodParameter(
Class<?> type,
boolean byValue,
boolean ref,
long sized,
String charset
String charset,
String canonicalType
) implements Constable {
public static DowncallMethodParameter of(Parameter parameter) {
CanonicalType anCanonicalType = parameter.getDeclaredAnnotation(CanonicalType.class);
Sized anSized = parameter.getDeclaredAnnotation(Sized.class);
StrCharset anStrCharset = parameter.getDeclaredAnnotation(StrCharset.class);

return new DowncallMethodParameter(parameter.getType(),
parameter.getDeclaredAnnotation(ByValue.class) != null,
parameter.getDeclaredAnnotation(Ref.class) != null,
anSized != null ? anSized.value() : -1,
anStrCharset != null ? anStrCharset.value() : null,
anCanonicalType != null ? anCanonicalType.value() : null);
}

@Override
public Optional<? extends ConstantDesc> describeConstable() {
return Optional.of(new Desc(ClassDesc.ofDescriptor(type.descriptorString()), ref, sized, charset));
public Optional<Desc> describeConstable() {
return Optional.of(new Desc(ClassDesc.ofDescriptor(type.descriptorString()), byValue, ref, sized, charset, canonicalType));
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (byValue) {
sb.append("[ByValue]");
}
if (canonicalType != null) {
sb.append("[CanonicalType=").append(canonicalType).append(']');
}
if (ref) {
sb.append("[Ref]");
}
Expand All @@ -54,25 +77,34 @@ public String toString() {
}

public static final class Desc extends DynamicConstantDesc<DowncallMethodParameter> {
private final ClassDesc type;
private final boolean byValue;
private final boolean ref;
private final long sized;
private final String charset;
private final String canonicalType;

public Desc(ClassDesc type, boolean ref, long sized, String charset) {
public Desc(ClassDesc type, boolean byValue, boolean ref, long sized, String charset, String canonicalType) {
super(Constants.BSM_DowncallFactory_createDowncallMethodParameter,
ConstantDescs.DEFAULT_NAME,
Constants.CD_DowncallMethodParameter,
type,
byValue ? ConstantDescs.TRUE : ConstantDescs.FALSE,
ref ? ConstantDescs.TRUE : ConstantDescs.FALSE,
sized,
charset);
charset != null ? charset : ConstantDescs.NULL,
canonicalType != null ? canonicalType : ConstantDescs.NULL);
this.type = type;
this.byValue = byValue;
this.ref = ref;
this.sized = sized;
this.charset = charset;
this.canonicalType = canonicalType;
}

@Override
public DowncallMethodParameter resolveConstantDesc(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
return new DowncallMethodParameter(constantType().resolveConstantDesc(lookup), ref, sized, charset);
return new DowncallMethodParameter(type.resolveConstantDesc(lookup), byValue, ref, sized, charset, canonicalType);
}
}
}
99 changes: 66 additions & 33 deletions src/main/java/overrun/marshal/gen/DowncallMethodType.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.lang.constant.*;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
Expand All @@ -40,8 +39,19 @@ public final class DowncallMethodType implements Constable {
private final boolean criticalAllowHeapAccess;
private final long sized;
private final String charset;

public DowncallMethodType(String entrypoint, Class<?> returnType, DowncallMethodParameter[] parameters, boolean byValue, boolean critical, boolean criticalAllowHeapAccess, long sized, String charset) {
private final String canonicalType;

public DowncallMethodType(
String entrypoint,
Class<?> returnType,
DowncallMethodParameter[] parameters,
boolean byValue,
boolean critical,
boolean criticalAllowHeapAccess,
long sized,
String charset,
String canonicalType
) {
this.entrypoint = entrypoint;
this.returnType = returnType;
this.parameters = parameters;
Expand All @@ -50,37 +60,36 @@ public DowncallMethodType(String entrypoint, Class<?> returnType, DowncallMethod
this.criticalAllowHeapAccess = criticalAllowHeapAccess;
this.sized = sized;
this.charset = charset;
this.canonicalType = canonicalType;
}

public static DowncallMethodType of(Method method) {
CanonicalType anCanonicalType = method.getDeclaredAnnotation(CanonicalType.class);
Convert anConvert = method.getDeclaredAnnotation(Convert.class);
Critical anCritical = method.getDeclaredAnnotation(Critical.class);
Sized anSized = method.getDeclaredAnnotation(Sized.class);
StrCharset anStrCharset = method.getDeclaredAnnotation(StrCharset.class);

Class<?> returnType = method.getReturnType();
if (returnType == boolean.class && anConvert != null) {
returnType = anConvert.value().javaClass();
}

return new DowncallMethodType(getMethodEntrypoint(method),
method.getReturnType(),
returnType,
getMethodParameters(method),
method.getDeclaredAnnotation(ByValue.class) != null,
anCritical != null,
anCritical != null && anCritical.allowHeapAccess(),
anSized != null ? anSized.value() : -1,
anStrCharset != null && !anStrCharset.value().isBlank() ? anStrCharset.value() : null);
anStrCharset != null ? anStrCharset.value() : null,
anCanonicalType != null ? anCanonicalType.value() : null);
}

private static DowncallMethodParameter[] getMethodParameters(Method method) {
Parameter[] p = method.getParameters();
DowncallMethodParameter[] parameters = new DowncallMethodParameter[p.length];
for (int i = 0; i < p.length; i++) {
Parameter parameter = p[i];
Sized anSized = parameter.getDeclaredAnnotation(Sized.class);
StrCharset anStrCharset = parameter.getDeclaredAnnotation(StrCharset.class);

parameters[i] = new DowncallMethodParameter(parameter.getType(),
parameter.getDeclaredAnnotation(Ref.class) != null,
anSized != null ? anSized.value() : -1,
anStrCharset != null && !anStrCharset.value().isBlank() ? anStrCharset.value() : null);
}
return parameters;
return Arrays.stream(method.getParameters())
.map(DowncallMethodParameter::of)
.toArray(DowncallMethodParameter[]::new);
}

private static String getMethodEntrypoint(Method method) {
Expand All @@ -91,8 +100,8 @@ private static String getMethodEntrypoint(Method method) {
}

@Override
public Optional<? extends ConstantDesc> describeConstable() {
return Optional.of(new Desc(entrypoint, ClassDesc.ofDescriptor(returnType.descriptorString()), parameters, byValue, critical, criticalAllowHeapAccess, sized, charset));
public Optional<Desc> describeConstable() {
return Optional.of(new Desc(entrypoint, ClassDesc.ofDescriptor(returnType.descriptorString()), parameters, byValue, critical, criticalAllowHeapAccess, sized, charset, canonicalType));
}

public String entrypoint() {
Expand Down Expand Up @@ -127,22 +136,29 @@ public String charset() {
return charset;
}

public String canonicalType() {
return canonicalType;
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (byValue) {
sb.append("[ByValue]");
}
if (canonicalType != null) {
sb.append("[CanonicalType=").append(canonicalType).append(']');
}
if (critical) {
sb.append("[Critical allowHeapAccess=").append(criticalAllowHeapAccess).append(']');
}
if (sized >= 0) {
sb.append("[Sized=").append(sized).append(']');
}
if (charset != null) {
sb.append("[StrCharset=").append(charset).append(']');
}
sb.append(returnType.getSimpleName()).append(' ');
if (critical) {
sb.append("[Critical allowHeapAccess=").append(criticalAllowHeapAccess).append(']');
}
sb.append(entrypoint).append('(');
for (int i = 0; i < parameters.length; i++) {
if (i > 0) {
Expand All @@ -155,34 +171,51 @@ public String toString() {
}

public static final class Desc extends DynamicConstantDesc<DowncallMethodType> {
private final ClassDesc returnType;
private final DowncallMethodParameter[] parameters;
private final boolean byValue;
private final boolean critical;
private final boolean criticalAllowHeapAccess;
private final long sized;
private final String charset;

public Desc(String entrypoint, ClassDesc returnType, DowncallMethodParameter[] parameters, boolean byValue, boolean critical, boolean criticalAllowHeapAccess, long sized, String charset) {
ConstantDesc[] args = new ConstantDesc[parameters.length + 1 + 1 + 1 + 1];
args[0] = byValue ? ConstantDescs.TRUE : ConstantDescs.FALSE;
args[1] = critical ? ConstantDescs.TRUE : ConstantDescs.FALSE;
args[2] = sized;
args[3] = entrypoint;
private final String canonicalType;

public Desc(
String entrypoint,
ClassDesc returnType,
DowncallMethodParameter[] parameters,
boolean byValue,
boolean critical,
boolean criticalAllowHeapAccess,
long sized,
String charset,
String canonicalType
) {
ConstantDesc[] args = new ConstantDesc[1 + 1 + 1 + 1 + 1 + 1 + 1 + parameters.length];
args[0] = returnType;
args[1] = byValue ? ConstantDescs.TRUE : ConstantDescs.FALSE;
args[2] = critical ? ConstantDescs.TRUE : ConstantDescs.FALSE;
args[3] = criticalAllowHeapAccess ? ConstantDescs.TRUE : ConstantDescs.FALSE;
args[4] = sized;
args[5] = charset != null ? charset : ConstantDescs.NULL;
args[6] = canonicalType != null ? canonicalType : ConstantDescs.NULL;
for (int i = 0; i < parameters.length; i++) {
args[i + 4] = parameters[i].describeConstable().orElseThrow();
args[i + 7] = parameters[i].describeConstable().orElseThrow();
}
super(Constants.BSM_DowncallFactory_createDowncallMethodType, entrypoint, returnType, args);
super(Constants.BSM_DowncallFactory_createDowncallMethodType, entrypoint, Constants.CD_DowncallMethodType, args);
this.returnType = returnType;
this.parameters = parameters;
this.byValue = byValue;
this.critical = critical;
this.criticalAllowHeapAccess = criticalAllowHeapAccess;
this.sized = sized;
this.charset = charset;
this.canonicalType = canonicalType;
}

@Override
public DowncallMethodType resolveConstantDesc(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
return new DowncallMethodType(constantName(), constantType().resolveConstantDesc(lookup), parameters, byValue, critical, criticalAllowHeapAccess, sized, charset);
return new DowncallMethodType(constantName(), returnType.resolveConstantDesc(lookup), parameters, byValue, critical, criticalAllowHeapAccess, sized, charset, canonicalType);
}
}
}
Loading

0 comments on commit f70e8eb

Please sign in to comment.