Skip to content

Commit 7bb92b6

Browse files
committed
Move thread-local dict to PythonThreadState
1 parent da4903c commit 7bb92b6

File tree

3 files changed

+77
-78
lines changed

3 files changed

+77
-78
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1662,7 +1662,7 @@ abstract static class PyThreadState_Get extends NativeBuiltin {
16621662
@Specialization
16631663
PThreadState get() {
16641664
// does not require a 'to_sulong' since it is already a native wrapper type
1665-
return getContext().getCustomThreadState();
1665+
return new PThreadState(getContext().getThreadState());
16661666
}
16671667
}
16681668

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/PThreadState.java

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545

4646
import com.oracle.graal.python.PythonLanguage;
4747
import com.oracle.graal.python.builtins.objects.PNone;
48+
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
4849
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.GetNativeNullNode;
4950
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.IsPointerNode;
5051
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.PCallCapiFunction;
@@ -59,6 +60,7 @@
5960
import com.oracle.graal.python.nodes.PNodeWithContext;
6061
import com.oracle.graal.python.nodes.object.GetClassNode;
6162
import com.oracle.graal.python.runtime.PythonContext;
63+
import com.oracle.graal.python.runtime.PythonContext.PythonThreadState;
6264
import com.oracle.graal.python.runtime.PythonOptions;
6365
import com.oracle.graal.python.runtime.exception.PException;
6466
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
@@ -83,6 +85,9 @@
8385
import com.oracle.truffle.api.library.ExportMessage;
8486
import com.oracle.truffle.llvm.spi.NativeTypeLibrary;
8587

