Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6738185
Verify context can be GCed after evaluation
JaroslavTulach Oct 29, 2025
d21d2fd
Cache EnsoMultiType instances per EnsoContext only
JaroslavTulach Oct 29, 2025
b9f1a97
Merge remote-tracking branch 'origin/develop' into wip/jtulach/Contex…
JaroslavTulach Oct 29, 2025
f2f638d
Let's make sure EnsoContext is garbage collected after each ContextUt…
JaroslavTulach Oct 29, 2025
c98bfc3
Separating the assertGC into own file
JaroslavTulach Oct 30, 2025
11f1a28
Avoid stack frame reference to ensoContext to allow GC of EnsoContext
JaroslavTulach Oct 30, 2025
7a1a95d
Dump .hprof file on out of memory errors
JaroslavTulach Oct 30, 2025
d8b80fe
Specify path to runtime-integration-tests/target/scala-2.13 directory
JaroslavTulach Oct 30, 2025
df08637
Try harder to process CleanableReference.QUEUE by creating new Context
JaroslavTulach Oct 30, 2025
0cc51c3
Eventually give up on GCing
JaroslavTulach Oct 30, 2025
1a63754
Don't hold EnsoContext via polyCtx
JaroslavTulach Oct 30, 2025
aa91c51
Allow to opt-out of assertGC check for ContextUtils
JaroslavTulach Oct 30, 2025
09277b0
Introducing topScope() getter for simple access to TopScope
JaroslavTulach Oct 30, 2025
7f4b17d
More tests that GC EnsoContext
JaroslavTulach Oct 30, 2025
35014cb
Clean up local variables to allow GC of the EnsoContext
JaroslavTulach Oct 30, 2025
fc3401b
assertGC is on by default when used as @Rule only
JaroslavTulach Oct 31, 2025
be9a9bd
Try harder to GC after five unsuccessful System.gc() calls
JaroslavTulach Oct 31, 2025
1addaa1
Clean Parameters when the test suite is over
JaroslavTulach Oct 31, 2025
e4a4ff2
Clean static state
JaroslavTulach Oct 31, 2025
23dcbef
Cleanup static values @AfterClass
JaroslavTulach Oct 31, 2025
d09e293
Cleanup EnsoMultiValues when no longer used
JaroslavTulach Oct 31, 2025
bff788a
Explicitly enter/leave context when computing @Parameterized.Parameters
JaroslavTulach Oct 31, 2025
235a5fb
Don't try to access context to assert GC in HelloWorldCacheTest
JaroslavTulach Oct 31, 2025
56c1653
Disable assertGC in these @Parametrized tests as parameters are leaki…
JaroslavTulach Oct 31, 2025
e700394
Clean all OtherJvmPool data when closing a channel
JaroslavTulach Oct 31, 2025
daeb088
Manually used ContextUtils don't check assertGC anymore. Removing the…
JaroslavTulach Oct 31, 2025
25314c5
= null no longer needed
JaroslavTulach Oct 31, 2025
31c4c39
Making anyIr per ModuleContext constant again
JaroslavTulach Oct 31, 2025
153dd0d
Even less = null assignments as assertGC is off for these cases now
JaroslavTulach Oct 31, 2025
1b2cef2
assertGC(false) in jvm-interop tests
JaroslavTulach Nov 1, 2025
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 @@ -252,7 +252,7 @@ case object TypeSignatures extends IRPass {
}
}

