|
35 | 35 | import java.lang.invoke.CallSite; |
36 | 36 | import java.lang.invoke.ConstantCallSite; |
37 | 37 | import java.lang.invoke.MethodHandle; |
| 38 | +import java.lang.ref.ReferenceQueue; |
38 | 39 | import java.lang.ref.WeakReference; |
39 | 40 | import java.lang.reflect.Executable; |
40 | 41 | import java.lang.reflect.Field; |
@@ -499,7 +500,32 @@ T get() { |
499 | 500 | } |
500 | 501 | } |
501 | 502 |
|
502 | | - @NativeImageReinitialize private HashMap<Long, WeakReference<ResolvedJavaType>> resolvedJavaTypes; |
| 503 | + |
| 504 | + /** |
| 505 | + * A weak reference that also tracks the key used to insert the value into {@link #resolvedJavaTypes} so that |
| 506 | + * it can be removed when the referent is cleared. |
| 507 | + */ |
| 508 | + static class KlassWeakReference extends WeakReference<HotSpotResolvedObjectTypeImpl> { |
| 509 | + |
| 510 | + private final Long klassPointer; |
| 511 | + |
| 512 | + public KlassWeakReference(Long klassPointer, HotSpotResolvedObjectTypeImpl referent, ReferenceQueue<HotSpotResolvedObjectTypeImpl> q) { |
| 513 | + super(referent, q); |
| 514 | + this.klassPointer = klassPointer; |
| 515 | + } |
| 516 | + } |
| 517 | + |
| 518 | + /** |
| 519 | + * A mapping from the {@code Klass*} to the corresponding {@link HotSpotResolvedObjectTypeImpl}. The value is |
| 520 | + * held weakly through a {@link KlassWeakReference} so that unused types can be unloaded when the compiler no longer needs them. |
| 521 | + */ |
| 522 | + @NativeImageReinitialize private HashMap<Long, KlassWeakReference> resolvedJavaTypes; |
| 523 | + |
| 524 | + /** |
| 525 | + * A {@link ReferenceQueue} to track when {@link KlassWeakReference}s have been freed so that the corresponding |
| 526 | + * entry in {@link #resolvedJavaTypes} can be cleared. |
| 527 | + */ |
| 528 | + @NativeImageReinitialize private ReferenceQueue<HotSpotResolvedObjectTypeImpl> resolvedJavaTypesQueue; |
503 | 529 |
|
504 | 530 | /** |
505 | 531 | * Stores the value set by {@link #excludeFromJVMCICompilation(Module...)} so that it can be |
@@ -662,24 +688,41 @@ HotSpotResolvedJavaType fromClass(Class<?> javaClass) { |
662 | 688 | return fromClass0(javaClass); |
663 | 689 | } |
664 | 690 |
|
665 | | - synchronized HotSpotResolvedObjectTypeImpl fromMetaspace(long klassPointer) { |
| 691 | + synchronized HotSpotResolvedObjectTypeImpl fromMetaspace(Long klassPointer) { |
666 | 692 | if (resolvedJavaTypes == null) { |
667 | 693 | resolvedJavaTypes = new HashMap<>(); |
| 694 | + resolvedJavaTypesQueue = new ReferenceQueue<>(); |
668 | 695 | } |
669 | 696 | assert klassPointer != 0; |
670 | | - WeakReference<ResolvedJavaType> klassReference = resolvedJavaTypes.get(klassPointer); |
| 697 | + KlassWeakReference klassReference = resolvedJavaTypes.get(klassPointer); |
671 | 698 | HotSpotResolvedObjectTypeImpl javaType = null; |
672 | 699 | if (klassReference != null) { |
673 | | - javaType = (HotSpotResolvedObjectTypeImpl) klassReference.get(); |
| 700 | + javaType = klassReference.get(); |
674 | 701 | } |
675 | 702 | if (javaType == null) { |
676 | 703 | String name = compilerToVm.getSignatureName(klassPointer); |
677 | 704 | javaType = new HotSpotResolvedObjectTypeImpl(klassPointer, name); |
678 | | - resolvedJavaTypes.put(klassPointer, new WeakReference<>(javaType)); |
| 705 | + resolvedJavaTypes.put(klassPointer, new KlassWeakReference(klassPointer, javaType, resolvedJavaTypesQueue)); |
679 | 706 | } |
| 707 | + expungeStaleKlassEntries(); |
680 | 708 | return javaType; |
681 | 709 | } |
682 | 710 |
|
| 711 | + |
| 712 | + /** |
| 713 | + * Clean up WeakReferences whose referents have been cleared. This should be called from a synchronized context. |
| 714 | + */ |
| 715 | + private void expungeStaleKlassEntries() { |
| 716 | + KlassWeakReference current = (KlassWeakReference) resolvedJavaTypesQueue.poll(); |
| 717 | + while (current != null) { |
| 718 | + // Make sure the entry is still mapped to the weak reference |
| 719 | + if (resolvedJavaTypes.get(current.klassPointer) == current) { |
| 720 | + resolvedJavaTypes.remove(current.klassPointer); |
| 721 | + } |
| 722 | + current = (KlassWeakReference) resolvedJavaTypesQueue.poll(); |
| 723 | + } |
| 724 | + } |
| 725 | + |
683 | 726 | private JVMCIBackend registerBackend(JVMCIBackend backend) { |
684 | 727 | Class<? extends Architecture> arch = backend.getCodeCache().getTarget().arch.getClass(); |
685 | 728 | JVMCIBackend oldValue = backends.put(arch, backend); |
|
0 commit comments