8
8
int
9
9
_PyStackRef_IsLive (_PyStackRef stackref )
10
10
{
11
- #if defined(Py_GIL_DISABLED ) && defined(Py_STACKREF_DEBUG )
12
- PyInterpreterState * interp = PyInterpreterState_Get ();
13
- struct _Py_stackref_entry * entry = & interp -> stackref_state .entries [stackref .bits >> RESERVED_BITS ];
14
- return entry -> is_live ;
15
- #else
11
+ _Py_stackref_to_object_transition (stackref , BORROW );
16
12
return 1 ;
17
- #endif
18
13
}
19
14
15
+
20
16
#if defined(Py_GIL_DISABLED ) && defined(Py_STACKREF_DEBUG )
21
17
PyObject *
22
18
_Py_stackref_to_object_transition (_PyStackRef stackref , _PyStackRef_OpKind op )
23
19
{
24
- PyObject * res ;
20
+ PyObject * res = NULL ;
25
21
PyInterpreterState * interp = PyInterpreterState_Get ();
26
22
assert (interp != NULL );
23
+ int is_null = 0 ;
24
+ void * bits = (void * )(stackref .bits >> RESERVED_BITS );
27
25
switch (op ) {
28
26
case STEAL : {
27
+ // We need to distinguish NULL here because _Py_hashtable_get
28
+ // returns NULL if it cannot find a value.
29
+ if (bits == 0 ) {
30
+ is_null = 1 ;
31
+ break ;
32
+ }
29
33
PyMutex_Lock (& interp -> stackref_state .lock );
30
- struct _Py_stackref_entry * entry = & interp -> stackref_state .entries [ stackref . bits >> RESERVED_BITS ] ;
31
- assert ( entry -> is_live );
32
- res = entry -> obj ;
33
- entry -> is_live = _Py_IsImmortal ( entry -> obj );
34
+ res = ( PyObject * ) _Py_hashtable_get ( interp -> stackref_state .entries , bits ) ;
35
+ if ( res != NULL && ! _Py_IsImmortal ( res )) {
36
+ res = ( PyObject * ) _Py_hashtable_steal ( interp -> stackref_state . entries , bits ) ;
37
+ }
34
38
PyMutex_Unlock (& interp -> stackref_state .lock );
35
39
break ;
36
40
}
37
41
case NEW :
38
42
case BORROW : {
39
- struct _Py_stackref_entry * entry = & interp -> stackref_state .entries [stackref .bits >> RESERVED_BITS ];
40
- assert (entry -> is_live );
41
- res = entry -> obj ;
43
+ if (bits == 0 ) {
44
+ is_null = 1 ;
45
+ break ;
46
+ }
47
+ PyMutex_Lock (& interp -> stackref_state .lock );
48
+ res = (PyObject * )_Py_hashtable_get (interp -> stackref_state .entries , bits );
49
+ PyMutex_Unlock (& interp -> stackref_state .lock );
42
50
break ;
43
51
}
44
52
}
53
+ assert ((res != NULL ) ^ is_null );
45
54
return res ;
46
55
}
47
56
@@ -55,30 +64,17 @@ _Py_object_to_stackref_transition(PyObject *obj, char tag, _PyStackRef_OpKind op
55
64
case STEAL :
56
65
case NEW :
57
66
{
67
+ if (obj == NULL ) {
68
+ return PyStackRef_NULL ;
69
+ }
58
70
PyMutex_Lock (& interp -> stackref_state .lock );
59
- res .bits = (interp -> stackref_state .next_ref << RESERVED_BITS ) | tag ;
60
- struct _Py_stackref_entry * entry = & interp -> stackref_state .entries [interp -> stackref_state .next_ref ];
61
- entry -> is_live = 1 ;
62
- entry -> obj = obj ;
63
- interp -> stackref_state .next_ref ++ ;
64
- // Out of space, allocate new one.
65
- if (interp -> stackref_state .next_ref >= interp -> stackref_state .n_entries ) {
66
- size_t old_size = interp -> stackref_state .n_entries ;
67
- interp -> stackref_state .n_entries *= 2 ;
68
- struct _Py_stackref_entry * new_mem = PyMem_Malloc (
69
- sizeof (struct _Py_stackref_entry ) *
70
- interp -> stackref_state .n_entries );
71
- if (new_mem == NULL ) {
72
- fprintf (stderr , "OOM for PyStackRef\n" );
73
- Py_FatalError ("Cannot allocate memory for stack references.\n" );
74
- return PyStackRef_NULL ;
75
- }
76
- memcpy (new_mem ,
77
- interp -> stackref_state .entries ,
78
- old_size * sizeof (struct _Py_stackref_entry ));
79
- PyMem_Free (interp -> stackref_state .entries );
80
- interp -> stackref_state .entries = new_mem ;
71
+ uintptr_t key = interp -> stackref_state .next_ref ;
72
+ res .bits = (key << RESERVED_BITS ) | tag ;
73
+ int err = _Py_hashtable_set (interp -> stackref_state .entries , (void * )key , obj );
74
+ if (err < 0 ) {
75
+ Py_FatalError ("Stackref handle allocation failed.\n" );
81
76
}
77
+ interp -> stackref_state .next_ref ++ ;
82
78
PyMutex_Unlock (& interp -> stackref_state .lock );
83
79
break ;
84
80
}
@@ -91,13 +87,7 @@ _Py_object_to_stackref_transition(PyObject *obj, char tag, _PyStackRef_OpKind op
91
87
void
92
88
_PyStackRef_Close (_PyStackRef stackref )
93
89
{
94
- PyInterpreterState * interp = PyInterpreterState_Get ();
95
- assert (interp != NULL );
96
- PyMutex_Lock (& interp -> stackref_state .lock );
97
- struct _Py_stackref_entry * entry = & interp -> stackref_state .entries [stackref .bits >> RESERVED_BITS ];
98
- assert (entry -> is_live );
99
- entry -> is_live = _Py_IsImmortal (entry -> obj );
100
- PyMutex_Unlock (& interp -> stackref_state .lock );
90
+ _Py_stackref_to_object_transition (stackref , STEAL );
101
91
}
102
92
103
93
_PyStackRef
0 commit comments