43
43
import static com .oracle .graal .python .nodes .BuiltinNames .J__WEAKREF ;
44
44
import static com .oracle .graal .python .nodes .BuiltinNames .T__WEAKREF ;
45
45
import static com .oracle .graal .python .nodes .StringLiterals .T_REF ;
46
+ import static com .oracle .graal .python .runtime .exception .PythonErrorType .TypeError ;
46
47
47
48
import java .lang .ref .Reference ;
48
49
import java .lang .ref .ReferenceQueue ;
70
71
import com .oracle .graal .python .nodes .PGuards ;
71
72
import com .oracle .graal .python .nodes .WriteUnraisableNode ;
72
73
import com .oracle .graal .python .nodes .attributes .ReadAttributeFromObjectNode ;
74
+ import com .oracle .graal .python .nodes .attributes .WriteAttributeToDynamicObjectNode ;
73
75
import com .oracle .graal .python .nodes .function .PythonBuiltinBaseNode ;
74
76
import com .oracle .graal .python .nodes .function .PythonBuiltinNode ;
75
77
import com .oracle .graal .python .nodes .function .builtins .PythonTernaryBuiltinNode ;
79
81
import com .oracle .graal .python .runtime .PythonContext ;
80
82
import com .oracle .graal .python .runtime .PythonOptions ;
81
83
import com .oracle .graal .python .runtime .exception .PException ;
82
- import com .oracle .graal .python .runtime .exception .PythonErrorType ;
83
84
import com .oracle .truffle .api .CompilerDirectives ;
84
85
import com .oracle .truffle .api .dsl .Bind ;
85
86
import com .oracle .truffle .api .dsl .Cached ;
@@ -95,11 +96,58 @@ public class WeakRefModuleBuiltins extends PythonBuiltins {
95
96
private static final HiddenKey weakRefQueueKey = new HiddenKey ("weakRefQueue" );
96
97
private final ReferenceQueue <Object > weakRefQueue = new ReferenceQueue <>();
97
98
99
+ // This GraalPy specific as CPython is storing weakref list within a PyObject (obj +
100
+ // tp_weaklistoffset)
101
+ public static final HiddenKey __WEAKLIST__ = new HiddenKey ("__weaklist__" );
102
+
98
103
@ Override
99
104
protected List <? extends NodeFactory <? extends PythonBuiltinBaseNode >> getNodeFactories () {
100
105
return WeakRefModuleBuiltinsFactory .getFactories ();
101
106
}
102
107
108
+ private static long getBuiltinTypeWeaklistoffset (PythonBuiltinClassType cls ) {
109
+ // @formatter:off
110
+ return switch (cls ) {
111
+ case PythonClass -> 368 ; // type
112
+ case PSet , // set
113
+ PFrozenSet // frozenset
114
+ -> 192 ;
115
+ case PMemoryView , // memoryview
116
+ PCode // code
117
+ -> 136 ;
118
+ case PBuiltinFunctionOrMethod , // builtin_function_or_method
119
+ PGenerator , // generator
120
+ PCoroutine , // coroutine
121
+ PythonModule , // module
122
+ PThreadLocal , // _thread._local
123
+ PRLock , // _thread.RLock
124
+ PBufferedRWPair , // _io.BufferedRWPair
125
+ PAsyncGenerator // async_generator
126
+ -> 40 ;
127
+ case PMethod , // method
128
+ PFileIO , // _io.FileIO
129
+ PTee // itertools._tee
130
+ -> 32 ;
131
+ case PFunction -> 80 ; // function
132
+ case PIOBase , // _io._IOBase
133
+ PRawIOBase , // _io._RawIOBase
134
+ PBufferedIOBase , // _io._BufferedIOBase
135
+ PTextIOBase // _io._TextIOBase
136
+ -> 24 ;
137
+ case PBytesIO , // _io.BytesIO
138
+ PPartial // functools.partial
139
+ -> 48 ;
140
+ case PStringIO -> 112 ; // _io.StringIO
141
+ case PBufferedReader , // _io.BufferedReader
142
+ PBufferedWriter , // _io.BufferedWriter
143
+ PBufferedRandom // _io.BufferedRandom
144
+ -> 144 ;
145
+ case PTextIOWrapper -> 176 ; // _io.TextIOWrapper
146
+ default -> 0 ;
147
+ // @formatter:on
148
+ };
149
+ }
150
+
103
151
private static class WeakrefCallbackAction extends AsyncHandler .AsyncPythonAction {
104
152
private final WeakRefStorage [] references ;
105
153
private int index ;
@@ -179,8 +227,31 @@ public abstract static class ReferenceTypeNode extends PythonTernaryBuiltinNode
179
227
@ Child private CExtNodes .GetTypeMemberNode getTpWeaklistoffsetNode ;
180
228
181
229
@ Specialization (guards = "!isNativeObject(object)" )
182
- public PReferenceType refType (Object cls , Object object , @ SuppressWarnings ("unused" ) PNone none ) {
183
- return factory ().createReferenceType (cls , object , null , getWeakReferenceQueue ());
230
+ public PReferenceType refType (Object cls , Object object , @ SuppressWarnings ("unused" ) PNone none ,
231
+ @ Cached InlinedGetClassNode getClassNode ,
232
+ @ Cached ReadAttributeFromObjectNode getAttrNode ,
233
+ @ Cached WriteAttributeToDynamicObjectNode setAttrNode ) {
234
+ Object obj = object ;
235
+ if (object instanceof PythonBuiltinClassType tobj ) {
236
+ obj = getContext ().getCore ().lookupType (tobj );
237
+ }
238
+
239
+ Object clazz = getClassNode .execute (this , obj );
240
+ boolean allowed = true ;
241
+ if (clazz instanceof PythonBuiltinClassType type ) {
242
+ allowed = getBuiltinTypeWeaklistoffset (type ) != 0 ;
243
+ }
244
+ if (!allowed ) {
245
+ throw raise (TypeError , ErrorMessages .CANNOT_CREATE_WEAK_REFERENCE_TO , obj );
246
+ }
247
+ Object wr = getAttrNode .execute (obj , __WEAKLIST__ );
248
+ if (wr != PNone .NO_VALUE ) {
249
+ return (PReferenceType ) wr ; // is must be a PReferenceType instance.
250
+ }
251
+
252
+ PReferenceType ref = factory ().createReferenceType (cls , obj , null , getWeakReferenceQueue ());
253
+ setAttrNode .execute (obj , __WEAKLIST__ , ref );
254
+ return ref ;
184
255
}
185
256
186
257
@ Specialization (guards = {"!isNativeObject(object)" , "!isPNone(callback)" })
@@ -223,7 +294,7 @@ public PReferenceType refType(Object cls, PythonAbstractNativeObject pythonObjec
223
294
224
295
@ Fallback
225
296
public PReferenceType refType (@ SuppressWarnings ("unused" ) Object cls , Object object , @ SuppressWarnings ("unused" ) Object callback ) {
226
- throw raise (PythonErrorType . TypeError , ErrorMessages .CANNOT_CREATE_WEAK_REFERENCE_TO , object );
297
+ throw raise (TypeError , ErrorMessages .CANNOT_CREATE_WEAK_REFERENCE_TO , object );
227
298
}
228
299
229
300
@ SuppressWarnings ("unchecked" )
0 commit comments