Skip to content

Commit

Permalink
Fix superinterface invoke bug
Browse files Browse the repository at this point in the history
  • Loading branch information
squid233 committed Jan 31, 2024
1 parent 1629a40 commit 755edc3
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 13 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,6 @@ Import as a Gradle dependency:

```groovy
dependencies {
implementation("io.github.over-run:marshal:0.1.0-alpha.11-jdk22")
implementation("io.github.over-run:marshal:0.1.0-alpha.12-jdk22")
}
```
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ projGroupId=io.github.over-run
projArtifactId=marshal
# The project name should only contain lowercase letters, numbers and hyphen.
projName=marshal
projVersion=0.1.0-alpha.11-jdk22
projVersion=0.1.0-alpha.12-jdk22
projDesc=Marshaler of native libraries
# Uncomment them if you want to publish to maven repository.
projUrl=https://github.com/Over-Run/marshal
Expand Down
21 changes: 10 additions & 11 deletions src/main/java/overrun/marshal/Downcall.java
Original file line number Diff line number Diff line change
Expand Up @@ -394,11 +394,11 @@ private static Method findUpcallWrapper(Class<?> aClass) {
}

@SuppressWarnings("unchecked")
private static <T> T loadBytecode(Class<?> callerClass, SymbolLookup lookup, Map<String, FunctionDescriptor> descriptorMap) {
private static <T> T loadBytecode(Class<?> targetClass, SymbolLookup lookup, Map<String, FunctionDescriptor> descriptorMap) {
final ClassFile cf = of();
final ClassDesc cd_thisClass = ClassDesc.of(callerClass.getPackageName(), DEFAULT_NAME);
final ClassDesc cd_thisClass = ClassDesc.of(targetClass.getPackageName(), DEFAULT_NAME);
final byte[] bytes = cf.build(cd_thisClass, classBuilder -> {
final List<Method> methodList = Arrays.stream(callerClass.getMethods())
final List<Method> methodList = Arrays.stream(targetClass.getMethods())
.filter(method ->
method.getDeclaredAnnotation(Skip.class) == null &&
!Modifier.isStatic(method.getModifiers()))
Expand All @@ -425,7 +425,8 @@ private static <T> T loadBytecode(Class<?> callerClass, SymbolLookup lookup, Map
classBuilder.withFlags(ACC_FINAL | ACC_SUPER);

// interface
classBuilder.withInterfaceSymbols(callerClass.describeConstable().orElseThrow());
final ClassDesc cd_targetClass = targetClass.describeConstable().orElseThrow();
classBuilder.withInterfaceSymbols(cd_targetClass);

// linker
classBuilder.withField("$LINKER", CD_Linker, ACC_PRIVATE | ACC_FINAL | ACC_STATIC);
Expand Down Expand Up @@ -833,11 +834,10 @@ private static <T> T loadBytecode(Class<?> callerClass, SymbolLookup lookup, Map
blockCodeBuilder -> {
// invoke super interface
invokeSuperMethod(blockCodeBuilder, parameters);
final Class<?> declaringClass = method.getDeclaringClass();
blockCodeBuilder.invokespecial(ClassDesc.ofDescriptor(declaringClass.descriptorString()),
blockCodeBuilder.invokespecial(cd_targetClass,
methodName,
mtd_method,
declaringClass.isInterface())
targetClass.isInterface())
.areturn();
});
} else {
Expand All @@ -854,11 +854,10 @@ private static <T> T loadBytecode(Class<?> callerClass, SymbolLookup lookup, Map
blockCodeBuilder -> {
// invoke super interface
invokeSuperMethod(blockCodeBuilder, parameters);
final Class<?> declaringClass = method.getDeclaringClass();
blockCodeBuilder.invokespecial(declaringClass.describeConstable().orElseThrow(),
blockCodeBuilder.invokespecial(cd_targetClass,
methodName,
mtd_method,
declaringClass.isInterface()
targetClass.isInterface()
).returnInstruction(returnTypeKind);
}
).nop();
Expand Down Expand Up @@ -1049,7 +1048,7 @@ private static <T> T loadBytecode(Class<?> callerClass, SymbolLookup lookup, Map
});

try {
final MethodHandles.Lookup hiddenClass = MethodHandles.privateLookupIn(callerClass, MethodHandles.lookup())
final MethodHandles.Lookup hiddenClass = MethodHandles.privateLookupIn(targetClass, MethodHandles.lookup())
.defineHiddenClassWithClassData(bytes, Map.copyOf(descriptorMap), true, MethodHandles.Lookup.ClassOption.STRONG);
return (T) hiddenClass.findConstructor(hiddenClass.lookupClass(), MethodType.methodType(void.class, SymbolLookup.class))
.invoke(lookup);
Expand Down
47 changes: 47 additions & 0 deletions src/test/java/overrun/marshal/test/IndirectInterfaceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* MIT License
*
* Copyright (c) 2024 Overrun Organization
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*/

package overrun.marshal.test;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import overrun.marshal.Downcall;

import java.lang.foreign.SymbolLookup;

/**
* Test indirect interface
*
* @author squid233
* @since 0.1.0
*/
public final class IndirectInterfaceTest {
interface I1 {
default int fun1() {
return 1;
}
}

interface I2 extends I1 {
}

I2 INSTANCE = Downcall.load(I2.class, SymbolLookup.loaderLookup());

@Test
void testIndirectInterface() {
Assertions.assertEquals(1, INSTANCE.fun1());
}
}

0 comments on commit 755edc3

Please sign in to comment.