88+
/**
89+
* Emulates CPython's {@code PyThreadState} struct.
90+
*/
8691
@ExportLibrary(InteropLibrary.class)
8792
@ExportLibrary(NativeTypeLibrary.class)
8893
public class PThreadState extends PythonNativeWrapper {
@@ -97,14 +102,10 @@ public class PThreadState extends PythonNativeWrapper {
97102
public static final String RECURSION_DEPTH = "recursion_depth";
98103
public static final String OVERFLOWED = "overflowed";
99104

100-
private PDict dict;
101-
102-
public PDict getThreadStateDict() {
103-
return dict;
104-
}
105+
private final PythonThreadState threadState;
105106

106-
public void setThreadStateDict(PDict dict) {
107-
this.dict = dict;
107+
public PThreadState(PythonThreadState threadState) {
108+
this.threadState = threadState;
108109
}
109110

110111
// READ
@@ -133,29 +134,20 @@ protected boolean isMemberReadable(String member) {
133134
}
134135

135136
@ExportMessage
136-
protected Object getMembers(@SuppressWarnings("unused") boolean includeInternal,
137-
@Exclusive @Cached PythonObjectFactory factory) {
138-
return factory.createList(new Object[]{CUR_EXC_TYPE, CUR_EXC_VALUE, CUR_EXC_TRACEBACK, EXC_TYPE, EXC_VALUE, EXC_TRACEBACK, DICT, PREV, RECURSION_DEPTH, OVERFLOWED});
139-
}
140-
141-
@ExportMessage
142-
protected Object readMember(String member,
143-
@Exclusive @Cached ThreadStateReadNode readNode) {
144-
return readNode.execute(member);
137+
protected Object getMembers(@SuppressWarnings("unused") boolean includeInternal) {
138+
return new PythonAbstractObject.Keys(new Object[]{CUR_EXC_TYPE, CUR_EXC_VALUE, CUR_EXC_TRACEBACK, EXC_TYPE, EXC_VALUE, EXC_TRACEBACK, DICT, PREV, RECURSION_DEPTH, OVERFLOWED});
145139
}
146140

147141
@ImportStatic(PThreadState.class)
148142
@GenerateUncached
149-
abstract static class ThreadStateReadNode extends PNodeWithContext {
150-
151-
public abstract Object execute(Object key);
143+
@ExportMessage
144+
abstract static class ReadMember {
152145

153146
@Specialization(guards = "eq(key, CUR_EXC_TYPE)")
154-
Object doCurExcType(@SuppressWarnings("unused") String key,
147+
static Object doCurExcType(PThreadState receiver, @SuppressWarnings("unused") String key,
155148
@Shared("toSulong") @Cached ToSulongNode toSulongNode,
156-
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context,
157149
@Shared("getClassNode") @Cached GetClassNode getClassNode) {
158-
PException currentException = context.getCurrentException();
150+
PException currentException = receiver.threadState.getCurrentException();
159151
Object result = null;
160152
if (currentException != null) {
161153
result = getClassNode.execute(currentException.getUnreifiedException());
@@ -164,10 +156,9 @@ Object doCurExcType(@SuppressWarnings("unused") String key,
164156
}
165157

166158
@Specialization(guards = "eq(key, CUR_EXC_VALUE)")
167-
Object doCurExcValue(@SuppressWarnings("unused") String key,
168-
@Shared("toSulong") @Cached ToSulongNode toSulongNode,
169-
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
170-
PException currentException = context.getCurrentException();
159+
static Object doCurExcValue(PThreadState receiver, @SuppressWarnings("unused") String key,
160+
@Shared("toSulong") @Cached ToSulongNode toSulongNode) {
161+
PException currentException = receiver.threadState.getCurrentException();
171162
Object result = null;
172163
if (currentException != null) {
173164
result = currentException.getEscapedException();
@@ -176,11 +167,10 @@ Object doCurExcValue(@SuppressWarnings("unused") String key,
176167
}
177168

178169
@Specialization(guards = "eq(key, CUR_EXC_TRACEBACK)")
179-
Object doCurExcTraceback(@SuppressWarnings("unused") String key,
170+
static Object doCurExcTraceback(PThreadState receiver, @SuppressWarnings("unused") String key,
180171
@Shared("toSulong") @Cached ToSulongNode toSulongNode,
181-
@Shared("getTraceback") @Cached GetTracebackNode getTracebackNode,
182-
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
183-
PException currentException = context.getCurrentException();
172+
@Shared("getTraceback") @Cached GetTracebackNode getTracebackNode) {
173+
PException currentException = receiver.threadState.getCurrentException();
184174
PTraceback result = null;
185175
if (currentException != null) {
186176
result = getTracebackNode.execute(currentException.getTraceback());
@@ -189,23 +179,21 @@ Object doCurExcTraceback(@SuppressWarnings("unused") String key,
189179
}
190180

191181
@Specialization(guards = "eq(key, EXC_TYPE)")
192-
Object doExcType(@SuppressWarnings("unused") String key,
182+
static Object doExcType(PThreadState receiver, @SuppressWarnings("unused") String key,
193183
@Shared("toSulong") @Cached ToSulongNode toSulongNode,
194-
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context,
195184
@Shared("getClassNode") @Cached GetClassNode getClassNode) {
196-
PException currentException = context.getCaughtException();
185+
PException caughtException = receiver.threadState.getCaughtException();
197186
Object result = null;
198-
if (currentException != null) {
199-
result = getClassNode.execute(currentException.getUnreifiedException());
187+
if (caughtException != null) {
188+
result = getClassNode.execute(caughtException.getUnreifiedException());
200189
}
201190
return toSulongNode.execute(result != null ? result : PNone.NO_VALUE);
202191
}
203192

204193
@Specialization(guards = "eq(key, EXC_VALUE)")
205-
Object doExcValue(@SuppressWarnings("unused") String key,
206-
@Shared("toSulong") @Cached ToSulongNode toSulongNode,
207-
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
208-
PException currentException = context.getCaughtException();
194+
static Object doExcValue(PThreadState receiver, @SuppressWarnings("unused") String key,
195+
@Shared("toSulong") @Cached ToSulongNode toSulongNode) {
196+
PException currentException = receiver.threadState.getCaughtException();
209197
Object result = null;
210198
if (currentException != null) {
211199
result = currentException.getEscapedException();
@@ -214,11 +202,10 @@ Object doExcValue(@SuppressWarnings("unused") String key,
214202
}
215203

216204
@Specialization(guards = "eq(key, EXC_TRACEBACK)")
217-
Object doExcTraceback(@SuppressWarnings("unused") String key,
205+
static Object doExcTraceback(PThreadState receiver, @SuppressWarnings("unused") String key,
218206
@Shared("toSulong") @Cached ToSulongNode toSulongNode,
219-
@Shared("getTraceback") @Cached GetTracebackNode getTracebackNode,
220-
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
221-
PException currentException = context.getCaughtException();
207+
@Shared("getTraceback") @Cached GetTracebackNode getTracebackNode) {
208+
PException currentException = receiver.threadState.getCaughtException();
222209
PTraceback result = null;
223210
if (currentException != null) {
224211
result = getTracebackNode.execute(currentException.getTraceback());
@@ -227,21 +214,20 @@ Object doExcTraceback(@SuppressWarnings("unused") String key,
227214
}
228215

229216
@Specialization(guards = "eq(key, DICT)")
230-
Object doDict(@SuppressWarnings("unused") String key,
217+
static Object doDict(PThreadState receiver, @SuppressWarnings("unused") String key,
231218
@Cached PythonObjectFactory factory,
232-
@Shared("toSulong") @Cached ToSulongNode toSulongNode,
233-
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
234-
PThreadState customThreadState = context.getCustomThreadState();
235-
PDict threadStateDict = customThreadState.getThreadStateDict();
219+
@Shared("toSulong") @Cached ToSulongNode toSulongNode) {
220+
PDict threadStateDict = receiver.threadState.getDict();
236221
if (threadStateDict == null) {
237222
threadStateDict = factory.createDict();
238-
customThreadState.setThreadStateDict(threadStateDict);
223+
receiver.threadState.setDict(threadStateDict);
239224
}
240225
return toSulongNode.execute(threadStateDict != null ? threadStateDict : PNone.NO_VALUE);
241226
}
242227

243228
@Specialization(guards = "eq(key, PREV)")
244-
Object doPrev(@SuppressWarnings("unused") String key,
229+
@SuppressWarnings("unused")
230+
static Object doPrev(PThreadState receiver, String key,
245231
@Cached GetNativeNullNode getNativeNullNode) {
246232
return getNativeNullNode.execute(null);
247233
}
@@ -256,14 +242,16 @@ public Object visitFrame(FrameInstance frameInstance) {
256242
}
257243

258244
@Specialization(guards = "eq(key, RECURSION_DEPTH)")
259-
long doRecursionDepth(@SuppressWarnings("unused") String key) {
245+
@SuppressWarnings("unused")
246+
static long doRecursionDepth(PThreadState receiver, String key) {
260247
DepthCounter visitor = new DepthCounter();
261248
Truffle.getRuntime().iterateFrames(visitor);
262249
return visitor.depth;
263250
}
264251

265252
@Specialization(guards = "eq(key, OVERFLOWED)")
266-
long doOverflowed(@SuppressWarnings("unused") String key) {
253+
@SuppressWarnings("unused")
254+
static long doOverflowed(PThreadState receiver, String key) {
267255
return 0;
268256
}
269257

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

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import java.util.LinkedList;
4848
import java.util.List;
4949
import java.util.Map;
50-
import java.util.Set;
5150
import java.util.WeakHashMap;
5251
import java.util.concurrent.atomic.AtomicLong;
5352
import java.util.concurrent.locks.ReentrantLock;
@@ -62,7 +61,6 @@
6261
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
6362
import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass;
6463
import com.oracle.graal.python.builtins.objects.cext.capi.CApiContext;
65-
import com.oracle.graal.python.builtins.objects.cext.capi.PThreadState;
6664
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper;
6765
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContext;
6866
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
@@ -115,6 +113,9 @@ public final class PythonContext {
115113
private static final TruffleLogger LOGGER = PythonLanguage.getLogger(PythonContext.class);
116114
private volatile boolean finalizing;
117115

116+
/**
117+
* A class to store thread-local data mostly like CPython's {@code PyThreadState}.
118+
*/
118119
public static final class PythonThreadState {
119120
private boolean shuttingDown = false;
120121

@@ -135,6 +136,13 @@ public static final class PythonThreadState {
135136
/* set to emulate Py_ReprEnter/Leave */
136137
HashSet<Object> reprObjectSet;
137138

139+
/* corresponds to 'PyThreadState.dict' */
140+
PDict dict;
141+
142+
/*
143+
* The constructor needs to have this particular signature such that we can use it for
144+
* ContextThreadLocal.
145+
*/
138146
@SuppressWarnings("unused")
139147
public PythonThreadState(PythonContext context, Thread owner) {
140148
}
@@ -159,6 +167,30 @@ boolean reprEnter(Object item) {
159167
void reprLeave(Object item) {
160168
reprObjectSet.remove(item);
161169
}
170+
171+
public PException getCurrentException() {
172+
return currentException;
173+
}
174+
175+
public void setCurrentException(PException currentException) {
176+
this.currentException = currentException;
177+
}
178+
179+
public PException getCaughtException() {
180+
return caughtException;
181+
}
182+
183+
public void setCaughtException(PException caughtException) {
184+
this.caughtException = caughtException;
185+
}
186+
187+
public PDict getDict() {
188+
return dict;
189+
}
190+
191+
public void setDict(PDict dict) {
192+
this.dict = dict;
193+
}
162194
}
163195

164196
private static final class AtExitHook {
@@ -232,9 +264,6 @@ private static final class AtExitHook {
232264

233265
private final ReentrantLock globalInterpreterLock = new ReentrantLock();
234266

235-
/** The thread-local state object. */
236-
private ThreadLocal<PThreadState> customThreadState;
237-
238267
/** Native wrappers for context-insensitive singletons like {@link PNone#NONE}. */
239268
@CompilationFinal(dimensions = 1) private final PythonNativeWrapper[] singletonNativePtrs = new PythonNativeWrapper[PythonLanguage.getNumberOfSpecialSingletons()];
240269

@@ -831,10 +860,6 @@ public void runShutdownHooks() {
831860
for (ShutdownHook h : shutdownHooks) {
832861
h.call(this);
833862
}
834-
// destroy thread state
835-
if (customThreadState != null) {
836-
customThreadState.set(null);
837-
}
838863
}
839864

840865
@TruffleBoundary
@@ -899,16 +924,6 @@ private void shutdownThreads() {
899924
}
900925
}
901926

902-
@TruffleBoundary
903-
public PThreadState getCustomThreadState() {
904-
if (customThreadState == null) {
905-
ThreadLocal<PThreadState> threadLocal = new ThreadLocal<>();
906-
threadLocal.set(new PThreadState());
907-
customThreadState = threadLocal;
908-
}
909-
return customThreadState.get();
910-
}
911-
912927
public void initializeMainModule(String path) {
913928
if (path != null) {
914929
mainModule.setAttribute(__FILE__, path);
@@ -1092,14 +1107,10 @@ public void popCurrentImport() {
10921107

10931108
public Thread[] getThreads() {
10941109
CompilerAsserts.neverPartOfCompilation();
1095-
Set<Thread> threads = new HashSet<>();
1096-
for (Thread th : threadStateMapping.keySet()) {
1097-
threads.add(th);
1098-
}
1099-
return threads.toArray(new Thread[0]);
1110+
return threadStateMapping.keySet().toArray(new Thread[0]);
11001111
}
11011112

1102-
private PythonThreadState getThreadState() {
1113+
public PythonThreadState getThreadState() {
11031114
PythonThreadState curThreadState = getThreadStateInternal();
11041115
if (curThreadState.isShuttingDown()) {
11051116
// we're shutting down, just release and die

0 commit comments

Comments
 (0)