Skip to content

Commit 25d722f

Browse files
committed
maintain node hygiene in the heap by passing the user objects as arguments to the atExitHook
1 parent ed4b7ee commit 25d722f

File tree

2 files changed

+31
-17
lines changed

2 files changed

+31
-17
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/AtexitModuleBuiltins.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,8 @@ private static class AtExitCallTarget extends RootNode {
8080

8181
private final ContextReference<PythonContext> contextRef = lookupContextReference(PythonLanguage.class);
8282

83-
private Object callable;
84-
private Object[] arguments;
85-
private PKeyword[] keywords;
86-
87-
protected AtExitCallTarget(TruffleLanguage<?> language, Object callable, Object[] arguments, PKeyword[] keywords) {
83+
protected AtExitCallTarget(TruffleLanguage<?> language) {
8884
super(language);
89-
this.callable = callable;
90-
this.arguments = arguments;
91-
this.keywords = keywords;
9285
}
9386

9487
@Override
@@ -98,6 +91,10 @@ public Object execute(VirtualFrame frame) {
9891
context.setTopFrameInfo(PFrame.Reference.EMPTY);
9992
context.setCaughtException(PException.NO_EXCEPTION);
10093

94+
Object callable = frame.getArguments()[0];
95+
Object[] arguments = (Object[]) frame.getArguments()[1];
96+
PKeyword[] keywords = (PKeyword[]) frame.getArguments()[2];
97+
10198
// We deliberately pass 'null' frame here, the execution state will then be taken
10299
// from the context.
103100
try {
@@ -112,8 +109,8 @@ public Object execute(VirtualFrame frame) {
112109
@Specialization
113110
Object register(Object callable, Object[] arguments, PKeyword[] keywords) {
114111
CompilerDirectives.transferToInterpreter();
115-
AtExitCallTarget atExitCallTarget = new AtExitCallTarget(getContext().getLanguage(), callable, arguments, keywords);
116-
getContext().registerShutdownHook(callable, PythonUtils.getOrCreateCallTarget(atExitCallTarget));
112+
AtExitCallTarget atExitCallTarget = new AtExitCallTarget(getContext().getLanguage());
113+
getContext().registerShutdownHook(callable, arguments, keywords, PythonUtils.getOrCreateCallTarget(atExitCallTarget));
117114
return callable;
118115
}
119116
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import java.util.logging.Level;
5252

5353
import org.graalvm.collections.EconomicMap;
54+
import org.graalvm.collections.MapCursor;
5455
import org.graalvm.nativeimage.ImageInfo;
5556
import org.graalvm.options.OptionKey;
5657

@@ -69,6 +70,7 @@
6970
import com.oracle.graal.python.builtins.objects.dict.PDict;
7071
import com.oracle.graal.python.builtins.objects.frame.PFrame;
7172
import com.oracle.graal.python.builtins.objects.frame.PFrame.Reference;
73+
import com.oracle.graal.python.builtins.objects.function.PKeyword;
7274
import com.oracle.graal.python.builtins.objects.list.PList;
7375
import com.oracle.graal.python.builtins.objects.module.PythonModule;
7476
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
@@ -164,6 +166,18 @@ List<WeakReference<Thread>> getOwners() {
164166
}
165167
}
166168

169+
private static final class AtExitHook {
170+
final Object[] arguments;
171+
final PKeyword[] keywords;
172+
final CallTarget ct;
173+
174+
AtExitHook(Object[] arguments, PKeyword[] keywords, CallTarget ct) {
175+
this.arguments = arguments;
176+
this.keywords = keywords;
177+
this.ct = ct;
178+
}
179+
}
180+
167181
static final String PREFIX = "/";
168182
static final String LIB_PYTHON_3 = "/lib-python/3";
169183
static final String LIB_GRAALPYTHON = "/lib-graalpython";
@@ -178,7 +192,7 @@ List<WeakReference<Thread>> getOwners() {
178192
private PythonModule mainModule;
179193
private final PythonCore core;
180194
private final List<ShutdownHook> shutdownHooks = new ArrayList<>();
181-
private final EconomicMap<Object, CallTarget> atExitHooks = EconomicMap.create();
195+
private final EconomicMap<Object, AtExitHook> atExitHooks = EconomicMap.create(0);
182196
private final HashMap<PythonNativeClass, CyclicAssumption> nativeClassStableAssumptions = new HashMap<>();
183197
private final AtomicLong globalId = new AtomicLong(Integer.MAX_VALUE * 2L + 4L);
184198
private final ThreadGroup threadGroup = new ThreadGroup(GRAALPYTHON_THREADS);
@@ -653,8 +667,8 @@ public void registerShutdownHook(ShutdownHook shutdownHook) {
653667
}
654668

655669
@TruffleBoundary
656-
public void registerShutdownHook(Object callable, CallTarget ct) {
657-
atExitHooks.put(callable, ct);
670+
public void registerShutdownHook(Object callable, Object[] arguments, PKeyword[] keywords, CallTarget ct) {
671+
atExitHooks.put(callable, new AtExitHook(arguments, keywords, ct));
658672
}
659673

660674
@TruffleBoundary
@@ -666,13 +680,16 @@ public void deregisterShutdownHook(Object callable) {
666680
public void runShutdownHooks() {
667681
handler.shutdown();
668682
// run atExitHooks in reverse order they were registered
669-
CallTarget[] hooks = new CallTarget[atExitHooks.size()];
670-
Iterator<CallTarget> hooksIter = atExitHooks.getValues().iterator();
683+
MapCursor<Object, AtExitHook> cursor = atExitHooks.getEntries();
684+
AtExitHook[] hooks = new AtExitHook[atExitHooks.size()];
685+
Object[] callables = new Object[atExitHooks.size()];
671686
for (int i = 0; i < hooks.length; i++) {
672-
hooks[i] = hooksIter.next();
687+
cursor.advance();
688+
callables[i] = cursor.getKey();
689+
hooks[i] = cursor.getValue();
673690
}
674691
for (int i = hooks.length - 1; i >= 0; i--) {
675-
hooks[i].call();
692+
hooks[i].ct.call(callables[i], hooks[i].arguments, hooks[i].keywords);
676693
}
677694
for (ShutdownHook h : shutdownHooks) {
678695
h.call(this);

0 commit comments

Comments
 (0)