27 import static java.lang.Thread.currentThread; |
27 import static java.lang.Thread.currentThread; |
28 |
28 |
29 import java.io.IOException; |
29 import java.io.IOException; |
30 import java.io.InputStream; |
30 import java.io.InputStream; |
31 import java.util.Arrays; |
31 import java.util.Arrays; |
|
32 import java.util.ArrayList; |
|
33 import java.util.HashMap; |
32 import java.util.Iterator; |
34 import java.util.Iterator; |
33 import java.util.List; |
35 import java.util.List; |
|
36 import java.util.Map; |
34 import java.util.ServiceConfigurationError; |
37 import java.util.ServiceConfigurationError; |
35 import java.util.ServiceLoader; |
38 import java.util.ServiceLoader; |
36 import java.util.concurrent.atomic.AtomicLong; |
39 import java.util.concurrent.atomic.AtomicLong; |
37 |
40 import java.util.function.Supplier; |
|
41 |
|
42 import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup.SpeculationContextObject; |
|
43 |
|
44 import jdk.vm.ci.code.BytecodePosition; |
|
45 import jdk.vm.ci.meta.ResolvedJavaField; |
|
46 import jdk.vm.ci.meta.ResolvedJavaMethod; |
|
47 import jdk.vm.ci.meta.ResolvedJavaType; |
38 import jdk.vm.ci.meta.SpeculationLog.SpeculationReason; |
48 import jdk.vm.ci.meta.SpeculationLog.SpeculationReason; |
|
49 import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding; |
39 import jdk.vm.ci.runtime.JVMCI; |
50 import jdk.vm.ci.runtime.JVMCI; |
40 import jdk.vm.ci.services.JVMCIPermission; |
51 import jdk.vm.ci.services.JVMCIPermission; |
41 import jdk.vm.ci.services.Services; |
52 import jdk.vm.ci.services.Services; |
42 |
53 |
|
54 import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; |
|
55 import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; |
|
56 |
43 /** |
57 /** |
44 * JDK 9+ version of {@link GraalServices}. |
58 * JDK 13+ version of {@link GraalServices}. |
45 */ |
59 */ |
46 public final class GraalServices { |
60 public final class GraalServices { |
47 |
61 |
|
62 private static final Map<Class<?>, List<?>> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null; |
|
63 |
48 private GraalServices() { |
64 private GraalServices() { |
49 } |
65 } |
50 |
66 |
51 /** |
67 /** |
52 * Gets an {@link Iterable} of the providers available for a given service. |
68 * Gets an {@link Iterable} of the providers available for a given service. |
53 * |
69 * |
54 * @throws SecurityException if on JDK8 and a security manager is present and it denies |
70 * @throws SecurityException if on JDK8 and a security manager is present and it denies |
55 * {@link JVMCIPermission} |
71 * {@link JVMCIPermission} |
56 */ |
72 */ |
|
73 @SuppressWarnings("unchecked") |
57 public static <S> Iterable<S> load(Class<S> service) { |
74 public static <S> Iterable<S> load(Class<S> service) { |
58 Iterable<S> iterable = ServiceLoader.load(service); |
75 if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) { |
|
76 List<?> list = servicesCache.get(service); |
|
77 if (list != null) { |
|
78 return (Iterable<S>) list; |
|
79 } |
|
80 if (IS_IN_NATIVE_IMAGE) { |
|
81 throw new InternalError(String.format("No %s providers found when building native image", service.getName())); |
|
82 } |
|
83 } |
|
84 |
|
85 Iterable<S> providers = load0(service); |
|
86 |
|
87 if (IS_BUILDING_NATIVE_IMAGE) { |
|
88 synchronized (servicesCache) { |
|
89 ArrayList<S> providersList = new ArrayList<>(); |
|
90 for (S provider : providers) { |
|
91 providersList.add(provider); |
|
92 } |
|
93 providers = providersList; |
|
94 servicesCache.put(service, providersList); |
|
95 return providers; |
|
96 } |
|
97 } |
|
98 |
|
99 return providers; |
|
100 } |
|
101 |
|
102 protected static <S> Iterable<S> load0(Class<S> service) { |
|
103 Iterable<S> iterable = ServiceLoader.load(service, GraalServices.class.getClassLoader()); |
59 return new Iterable<>() { |
104 return new Iterable<>() { |
60 @Override |
105 @Override |
61 public Iterator<S> iterator() { |
106 public Iterator<S> iterator() { |
62 Iterator<S> iterator = iterable.iterator(); |
107 Iterator<S> iterator = iterable.iterator(); |
63 return new Iterator<>() { |
108 return new Iterator<>() { |
88 * opened all its packages to the module defining {@link GraalServices}. |
133 * opened all its packages to the module defining {@link GraalServices}. |
89 * |
134 * |
90 * @param other all JVMCI packages will be opened to the module defining this class |
135 * @param other all JVMCI packages will be opened to the module defining this class |
91 */ |
136 */ |
92 static void openJVMCITo(Class<?> other) { |
137 static void openJVMCITo(Class<?> other) { |
|
138 if (IS_IN_NATIVE_IMAGE) return; |
|
139 |
93 Module jvmciModule = JVMCI_MODULE; |
140 Module jvmciModule = JVMCI_MODULE; |
94 Module otherModule = other.getModule(); |
141 Module otherModule = other.getModule(); |
95 if (jvmciModule != otherModule) { |
142 if (jvmciModule != otherModule) { |
96 for (String pkg : jvmciModule.getPackages()) { |
143 for (String pkg : jvmciModule.getPackages()) { |
97 if (!jvmciModule.isOpen(pkg, otherModule)) { |
144 if (!jvmciModule.isOpen(pkg, otherModule)) { |
98 // JVMCI initialization opens all JVMCI packages |
145 // JVMCI initialization opens all JVMCI packages |
99 // to Graal which is a prerequisite for Graal to |
146 // to Graal which is a prerequisite for Graal to |
100 // open JVMCI packages to other modules. |
147 // open JVMCI packages to other modules. |
101 JVMCI.initialize(); |
148 JVMCI.getRuntime(); |
102 |
149 |
103 jvmciModule.addOpens(pkg, otherModule); |
150 jvmciModule.addOpens(pkg, otherModule); |
104 } |
151 } |
105 } |
152 } |
106 } |
153 } |
177 */ |
224 */ |
178 static final class DirectSpeculationReason implements SpeculationReason { |
225 static final class DirectSpeculationReason implements SpeculationReason { |
179 final int groupId; |
226 final int groupId; |
180 final String groupName; |
227 final String groupName; |
181 final Object[] context; |
228 final Object[] context; |
|
229 private SpeculationReasonEncoding encoding; |
182 |
230 |
183 DirectSpeculationReason(int groupId, String groupName, Object[] context) { |
231 DirectSpeculationReason(int groupId, String groupName, Object[] context) { |
184 this.groupId = groupId; |
232 this.groupId = groupId; |
185 this.groupName = groupName; |
233 this.groupName = groupName; |
186 this.context = context; |
234 this.context = context; |
201 } |
249 } |
202 |
250 |
203 @Override |
251 @Override |
204 public String toString() { |
252 public String toString() { |
205 return String.format("%s@%d%s", groupName, groupId, Arrays.toString(context)); |
253 return String.format("%s@%d%s", groupName, groupId, Arrays.toString(context)); |
|
254 } |
|
255 |
|
256 @Override |
|
257 public SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) { |
|
258 if (encoding == null) { |
|
259 encoding = encodingSupplier.get(); |
|
260 encoding.addInt(groupId); |
|
261 for (Object o : context) { |
|
262 if (o == null) { |
|
263 encoding.addInt(0); |
|
264 } else { |
|
265 addNonNullObject(encoding, o); |
|
266 } |
|
267 } |
|
268 } |
|
269 return encoding; |
|
270 } |
|
271 |
|
272 static void addNonNullObject(SpeculationReasonEncoding encoding, Object o) { |
|
273 Class<? extends Object> c = o.getClass(); |
|
274 if (c == String.class) { |
|
275 encoding.addString((String) o); |
|
276 } else if (c == Byte.class) { |
|
277 encoding.addByte((Byte) o); |
|
278 } else if (c == Short.class) { |
|
279 encoding.addShort((Short) o); |
|
280 } else if (c == Character.class) { |
|
281 encoding.addShort((Character) o); |
|
282 } else if (c == Integer.class) { |
|
283 encoding.addInt((Integer) o); |
|
284 } else if (c == Long.class) { |
|
285 encoding.addLong((Long) o); |
|
286 } else if (c == Float.class) { |
|
287 encoding.addInt(Float.floatToRawIntBits((Float) o)); |
|
288 } else if (c == Double.class) { |
|
289 encoding.addLong(Double.doubleToRawLongBits((Double) o)); |
|
290 } else if (o instanceof Enum) { |
|
291 encoding.addInt(((Enum<?>) o).ordinal()); |
|
292 } else if (o instanceof ResolvedJavaMethod) { |
|
293 encoding.addMethod((ResolvedJavaMethod) o); |
|
294 } else if (o instanceof ResolvedJavaType) { |
|
295 encoding.addType((ResolvedJavaType) o); |
|
296 } else if (o instanceof ResolvedJavaField) { |
|
297 encoding.addField((ResolvedJavaField) o); |
|
298 } else if (o instanceof SpeculationContextObject) { |
|
299 SpeculationContextObject sco = (SpeculationContextObject) o; |
|
300 // These are compiler objects which all have the same class |
|
301 // loader so the class name uniquely identifies the class. |
|
302 encoding.addString(o.getClass().getName()); |
|
303 sco.accept(new EncodingAdapter(encoding)); |
|
304 } else if (o.getClass() == BytecodePosition.class) { |
|
305 BytecodePosition p = (BytecodePosition) o; |
|
306 while (p != null) { |
|
307 encoding.addInt(p.getBCI()); |
|
308 encoding.addMethod(p.getMethod()); |
|
309 p = p.getCaller(); |
|
310 } |
|
311 } else { |
|
312 throw new IllegalArgumentException("Unsupported type for encoding: " + c.getName()); |
|
313 } |
|
314 } |
|
315 } |
|
316 |
|
317 static class EncodingAdapter implements SpeculationContextObject.Visitor { |
|
318 private final SpeculationReasonEncoding encoding; |
|
319 |
|
320 EncodingAdapter(SpeculationReasonEncoding encoding) { |
|
321 this.encoding = encoding; |
|
322 } |
|
323 |
|
324 @Override |
|
325 public void visitBoolean(boolean v) { |
|
326 encoding.addByte(v ? 1 : 0); |
|
327 } |
|
328 |
|
329 @Override |
|
330 public void visitByte(byte v) { |
|
331 encoding.addByte(v); |
|
332 } |
|
333 |
|
334 @Override |
|
335 public void visitChar(char v) { |
|
336 encoding.addShort(v); |
|
337 } |
|
338 |
|
339 @Override |
|
340 public void visitShort(short v) { |
|
341 encoding.addInt(v); |
|
342 } |
|
343 |
|
344 @Override |
|
345 public void visitInt(int v) { |
|
346 encoding.addInt(v); |
|
347 } |
|
348 |
|
349 @Override |
|
350 public void visitLong(long v) { |
|
351 encoding.addLong(v); |
|
352 } |
|
353 |
|
354 @Override |
|
355 public void visitFloat(float v) { |
|
356 encoding.addInt(Float.floatToRawIntBits(v)); |
|
357 } |
|
358 |
|
359 @Override |
|
360 public void visitDouble(double v) { |
|
361 encoding.addLong(Double.doubleToRawLongBits(v)); |
|
362 } |
|
363 |
|
364 @Override |
|
365 public void visitObject(Object v) { |
|
366 if (v == null) { |
|
367 encoding.addInt(0); |
|
368 } else { |
|
369 DirectSpeculationReason.addNonNullObject(encoding, v); |
|
370 } |
206 } |
371 } |
207 } |
372 } |
208 |
373 |
209 static SpeculationReason createSpeculationReason(int groupId, String groupName, Object... context) { |
374 static SpeculationReason createSpeculationReason(int groupId, String groupName, Object... context) { |
210 return new DirectSpeculationReason(groupId, groupName, context); |
375 return new DirectSpeculationReason(groupId, groupName, context); |