Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
Expand Down Expand Up @@ -499,7 +500,32 @@ T get() {
}
}

@NativeImageReinitialize private HashMap<Long, WeakReference<ResolvedJavaType>> resolvedJavaTypes;

/**
* A weak reference that also tracks the key used to insert the value into {@link #resolvedJavaTypes} so that
* it can be removed when the referent is cleared.
*/
static class KlassWeakReference extends WeakReference<HotSpotResolvedObjectTypeImpl> {

private final Long klassPointer;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is Long instead of long to avoid boxing in expungeStaleEntries?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's autoboxing in a more few places and I wanted to avoid having multiple copies of the box live so I promoted it to Long on entry to fromMetaspace.


public KlassWeakReference(Long klassPointer, HotSpotResolvedObjectTypeImpl referent, ReferenceQueue<HotSpotResolvedObjectTypeImpl> q) {
super(referent, q);
this.klassPointer = klassPointer;
}
}

/**
* A mapping from the {@code Klass*} to the corresponding {@link HotSpotResolvedObjectTypeImpl}. The value is
* held weakly through a {@link KlassWeakReference} so that unused types can be unloaded when the compiler no longer needs them.
*/
@NativeImageReinitialize private HashMap<Long, KlassWeakReference> resolvedJavaTypes;

/**
* A {@link ReferenceQueue} to track when {@link KlassWeakReference}s have been freed so that the corresponding
* entry in {@link #resolvedJavaTypes} can be cleared.
*/
@NativeImageReinitialize private ReferenceQueue<HotSpotResolvedObjectTypeImpl> resolvedJavaTypesQueue;

/**
* Stores the value set by {@link #excludeFromJVMCICompilation(Module...)} so that it can be
Expand Down Expand Up @@ -662,24 +688,41 @@ HotSpotResolvedJavaType fromClass(Class<?> javaClass) {
return fromClass0(javaClass);
}

synchronized HotSpotResolvedObjectTypeImpl fromMetaspace(long klassPointer) {
synchronized HotSpotResolvedObjectTypeImpl fromMetaspace(Long klassPointer) {
if (resolvedJavaTypes == null) {
resolvedJavaTypes = new HashMap<>();
resolvedJavaTypesQueue = new ReferenceQueue<>();
}
assert klassPointer != 0;
WeakReference<ResolvedJavaType> klassReference = resolvedJavaTypes.get(klassPointer);
KlassWeakReference klassReference = resolvedJavaTypes.get(klassPointer);
HotSpotResolvedObjectTypeImpl javaType = null;
if (klassReference != null) {
javaType = (HotSpotResolvedObjectTypeImpl) klassReference.get();
javaType = klassReference.get();
}
if (javaType == null) {
String name = compilerToVm.getSignatureName(klassPointer);
javaType = new HotSpotResolvedObjectTypeImpl(klassPointer, name);
resolvedJavaTypes.put(klassPointer, new WeakReference<>(javaType));
resolvedJavaTypes.put(klassPointer, new KlassWeakReference(klassPointer, javaType, resolvedJavaTypesQueue));
}
expungeStaleKlassEntries();
return javaType;
}


/**
* Clean up WeakReferences whose referents have been cleared. This should be called from a synchronized context.
*/
private void expungeStaleKlassEntries() {
KlassWeakReference current = (KlassWeakReference) resolvedJavaTypesQueue.poll();
while (current != null) {
// Make sure the entry is still mapped to the weak reference
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The atomicity of this test-and-update relies on fromMetaspace being synchronized right? Maybe worth pointing this out in the comment.

if (resolvedJavaTypes.get(current.klassPointer) == current) {
resolvedJavaTypes.remove(current.klassPointer);
}
current = (KlassWeakReference) resolvedJavaTypesQueue.poll();
}
}

private JVMCIBackend registerBackend(JVMCIBackend backend) {
Class<? extends Architecture> arch = backend.getCodeCache().getTarget().arch.getClass();
JVMCIBackend oldValue = backends.put(arch, backend);
Expand Down