Skip to content
Merged
Show file tree
Hide file tree
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 @@ -24,6 +24,7 @@

import java.nio.file.Path;
import java.util.List;
import java.util.Set;

import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.frame.Frame;
Expand Down Expand Up @@ -65,7 +66,7 @@ public interface JDWPContext {
*
* @return array containing every class loaded
*/
KlassRef[] getAllLoadedClasses();
Set<? extends KlassRef> getAllLoadedClasses();

/**
* Finds the method for which an root node was created from.
Expand Down Expand Up @@ -177,9 +178,9 @@ public interface JDWPContext {
* Returns all classes for which the class loader initiated loading.
*
* @param classLoader guest language class loader
* @return array of classes initiated by the class loader
* @return set of classes initiated by the class loader
*/
List<? extends KlassRef> getInitiatedClasses(Object classLoader);
Set<? extends KlassRef> getInitiatedClasses(Object classLoader);

/**
* Retrieves the field value of a static field.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,13 @@ public interface KlassRef {
int getModifiers();

/**
* Returns the array klass for this klass with the given dimensions.
* Returns the array klass for this klass with the given dimensions iff the array type was
* loaded.
*
* @param dimensions array dimension
* @return array klass
*/
KlassRef getArrayClass(int dimensions);
KlassRef getArrayClassNoCreate(int dimensions);

/**
* Returns the major version of the corresponding class file for this klass.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import com.oracle.truffle.api.interop.InteropException;
import com.oracle.truffle.espresso.classfile.attributes.LineNumberTableRef;
Expand Down Expand Up @@ -112,16 +113,16 @@ static class ALL_CLASSES {
static CommandResult createReply(Packet packet, JDWPContext context, DebuggerController controller) {
PacketStream reply = new PacketStream().replyPacket().id(packet.id);

KlassRef[] allLoadedClasses = context.getAllLoadedClasses();
reply.writeInt(allLoadedClasses.length);
Set<? extends KlassRef> allLoadedClasses = context.getAllLoadedClasses();
reply.writeInt(allLoadedClasses.size());

for (KlassRef klass : allLoadedClasses) {
reply.writeByte(TypeTag.getKind(klass));
reply.writeLong(context.getIds().getIdAsLong(klass));
reply.writeString(klass.getTypeAsString());
reply.writeInt(klass.getStatus());
}
controller.fine(() -> "Loaded classes: " + allLoadedClasses.length);
controller.fine(() -> "Loaded classes: " + allLoadedClasses.size());

return new CommandResult(reply);
}
Expand Down Expand Up @@ -438,8 +439,8 @@ static class ALL_CLASSES_WITH_GENERIC {
static CommandResult createReply(Packet packet, JDWPContext context) {
PacketStream reply = new PacketStream().replyPacket().id(packet.id);

KlassRef[] allLoadedClasses = context.getAllLoadedClasses();
reply.writeInt(allLoadedClasses.length);
Set<? extends KlassRef> allLoadedClasses = context.getAllLoadedClasses();
reply.writeInt(allLoadedClasses.size());

for (KlassRef klass : allLoadedClasses) {
reply.writeByte(TypeTag.getKind(klass));
Expand Down Expand Up @@ -2659,7 +2660,7 @@ static CommandResult createReply(Packet packet, JDWPContext context) {
if (classLoader == null) {
return new CommandResult(reply);
}
List<? extends KlassRef> klasses = context.getInitiatedClasses(classLoader);
Set<? extends KlassRef> klasses = context.getInitiatedClasses(classLoader);

reply.writeInt(klasses.size());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ private void skipGuestClass() {
Symbol<Type> elementalTypeSymbol = espressoContext.getTypes().getElementalType(typeSymbol);
if (TypeSymbols.isArray(typeSymbol) && TypeSymbols.isPrimitive(elementalTypeSymbol)) {
Klass elemental = meta.resolvePrimitive(elementalTypeSymbol);
klass = elemental.getArrayClass(TypeSymbols.getArrayDimensions(typeSymbol));
klass = elemental.getArrayKlass(TypeSymbols.getArrayDimensions(typeSymbol));
} else {
klass = meta.loadKlassOrNull(typeSymbol, StaticObject.NULL, StaticObject.NULL);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
import static com.oracle.truffle.espresso.impl.LoadingConstraints.INVALID_LOADER_ID;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.WeakHashMap;
Expand Down Expand Up @@ -190,7 +193,7 @@ public Klass findLoadedClass(Symbol<Type> type, @JavaType(ClassLoader.class) Sta
if (elemental == null) {
return null;
}
return elemental.getArrayClass(TypeSymbols.getArrayDimensions(type));
return elemental.getArrayKlass(TypeSymbols.getArrayDimensions(type));
}

ClassRegistry registry = getClassRegistry(classLoader);
Expand All @@ -199,16 +202,44 @@ public Klass findLoadedClass(Symbol<Type> type, @JavaType(ClassLoader.class) Sta
}

@TruffleBoundary
public List<Klass> getLoadedClassesByLoader(StaticObject classLoader) {
public Set<Klass> getLoadedClassesByLoader(StaticObject classLoader, boolean includeHidden) {
if (classLoader == StaticObject.NULL) {
ArrayList<Klass> result = new ArrayList<>(bootClassRegistry.classes.size());
Set<Klass> result = new HashSet<>();
for (RegistryEntry value : bootClassRegistry.classes.values()) {
result.add(value.klass());
}
if (includeHidden) {
addAllHiddenKlasses(bootClassRegistry, result);
}
// include array classes
result.addAll(getLoadedArrayClasses(result));
// include primitive array classes, but not the primitive classes themselves
result.addAll(getLoadedArrayClasses(Arrays.asList(context.getMeta().PRIMITIVE_KLASSES)));
return result;
}
ClassRegistry classRegistry = getClassRegistry(classLoader);
return classRegistry == null ? Collections.emptyList() : classRegistry.getLoadedKlasses();
if (classRegistry == null) {
return Collections.emptySet();
}
Set<Klass> result = classRegistry.getLoadedKlasses();
if (includeHidden) {
addAllHiddenKlasses(classRegistry, result);
}

// include loaded array classes
result.addAll(getLoadedArrayClasses(result));
return result;
}

private static void addAllHiddenKlasses(ClassRegistry registry, Set<Klass> result) {
synchronized (registry.getStrongHiddenClassRegistrationLock()) {
if (registry.strongHiddenKlasses != null) {
result.addAll(registry.strongHiddenKlasses);
}
if (registry.getHiddenKlasses() != null) {
result.addAll(registry.getHiddenKlasses());
}
}
}

@TruffleBoundary
Expand All @@ -234,21 +265,29 @@ public Klass[] findLoadedClassAny(Symbol<Type> type) {
}

@TruffleBoundary
public List<Klass> getAllLoadedClasses() {
ArrayList<Klass> list = new ArrayList<>();
// add classes from boot registry
for (RegistryEntry entry : bootClassRegistry.classes.values()) {
list.add(entry.klass());
}
public Set<Klass> getAllLoadedClasses() {
// first add classes from boot registry
HashSet<Klass> set = new HashSet<>(getLoadedClassesByLoader(StaticObject.NULL, true));

// add classes from all other registries
synchronized (weakClassLoaderSet) {
for (StaticObject classLoader : weakClassLoaderSet) {
for (RegistryEntry entry : getClassRegistry(classLoader).classes.values()) {
list.add(entry.klass());
}
set.addAll(getLoadedClassesByLoader(classLoader, true));
}
}
return list;
return set;
}

private static Set<Klass> getLoadedArrayClasses(Collection<Klass> elementalKlasses) {
Set<Klass> result = new HashSet<>();
for (Klass elementalKlass : elementalKlasses) {
ArrayKlass arrayKlass = elementalKlass.getArrayKlass(false);
while (arrayKlass != null) {
result.add(arrayKlass);
arrayKlass = arrayKlass.getArrayKlass(false);
}
}
return result;
}

public ModuleRef[] getAllModuleRefs() {
Expand Down Expand Up @@ -298,7 +337,7 @@ public Klass loadKlass(Symbol<Type> type, @JavaType(ClassLoader.class) StaticObj
if (elemental == null) {
return null;
}
return elemental.getArrayClass(TypeSymbols.getArrayDimensions(type));
return elemental.getArrayKlass(TypeSymbols.getArrayDimensions(type));
}
ClassRegistry registry = getClassRegistry(classLoader);
return registry.loadKlass(context, type, protectionDomain);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
Expand Down Expand Up @@ -281,13 +284,19 @@ public byte[] getRetransformBytes(Klass klass) {
* reclaimed, while not appearing in the actual registry. This field simply keeps those hidden
* classes strongly reachable from the class registry.
*/
private volatile Collection<Klass> strongHiddenKlasses = null;
volatile Collection<Klass> strongHiddenKlasses = null;

private Object getStrongHiddenClassRegistrationLock() {
/**
* Hidden classes must be reachable until they're unloaded, because JDWP and JVMTI must be able
* to query all classes.
*/
private volatile WeakHashMap<Klass, Void> hiddenKlasses = null;

Object getStrongHiddenClassRegistrationLock() {
return this;
}

private void registerStrongHiddenClass(Klass klass) {
private void registerStrongHiddenKlass(Klass klass) {
synchronized (getStrongHiddenClassRegistrationLock()) {
if (strongHiddenKlasses == null) {
strongHiddenKlasses = new ArrayList<>();
Expand All @@ -296,6 +305,19 @@ private void registerStrongHiddenClass(Klass klass) {
}
}

private void registerHiddenKlass(Klass klass) {
synchronized (getStrongHiddenClassRegistrationLock()) {
if (hiddenKlasses == null) {
hiddenKlasses = new WeakHashMap<>();
}
hiddenKlasses.put(klass, null);
}
}

public Set<Klass> getHiddenKlasses() {
return hiddenKlasses != null ? hiddenKlasses.keySet() : Collections.emptySet();
}

protected ClassRegistry(long loaderID, ArchivedRegistryData archivedData) {
this.loaderID = loaderID;
if (archivedData != null) {
Expand Down Expand Up @@ -332,7 +354,7 @@ Klass loadKlass(EspressoContext context, Symbol<Type> type, StaticObject protect
if (elemental == null) {
return null;
}
return elemental.getArrayClass(TypeSymbols.getArrayDimensions(type));
return elemental.getArrayKlass(TypeSymbols.getArrayDimensions(type));
}

loadKlassCountInc();
Expand Down Expand Up @@ -373,8 +395,8 @@ Klass loadKlass(EspressoContext context, Symbol<Type> type, StaticObject protect
public abstract @JavaType(ClassLoader.class) StaticObject getClassLoader();

@TruffleBoundary
public List<Klass> getLoadedKlasses() {
ArrayList<Klass> klasses = new ArrayList<>(classes.size());
Set<Klass> getLoadedKlasses() {
HashSet<Klass> klasses = new HashSet<>(classes.size());
for (ClassRegistries.RegistryEntry entry : classes.values()) {
klasses.add(entry.klass());
}
Expand All @@ -388,7 +410,7 @@ public Klass findLoadedKlass(ClassLoadingEnv env, Symbol<Type> type) {
if (elementalKlass == null) {
return null;
}
return elementalKlass.getArrayClass(TypeSymbols.getArrayDimensions(type));
return elementalKlass.getArrayKlass(TypeSymbols.getArrayDimensions(type));
}
ClassRegistries.RegistryEntry entry = classes.get(type);
if (entry == null) {
Expand Down Expand Up @@ -456,7 +478,9 @@ public ObjectKlass defineKlass(EspressoContext context, Symbol<Type> typeOrNull,
if (info.addedToRegistry()) {
registerKlass(klass, type, beforeRetransformBytes);
} else if (info.isStrongHidden()) {
registerStrongHiddenClass(klass);
registerStrongHiddenKlass(klass);
} else {
registerHiddenKlass(klass);
}
return klass;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,18 +945,22 @@ private boolean checkTypeName(@JavaType(String.class) StaticObject computedTypeN
/**
* Gets the array class type representing an array with elements of this type.
*
* This method is equivalent to {@link Klass#getArrayClass()}.
* This method is equivalent to {@link Klass#getArrayKlass()}.
*/
public final ArrayKlass array() {
return getArrayClass();
return getArrayKlass();
}

/**
* Gets the array class type representing an array with elements of this type.
*/
public final ArrayKlass getArrayClass() {
public final ArrayKlass getArrayKlass() {
return getArrayKlass(true);
}

public final ArrayKlass getArrayKlass(boolean create) {
ArrayKlass result = this.arrayKlass;
if (result == null) {
if (result == null && create) {
CompilerDirectives.transferToInterpreterAndInvalidate();
result = createArrayKlass();
}
Expand All @@ -972,22 +976,33 @@ private synchronized ArrayKlass createArrayKlass() {
return result;
}

@Override
public ArrayKlass getArrayClass(int dimensions) {
public ArrayKlass getArrayKlass(int dimensions) {
return getArrayKlass(dimensions, true);
}

private ArrayKlass getArrayKlass(int dimensions, boolean create) {
assert dimensions > 0;
ArrayKlass array = array();
ArrayKlass array = getArrayKlass(create);

// Careful with of impossible void[].
if (array == null) {
return null;
}

for (int i = 1; i < dimensions; ++i) {
array = array.getArrayClass();
array = array.getArrayKlass(create);
if (array == null) {
return null;
}
}
return array;
}

@Override
public ArrayKlass getArrayClassNoCreate(int dimensions) {
return getArrayKlass(dimensions, false);
}

@Override
public final boolean equals(Object that) {
return this == that;
Expand Down Expand Up @@ -1346,7 +1361,7 @@ public StaticObject allocateReferenceArray(int length, IntFunction<StaticObject>
for (int i = 0; i < array.length; ++i) {
array[i] = generator.apply(i);
}
return meta.getAllocator().wrapArrayAs(getArrayClass(), array);
return meta.getAllocator().wrapArrayAs(getArrayKlass(), array);
}

// region Lookup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public static Klass findObjectType(Symbol<Type> symbol, ObjectKlass accessingKla
if (elemental == null) {
return null;
}
return elemental.getArrayClass(TypeSymbols.getArrayDimensions(symbol));
return elemental.getArrayKlass(TypeSymbols.getArrayDimensions(symbol));
} else {
return findInstanceType(symbol, accessingKlass, resolve, meta);
}
Expand Down
Loading