Skip to content

Commit 253af92

Browse files
committed
Kores 4.1.0: Consistent InvokeDynamic, following JVM/JDK Specifications. Fixes #79.
1 parent 709d5e0 commit 253af92

14 files changed

+849
-18
lines changed

build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ buildscript {
1919
}
2020

2121
group 'com.github.jonathanxd'
22-
version '4.0.7.base'
22+
version '4.1.0.base'
2323

2424
apply from: 'gradle/common.gradle'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Kores - Java source and Bytecode generation framework <https://github.com/JonathanxD/Kores>
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2021 TheRealBuggy/JonathanxD (https://github.com/JonathanxD/) <jonathan.scripter@programmer.net>
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.base
29+
30+
import com.github.jonathanxd.kores.base.InvokeType.*
31+
import com.github.jonathanxd.kores.type.isInterface
32+
import kotlinx.serialization.Serializable
33+
import java.lang.reflect.Type
34+
35+
/**
36+
* TODO Documentation
37+
*/
38+
@Serializable
39+
enum class DynamicInvokeType {
40+
41+
/**
42+
* Static method invocation.
43+
*/
44+
INVOKE_STATIC,
45+
46+
/**
47+
* Virtual method invocation (instance methods).
48+
*/
49+
INVOKE_VIRTUAL,
50+
51+
/**
52+
* Special invocation.
53+
*
54+
* - Constructor methods.
55+
* - Private methods.
56+
* - Super constructor invocation. (or this constructor invocation).
57+
*/
58+
INVOKE_SPECIAL,
59+
60+
/**
61+
* Special invocation of constructors.
62+
*/
63+
NEW_INVOKE_SPECIAL,
64+
65+
/**
66+
* Interface method invocation.
67+
*/
68+
INVOKE_INTERFACE;
69+
70+
/**
71+
* Returns true if the InvokeType is [INVOKE_STATIC].
72+
*
73+
* @return True if the InvokeType is [INVOKE_STATIC].
74+
*/
75+
fun isStatic() = this == INVOKE_STATIC
76+
77+
/**
78+
* Returns true if the InvokeType is [INVOKE_VIRTUAL].
79+
*
80+
* @return True if the InvokeType is [INVOKE_VIRTUAL].
81+
*/
82+
fun isVirtual() = this == INVOKE_VIRTUAL
83+
84+
/**
85+
* Returns true if the InvokeType is [INVOKE_SPECIAL].
86+
*
87+
* @return True if the InvokeType is [INVOKE_SPECIAL].
88+
*/
89+
fun isSpecial() = this == INVOKE_SPECIAL
90+
91+
/**
92+
* Returns true if the InvokeType is [NEW_INVOKE_SPECIAL].
93+
*
94+
* @return True if the InvokeType is [NEW_INVOKE_SPECIAL].
95+
*/
96+
fun isNewSpecial() = this == NEW_INVOKE_SPECIAL
97+
98+
/**
99+
* Returns true if the InvokeType is [INVOKE_INTERFACE].
100+
*
101+
* @return True if the InvokeType is [INVOKE_INTERFACE].
102+
*/
103+
fun isInterface() = this == INVOKE_INTERFACE
104+
105+
fun toInvokeType(): InvokeType = when(this) {
106+
INVOKE_STATIC -> InvokeType.INVOKE_STATIC
107+
INVOKE_VIRTUAL -> InvokeType.INVOKE_VIRTUAL
108+
INVOKE_SPECIAL, NEW_INVOKE_SPECIAL -> InvokeType.INVOKE_SPECIAL
109+
INVOKE_INTERFACE -> InvokeType.INVOKE_INTERFACE
110+
}
111+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Kores - Java source and Bytecode generation framework <https://github.com/JonathanxD/Kores>
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2021 TheRealBuggy/JonathanxD (https://github.com/JonathanxD/) <jonathan.scripter@programmer.net>
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.base
29+
30+
import com.github.jonathanxd.kores.base.InvokeType.*
31+
import com.github.jonathanxd.kores.type.isInterface
32+
import kotlinx.serialization.Serializable
33+
import java.lang.reflect.Type
34+
35+
/**
36+
* TODO Documentation
37+
*
38+
* A
39+
*/
40+
@Serializable
41+
enum class FieldAccessKind {
42+
43+
/**
44+
* Access instance field of an object.
45+
*/
46+
GET_FIELD,
47+
48+
/**
49+
* Access static field of a type.
50+
*/
51+
GET_STATIC,
52+
53+
/**
54+
* Set the instance field value of an object.
55+
*/
56+
PUT_FIELD,
57+
58+
/**
59+
* Set the static field value of a type.
60+
*/
61+
PUT_STATIC
62+
63+
}

src/main/kotlin/com/github/jonathanxd/kores/base/InvokeDynamic.kt

+60-6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ import com.github.jonathanxd.kores.builder.self
3232
import com.github.jonathanxd.kores.common.DynamicMethodSpec
3333
import com.github.jonathanxd.kores.common.MethodInvokeSpec
3434
import com.github.jonathanxd.kores.common.MethodTypeSpec
35+
import com.github.jonathanxd.kores.common.FieldAccessHandleSpec
36+
import com.github.jonathanxd.kores.common.MethodInvokeHandleSpec
37+
import com.github.jonathanxd.kores.common.DynamicConstantSpec
3538
import com.github.jonathanxd.kores.serialization.BootstrapArgListSerializer
3639
import com.github.jonathanxd.kores.serialization.BootstrapArgSerializer
3740
import com.github.jonathanxd.kores.type.KoresType
@@ -41,10 +44,35 @@ import java.lang.reflect.Type
4144
import java.util.function.Supplier
4245

4346
/**
44-
* A dynamic invocation of a method.
47+
* Represents a dynamic invocation of a method. The mechanism of a dynamic invocation is very simple, when JVM encounters an
48+
* `invokedynamic` instruction, it calls the [bootstrap] method (which is a static method defined in [bootstrapLocalization])
49+
* to resolve the [target method][dynamicMethod]. Once resolved, the [target method][dynamicMethod] keeps linked to the
50+
* call-site and there is no way to revert this. Subsequent calls are routed to the resolved method without invoking the bootstrap.
51+
* This allows optimizations to take in place (like the JIT compiler optimizations).
4552
*
46-
* Note: this class does not extends [MethodInvocation] because it is not
47-
* a normal invocation.
53+
* The [dynamicMethod] corresponds to the dynamic method that need to be resolved, it contains important information about
54+
* the method that need to be resolved. The [DynamicMethodSpec.name] and [DynamicMethodSpec.typeSpec] (which are provided as
55+
* [String] and [MethodType], respectively) are available to the bootstrap method, but [DynamicMethodSpec.arguments] is not,
56+
* as specified in the documentation of the property.
57+
*
58+
* Additional information can be provided through [bootstrapArgs] and are passed as the last argument of the
59+
* [bootstrap method][bootstrap]. The last parameter of [bootstrap method][bootstrap] can be a vararg, an [Array] of [Any],
60+
* or various parameters of the types accepted by bootstrap methods as specified in JVM Specification and in the
61+
* [java.lang.invoke] package documentation. The known allowed parameter types are:
62+
* - Literal Constants
63+
* - [Int], [Float], [Long], [Double], [String] (it includes [dynamic constant][DynamicConstantSpec]).
64+
* - Type Constants
65+
* - [Type]/[Class]
66+
* - Field and Method specification
67+
* - [MethodHandle]
68+
* - Descriptors
69+
* - [MethodType]/[TypeDescriptor] (since Java 12)
70+
*
71+
*
72+
* ### Relevant documents
73+
* - [Java Virtual Machine Support for Non-Java Languages](https://docs.oracle.com/javase/8/docs/technotes/guides/vm/multiple-language-support.html)
74+
* - [Understanding Java method invocation with invokedynamic](https://blogs.oracle.com/javamagazine/understanding-java-method-invocation-with-invokedynamic)
75+
* - [Chapter 6. The Java Virtual Machine Instruction Set#invokedynamic](https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-6.html#jvms-6.5.invokedynamic)
4876
*/
4977
interface InvokeDynamicBase : TypedInstruction {
5078

@@ -60,13 +88,39 @@ interface InvokeDynamicBase : TypedInstruction {
6088
val bootstrap: MethodInvokeSpec
6189

6290
/**
63-
* Specification of dynamic method.
91+
* The [Type] that declares the [bootstrap method][bootstrap].
92+
*
93+
* This is the same value provided via [MethodTypeSpec] to the [bootstrap].[methodTypeSpec][MethodInvokeSpec.methodTypeSpec].
94+
*/
95+
val bootstrapLocalization: Type
96+
get() = this.bootstrap.methodTypeSpec.localization
97+
98+
/**
99+
* Specification of the method to invoke dynamically. This information is used by the [bootstrap method][bootstrap]
100+
* to resolve the target invocation method.
101+
*
102+
* Arguments provided to [DynamicMethodSpec] are passed to the method resolved by the [bootstrap].
64103
*/
65104
val dynamicMethod: DynamicMethodSpec
66105

67106
/**
68-
* Bootstrap method Arguments, must be an [String], [Int],
69-
* [Long], [Float], [Double], [KoresType] or [MethodInvokeSpec].
107+
* Bootstrap method Arguments, must be one of the following types:
108+
* - [String]
109+
* - [Int],
110+
* - [Long]
111+
* - [Float]
112+
* - [Double]
113+
* - [KoresType]/[Type]
114+
* - [MethodInvokeSpec] (normally translated into [MethodHandle] at runtime, by the JVM)
115+
* - [FieldAccessHandleSpec] (normally translated into [MethodHandle] at runtime, by the JVM)
116+
* - [MethodInvokeHandleSpec] (normally translated into [MethodHandle] at runtime, by the JVM)
117+
* - [TypeSpec] (normally translated into [MethodType] at runtime, by the JVM)
118+
* - [DynamicConstantSpec] (as specified in [JEP 309](https://openjdk.java.net/jeps/309), translated into a constant).
119+
*
120+
* This is the value provided to the bootstrap method which resolves the target method to invoke. Those values
121+
* are stored in the **ConstantPool** and are not provided to the target method.
122+
*
123+
* Arguments that must be provided to the target method must be provided in the [dynamicMethod] specification.
70124
*/
71125
@Serializable(with = BootstrapArgListSerializer::class)
72126
val bootstrapArgs: List<Any>

src/main/kotlin/com/github/jonathanxd/kores/base/InvokeType.kt

+7
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ enum class InvokeType {
9999
*/
100100
fun isInterface() = this == INVOKE_INTERFACE
101101

102+
fun toDynamicInvokeType(): DynamicInvokeType = when(this) {
103+
INVOKE_STATIC -> DynamicInvokeType.INVOKE_STATIC
104+
INVOKE_VIRTUAL -> DynamicInvokeType.INVOKE_VIRTUAL
105+
INVOKE_SPECIAL -> DynamicInvokeType.INVOKE_SPECIAL
106+
INVOKE_INTERFACE -> DynamicInvokeType.INVOKE_INTERFACE
107+
}
108+
102109
companion object {
103110

104111
/**

0 commit comments

Comments
 (0)