Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/jcl/src/java.base/share/classes/java/lang/invoke/HandleCache.java
12521 views
1
/*[INCLUDE-IF Sidecar17 & !OPENJDK_METHODHANDLES]*/
2
/*******************************************************************************
3
* Copyright (c) 2010, 2020 IBM Corp. and others
4
*
5
* This program and the accompanying materials are made available under
6
* the terms of the Eclipse Public License 2.0 which accompanies this
7
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
* or the Apache License, Version 2.0 which accompanies this distribution and
9
* is available at https://www.apache.org/licenses/LICENSE-2.0.
10
*
11
* This Source Code may also be made available under the following
12
* Secondary Licenses when the conditions for such availability set
13
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
* General Public License, version 2 with the GNU Classpath
15
* Exception [1] and GNU General Public License, version 2 with the
16
* OpenJDK Assembly Exception [2].
17
*
18
* [1] https://www.gnu.org/software/classpath/license.html
19
* [2] http://openjdk.java.net/legal/assembly-exception.html
20
*
21
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
22
*******************************************************************************/
23
package java.lang.invoke;
24
25
import java.lang.ref.WeakReference;
26
import java.util.Collections;
27
import java.util.Map;
28
import java.util.WeakHashMap;
29
30
/*
31
* ClassValue based Cache for mapping from a Class to its perClassCache.
32
*/
33
final class Cache extends ClassValue<Map<CacheKey, WeakReference<MethodHandle>>> {
34
@Override
35
protected Map<CacheKey, WeakReference<MethodHandle>> computeValue(Class<?> arg0) {
36
return Collections.synchronizedMap(new WeakHashMap<CacheKey, WeakReference<MethodHandle>>());
37
}
38
}
39
40
/* Cache key for mapping the methodName and MethodType to the actual MethodHandle */
41
final class MethodCacheKey extends CacheKey {
42
private final MethodType type;
43
private final Class<?> specialCaller;
44
45
public MethodCacheKey(String name, MethodType mt, Class<?> specialCaller) {
46
super(name, calculateHashcode(name, mt, specialCaller));
47
48
this.type = mt;
49
this.specialCaller = specialCaller;
50
}
51
52
private static int calculateHashcode(String name, MethodType mt, Class<?> specialCaller) {
53
/* Hash code based off MethodType.hashCode() */
54
int hash = 31 + mt.hashCode();
55
hash = 31 * hash + name.hashCode();
56
57
if (specialCaller != null) {
58
hash = 31 * hash + specialCaller.hashCode();
59
}
60
return hash;
61
}
62
63
@Override
64
public boolean equals(Object o) {
65
if ((o == null) || !(o instanceof MethodCacheKey)) {
66
return false;
67
}
68
MethodCacheKey other = (MethodCacheKey) o;
69
if ((other.type == type) && other.name.equals(name) && (other.specialCaller == this.specialCaller)) {
70
return true;
71
}
72
return false;
73
}
74
}
75
76
final class FieldCacheKey extends CacheKey {
77
private final Class<?> fieldType;
78
79
public FieldCacheKey(String fieldName, Class<?> fieldType) {
80
super(fieldName, calculateHashcode(fieldName, fieldType));
81
this.fieldType = fieldType;
82
}
83
84
private static int calculateHashcode(String fieldName, Class<?> fieldType) {
85
/* Hash code based off MethodType.hashCode() */
86
int hash = 31 + fieldType.hashCode();
87
hash = 31 * hash + fieldName.hashCode();
88
return hash;
89
}
90
91
92
@Override
93
public boolean equals(Object o){
94
if ((o == null) || !(o instanceof FieldCacheKey)) {
95
return false;
96
}
97
FieldCacheKey other = (FieldCacheKey) o;
98
if (other.fieldType == fieldType && other.name.equals(name)) {
99
return true;
100
}
101
return false;
102
}
103
}
104
105
/* The handle cache itself - it holds onto the individual caches for:
106
* findVirtual
107
* findStatic
108
* findSpecial
109
* findConstructor
110
*/
111
final class HandleCache {
112
private static final Cache findVirtualCache = new Cache();
113
private static final Cache findStaticCache = new Cache();
114
private static final Cache findSpecialCache = new Cache();
115
private static final Cache findConstructorCache = new Cache();
116
private static final Cache staticFieldSetterCache = new Cache();
117
private static final Cache staticFieldGetterCache = new Cache();
118
private static final Cache fieldSetterCache = new Cache();
119
private static final Cache fieldGetterCache = new Cache();
120
121
static Map<CacheKey, WeakReference<MethodHandle>> getVirtualCache(Class<?> c) {
122
return findVirtualCache.get(c);
123
}
124
static Map<CacheKey, WeakReference<MethodHandle>> getStaticCache(Class<?> c) {
125
return findStaticCache.get(c);
126
}
127
static Map<CacheKey, WeakReference<MethodHandle>> getSpecialCache(Class<?> c) {
128
return findSpecialCache.get(c);
129
}
130
static Map<CacheKey, WeakReference<MethodHandle>> getConstructorCache(Class<?> c) {
131
return findConstructorCache.get(c);
132
}
133
static Map<CacheKey, WeakReference<MethodHandle>> getFieldSetterCache(Class<?> c) {
134
return fieldSetterCache.get(c);
135
}
136
static Map<CacheKey, WeakReference<MethodHandle>> getFieldGetterCache(Class<?> c) {
137
return fieldGetterCache.get(c);
138
}
139
static Map<CacheKey, WeakReference<MethodHandle>> getStaticFieldSetterCache(Class<?> c) {
140
return staticFieldSetterCache.get(c);
141
}
142
static Map<CacheKey, WeakReference<MethodHandle>> getStaticFieldGetterCache(Class<?> c) {
143
return staticFieldGetterCache.get(c);
144
}
145
146
/* Search the 'perClassCache' returned by one of the 'get{Virtual|Static|Special|Constructor}Cache(Class)' methods
147
* for the MethodHandle with matching name and type.
148
*/
149
public static MethodHandle getMethodFromPerClassCache(Map<CacheKey, WeakReference<MethodHandle>> perClassCache, String name, MethodType type) {
150
return getMethodWithSpecialCallerFromPerClassCache(perClassCache, name, type, null);
151
}
152
153
public static MethodHandle getMethodWithSpecialCallerFromPerClassCache(Map<CacheKey, WeakReference<MethodHandle>> perClassCache, String name, MethodType type, Class<?> specialCaller) {
154
WeakReference<MethodHandle> handleRef = perClassCache.get(new MethodCacheKey(name, type, specialCaller));
155
if (handleRef != null) {
156
return handleRef.get();
157
}
158
return null;
159
}
160
161
public static MethodHandle getFieldFromPerClassCache(Map<CacheKey, WeakReference<MethodHandle>> perClassCache, String name, Class<?> fieldType) {
162
WeakReference<MethodHandle> handleRef = perClassCache.get(new FieldCacheKey(name, fieldType));
163
if (handleRef != null) {
164
return handleRef.get();
165
}
166
return null;
167
}
168
169
/* Update the cache to hold the <Name, Type> -> MethodHandle mapping */
170
public static MethodHandle putMethodInPerClassCache(Map<CacheKey, WeakReference<MethodHandle>> perClassCache, String name, MethodType type, MethodHandle handle) {
171
return putMethodWithSpecialCallerInPerClassCache(perClassCache, name, type, handle, null);
172
}
173
174
/* Update the cache to hold the <Name, Type, SpecialCaller> -> MethodHandle mapping */
175
public static MethodHandle putMethodWithSpecialCallerInPerClassCache(Map<CacheKey, WeakReference<MethodHandle>> perClassCache, String name, MethodType type, MethodHandle handle, Class<?> specialCaller) {
176
return cacheHandle(perClassCache, new MethodCacheKey(name, type, specialCaller), handle);
177
}
178
179
/* Update the cache to hold the <Name, FieldType> -> MethodHandle mapping */
180
public static MethodHandle putFieldInPerClassCache(Map<CacheKey, WeakReference<MethodHandle>> perClassCache, String fieldName, Class<?> fieldType, MethodHandle handle) {
181
return cacheHandle(perClassCache, new FieldCacheKey(fieldName, fieldType), handle);
182
}
183
184
private static MethodHandle cacheHandle(Map<CacheKey, WeakReference<MethodHandle>> perClassCache, CacheKey cacheKey, MethodHandle handle){
185
/* Keep a strong reference to the FieldCacheKey in the MH being cached so that it won't
186
* be immediately collected. Uses a WeakHashMap<FieldCacheKey, WeakRef<MH>> to cache.
187
* Since the MH keeps a strong ref to the FieldCacheKey, as long as the MH is alive
188
* the Key can't be collected, despite being a weakref.
189
*/
190
handle.cacheKey = cacheKey;
191
perClassCache.put(handle.cacheKey, new WeakReference<MethodHandle>(handle));
192
return handle;
193
}
194
195
}
196
197
198