val anyIr = Name.Qualified(
def anyIr = Name.Qualified(
List(
Name.Literal("Standard", isMethod = false, identifiedLocation = null),
Name.Literal("Base", isMethod = false, identifiedLocation = null),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.enso.interpreter.runtime;

import static org.junit.Assert.assertEquals;

import org.enso.test.utils.ContextUtils;
import org.junit.Rule;
import org.junit.Test;

public class ContextGCTest {
@Rule public final ContextUtils ctx = ContextUtils.createDefault();

@Test
public void simpleEval() throws Exception {
var fourtyTwo =
ctx.evalModule(
"""
from Standard.Base import all

main = 6 * 7
""");
assertEquals(42, fourtyTwo.asInt());
}

@Test
public void multiValue() throws Exception {
var arr =
ctx.evalModule(
"""
from Standard.Base import all

type T

Integer.from (_:T) = 42
Text.from (_:T) = "Meaning"

main =
conv t -> Integer&Text = t
v = conv T
[v, v:Text, v:Integer]

""");
assertEquals(42, arr.getArrayElement(2).asInt());
assertEquals("Meaning", arr.getArrayElement(1).asString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.oracle.truffle.api.nodes.Node;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.enso.interpreter.runtime.EnsoContext;

Expand All @@ -19,8 +20,8 @@
* <p>Think twice before opening this type to public!
*/
final class EnsoMultiType {
private static final ConcurrentHashMap<EnsoMultiType, EnsoMultiType> ALL_TYPES =
new ConcurrentHashMap<>();
private static final EnsoContext.Extra<Map> ALL_TYPES =
new EnsoContext.Extra<>(Map.class, (_) -> new ConcurrentHashMap());

@CompilerDirectives.CompilationFinal(dimensions = 1)
private final Type[] types;
Expand All @@ -41,9 +42,11 @@ private static boolean checkNonNull(Type[] types) {
}

@CompilerDirectives.TruffleBoundary
static EnsoMultiType findOrCreateSlow(Type[] types, int from, int to) {
@SuppressWarnings("unchecked")
static EnsoMultiType findOrCreateSlow(EnsoContext ctx, Type[] types, int from, int to) {
var mt = new EnsoMultiType(Arrays.copyOfRange(types, from, to));
return ALL_TYPES.computeIfAbsent(mt, java.util.function.Function.identity());
var registry = ALL_TYPES.get(ctx);
return (EnsoMultiType) registry.computeIfAbsent(mt, java.util.function.Function.identity());
}

final int typesLength() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ final EnsoMultiType cachedMultiType(

@Specialization(replaces = "cachedMultiType")
final EnsoMultiType createMultiType(Type[] types, int from, int to) {
return EnsoMultiType.findOrCreateSlow(types, from, to);
var ctx = EnsoContext.get(this);
return EnsoMultiType.findOrCreateSlow(ctx, types, from, to);
}

@TruffleBoundary
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package org.enso.test.utils;

import static org.junit.Assert.fail;

import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.nodes.Node;
import java.io.ByteArrayOutputStream;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
Expand Down Expand Up @@ -127,8 +131,10 @@ public void resetOut() {
@Override
public void close() {
if (context != null) {
var ref = new WeakReference<>(ensoContext());
context.close();
context = null;
assertGC("EnsoContext can be GCed when context is closed", true, ref);
Copy link
Member Author

Choose a reason for hiding this comment

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

  • The ultimate goal is to make sure that once org.graalvm.polyglot.Context is closed
  • all references to EnsoContext are closed
  • that's not really the case right now and fixes may be needed all over the place to make that happen

}
resetOut();
}
Expand Down Expand Up @@ -458,7 +464,7 @@ private CustomStatement(Statement base, Description description) {
/** Evaluates jUnit {@link org.junit.Test}. */
@Override
public void evaluate() throws Throwable {
try (var ctx = currentCtx()) {
try {
if (alwaysExecuteInContext) {
executeInContext(
() -> {
Expand Down Expand Up @@ -509,4 +515,23 @@ boolean isExecutable() {
return true;
}
}

private static void assertGC(String msg, boolean expectGC, Reference<?> ref) {
for (var i = 1; i < Integer.MAX_VALUE / 2; i *= 2) {
if (ref.get() == null) {
break;
}
System.gc();
}
var obj = ref.get();
if (expectGC) {
if (obj != null) {
fail(msg + " ref still alive: " + obj);
}
} else {
if (obj == null) {
fail(msg + " ref has been cleaned: " + obj);
}
}
}
}
Loading