Skip to content

Commit a25fbe6

Browse files
committed
Add DynamicConstant test and target JDK 16. Kores-BytecodeWriter is still able to produce bytecode from Java 8 up to Java 16.
1 parent 1c469d9 commit a25fbe6

File tree

5 files changed

+390
-4
lines changed

5 files changed

+390
-4
lines changed

Kores

Submodule Kores updated 193 files

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ buildscript {
1818
}
1919

2020
group 'com.github.jonathanxd'
21-
version '4.1.1.bytecode.1'
21+
version '4.1.2.bytecode.1'
2222

2323
apply from: project(":Kores").file("gradle/common.gradle")
2424

@@ -28,7 +28,7 @@ dependencies {
2828
// with runtime dependency pointing to Kores published version
2929
//compile project(":Kores")
3030
compileOnly project(":Kores")
31-
runtimeOnly "com.github.koresframework.Kores:Kores:4.1.1.base"
31+
runtimeOnly "com.github.koresframework.Kores:Kores:4.1.2.base"
3232
implementation 'com.github.JonathanxD:BytecodeDisassembler:2.3.0'
3333
implementation "org.ow2.asm:asm:9.2"
3434
implementation "org.ow2.asm:asm-analysis:9.2"
Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
/*
2+
* Kores-BytecodeWriter - Translates Kores Structure to JVM Bytecode <https://github.com/JonathanxD/CodeAPI-BytecodeWriter>
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2021 TheRealBuggy/JonathanxD (https://github.com/JonathanxD/) <[email protected]>
7+
* Copyright (c) contributors
8+
*
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in
18+
* all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+
* THE SOFTWARE.
27+
*/
28+
package com.github.jonathanxd.kores.test.asm;
29+
30+
import com.github.jonathanxd.iutils.annotation.Named;
31+
import com.github.jonathanxd.kores.*;
32+
import com.github.jonathanxd.kores.base.*;
33+
import com.github.jonathanxd.kores.common.*;
34+
import com.github.jonathanxd.kores.factory.DynamicInvocationFactory;
35+
import com.github.jonathanxd.kores.factory.Factories;
36+
import com.github.jonathanxd.kores.factory.InvocationFactory;
37+
import com.github.jonathanxd.kores.factory.VariableFactory;
38+
import com.github.jonathanxd.kores.helper.Predefined;
39+
import com.github.jonathanxd.kores.literal.Literals;
40+
import com.github.jonathanxd.kores.operator.Operators;
41+
import com.github.jonathanxd.kores.test.*;
42+
import com.github.jonathanxd.kores.type.KoresType;
43+
import com.github.jonathanxd.kores.type.KoresTypes;
44+
import com.github.jonathanxd.kores.type.TypeRef;
45+
import org.junit.Assert;
46+
import org.junit.Test;
47+
48+
import java.io.PrintStream;
49+
import java.lang.invoke.*;
50+
import java.lang.reflect.Field;
51+
import java.lang.reflect.Modifier;
52+
import java.util.Arrays;
53+
import java.util.Collections;
54+
import java.util.concurrent.atomic.AtomicInteger;
55+
import java.util.function.Supplier;
56+
import java.util.function.UnaryOperator;
57+
58+
import static java.util.Collections.emptyList;
59+
import static java.util.Collections.singletonList;
60+
61+
public class IndyTest {
62+
63+
private static final AtomicInteger BOOTSTRAP_CALLS = new AtomicInteger();
64+
private static final AtomicInteger CONST_BOOTSTRAP_CALLS = new AtomicInteger();
65+
66+
@Test
67+
public void indyTest() {
68+
TypeDeclaration $ = IndyTest.$();
69+
70+
@Named("Instance") Class<?> define = CommonBytecodeTest.test(this.getClass(), $, UnaryOperator.identity(), aClass -> aClass);
71+
72+
Object o;
73+
try {
74+
o = define.newInstance();
75+
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
76+
77+
MethodHandle check = lookup.findVirtual(define, "check", MethodType.methodType(String.class, Integer.TYPE)).bindTo(o);
78+
79+
try {
80+
String invoke = (String) check.invoke(9);
81+
String invoke2 = (String) check.invoke(9);
82+
83+
Assert.assertEquals("MAGIC", invoke);
84+
Assert.assertEquals("MAGIC", invoke2);
85+
Assert.assertEquals(2, BOOTSTRAP_CALLS.get());
86+
Assert.assertEquals(1, CONST_BOOTSTRAP_CALLS.get());
87+
} catch (Throwable throwable) {
88+
throwable.printStackTrace();
89+
}
90+
91+
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException e) {
92+
throw new RuntimeException(e);
93+
}
94+
95+
for (Field field : define.getDeclaredFields()) {
96+
try {
97+
System.out.println("Field -> " + field + " = " + field.get(o));
98+
} catch (IllegalAccessException e) {
99+
throw new RuntimeException(e);
100+
}
101+
}
102+
}
103+
104+
public static final IndyTest INSTANCE = new IndyTest();
105+
public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
106+
public static final MethodTypeSpec BOOTSTRAP_SPEC = new MethodTypeSpec(
107+
KoresTypes.getKoresType(IndyTest.class),
108+
"myBootstrap",
109+
Factories.typeSpec(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, Object[].class)
110+
);
111+
public static final MethodTypeSpec CONSTANT_BOOTSTRAP_SPEC = new MethodTypeSpec(
112+
KoresTypes.getKoresType(IndyTest.class),
113+
"constantBootstrap",
114+
Factories.typeSpec(String.class, MethodHandles.Lookup.class, String.class, Class.class, Object[].class)
115+
);
116+
117+
public static final MethodHandle FALLBACK;
118+
public static final MethodHandle CONST_FALLBACK;
119+
120+
static {
121+
try {
122+
FALLBACK = LOOKUP.findStatic(
123+
IndyTest.class,
124+
"fallback",
125+
MethodType.methodType(Object.class, IndyTest.MyCallSite.class, Object[].class));
126+
} catch (NoSuchMethodException | IllegalAccessException e) {
127+
throw new RuntimeException(e);
128+
}
129+
try {
130+
CONST_FALLBACK = LOOKUP.findStatic(
131+
IndyTest.class,
132+
"constFallback", MethodType.methodType(String.class, String.class, Object[].class));
133+
} catch (NoSuchMethodException | IllegalAccessException e) {
134+
throw new RuntimeException(e);
135+
}
136+
}
137+
138+
public static KoresPart invokePrintln(Instruction toPrint) {
139+
return InvocationFactory.invoke(InvokeType.INVOKE_VIRTUAL, KoresTypes.getKoresType(PrintStream.class),
140+
Factories.accessStaticField(KoresTypes.getKoresType(System.class), KoresTypes.getKoresType(PrintStream.class), "out"),
141+
"println",
142+
Factories.voidTypeSpec(Types.OBJECT),
143+
Collections.singletonList(toPrint));
144+
}
145+
146+
public static void bmp(String a, String b) {
147+
System.out.println("A = " + a + ", B = " + b);
148+
}
149+
150+
public static CallSite myBootstrap(MethodHandles.Lookup caller, String name,
151+
MethodType type, Object... parameters) throws Throwable {
152+
BOOTSTRAP_CALLS.incrementAndGet();
153+
IndyTest.MyCallSite myCallSite = new IndyTest.MyCallSite(caller, name, parameters);
154+
155+
MethodHandle methodHandle = FALLBACK.bindTo(myCallSite)
156+
.asCollector(Object[].class, type.parameterCount())
157+
.asType(type);
158+
159+
return new ConstantCallSite(methodHandle);
160+
}
161+
162+
public static String constantBootstrap(MethodHandles.Lookup caller, String name,
163+
Class<?> type, Object... parameters) throws Throwable {
164+
CONST_BOOTSTRAP_CALLS.incrementAndGet();
165+
if ("some".equals(name)) {
166+
return "MAGIC";
167+
}
168+
return "NO_MAGIC";
169+
}
170+
171+
public static Object fallback(IndyTest.MyCallSite callSite, Object[] args) throws Throwable {
172+
return callSite.parameters[0];
173+
}
174+
175+
public static String constFallback(String constantName, Object[] args) throws Throwable {
176+
if ("some".equals(constantName)) {
177+
return "MAGIC";
178+
}
179+
return "NO_MAGIC";
180+
}
181+
182+
public static TypeDeclaration $() {
183+
MutableInstructions codeSource = MutableInstructions.create();
184+
185+
TypeRef typeRef = new TypeRef("fullName." + IndyTest.class.getSimpleName() + "_Generated");
186+
187+
188+
ClassDeclaration codeClass = ClassDeclaration.Builder.Companion.builder()
189+
.modifiers(KoresModifier.PUBLIC)
190+
.base(typeRef)
191+
.superClass(Types.OBJECT)
192+
.fields(FieldDeclaration.Builder.builder()
193+
.modifiers(KoresModifier.PUBLIC, KoresModifier.FINAL)
194+
.type(Types.STRING)
195+
.name("FIELD")
196+
.value(Literals.STRING("AVD"))
197+
.build(),
198+
FieldDeclaration.Builder.builder()
199+
.modifiers(KoresModifier.PUBLIC, KoresModifier.FINAL)
200+
.type(Types.INT)
201+
.name("n")
202+
.value(Literals.INT(15))
203+
.build()
204+
)
205+
.constructors(ConstructorDeclaration.Builder.Companion.builder()
206+
.modifiers(KoresModifier.PUBLIC)
207+
.body(Instructions.empty())
208+
.build())
209+
.methods(makeCM2(typeRef))
210+
.build();
211+
212+
return codeClass;
213+
}
214+
215+
public static MethodDeclaration makeCM2(TypeRef typeDeclaration) {
216+
MutableInstructions methodSource = MutableInstructions.create();
217+
218+
MethodDeclaration codeMethod = MethodDeclaration.Builder.builder()
219+
.modifiers(KoresModifier.PUBLIC)
220+
.name("check")
221+
.returnType(Types.STRING)
222+
.parameters(Factories.parameter(Types.INT, "x"))
223+
.body(methodSource)
224+
.build();
225+
226+
methodSource.add(Predefined.invokePrintln(Literals.STRING("Invoke Dynamic Bootstrap ->")));
227+
DynamicConstantSpec someConst = new DynamicConstantSpec(
228+
"some",
229+
Types.STRING,
230+
new MethodInvokeHandleSpec(DynamicInvokeType.INVOKE_STATIC, CONSTANT_BOOTSTRAP_SPEC),
231+
Collections.singletonList("value")
232+
);
233+
234+
InvokeDynamic bootstrapInvocation = DynamicInvocationFactory.invokeDynamic(
235+
new MethodInvokeSpec(InvokeType.INVOKE_STATIC, BOOTSTRAP_SPEC),
236+
new DynamicMethodSpec("helloWorld", Factories.typeSpec(Types.STRING, Types.STRING),
237+
singletonList(Literals.STRING("World"))),
238+
Collections.singletonList(
239+
someConst
240+
)
241+
);
242+
243+
244+
methodSource.add(bootstrapInvocation);
245+
methodSource.add(Factories.returnValue(Types.STRING, bootstrapInvocation));
246+
247+
return codeMethod;
248+
}
249+
250+
public void helloWorld(String name) {
251+
System.out.println("Hello, " + name);
252+
}
253+
254+
@Test
255+
public void test() {
256+
$();
257+
}
258+
259+
/*public static class MyCallSite extends ConstantCallSite {
260+
261+
final MethodHandles.Lookup callerLookup;
262+
final String name;
263+
final Object[] parameters;
264+
265+
MyCallSite(MethodHandles.Lookup callerLookup, MethodHandle target, String name, Object[] parameters) {
266+
super(target);
267+
this.callerLookup = callerLookup;
268+
this.name = name;
269+
this.parameters = parameters;
270+
}
271+
272+
273+
}
274+
*/
275+
public static class MyCallSite {
276+
277+
final MethodHandles.Lookup callerLookup;
278+
final String name;
279+
final Object[] parameters;
280+
281+
MyCallSite(MethodHandles.Lookup callerLookup, String name, Object[] parameters) {
282+
this.callerLookup = callerLookup;
283+
this.name = name;
284+
this.parameters = parameters;
285+
}
286+
287+
288+
}
289+
290+
291+
292+
private static final class BCLoader extends ClassLoader {
293+
294+
protected BCLoader(ClassLoader parent) {
295+
super(parent);
296+
}
297+
298+
public Class<?> define(String name, byte[] bytes) {
299+
return super.defineClass(name, bytes, 0, bytes.length);
300+
}
301+
}
302+
}

src/test/java/com/github/jonathanxd/kores/test/asm/ResultSaver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public final class ResultSaver {
4848
static {
4949
String prop = System.getProperty("env");
5050

51-
IS_GRADLE_ENVIRONMENT = prop != null && prop.equals("gradle");
51+
IS_GRADLE_ENVIRONMENT = false;//prop != null && prop.equals("gradle");
5252

5353
if (IS_GRADLE_ENVIRONMENT) {
5454
System.out.println("Gradle environment property defined!");

0 commit comments

Comments
 (0)