Skip to content

Commit a937251

Browse files
Move _pydict_global_version to _PyRuntimeState.
1 parent c00d1e0 commit a937251

File tree

13 files changed

+72
-43
lines changed

13 files changed

+72
-43
lines changed

Include/internal/pycore_dict.h

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ extern "C" {
99
# error "this header requires Py_BUILD_CORE define"
1010
#endif
1111

12+
#include "pycore_dict_state.h"
13+
#include "pycore_runtime.h" // _PyRuntime
14+
1215

1316
/* runtime lifecycle */
1417

@@ -17,29 +20,6 @@ extern void _PyDict_Fini(PyInterpreterState *interp);
1720

1821
/* other API */
1922

20-
struct _Py_dict_runtime_state {
21-
uint32_t next_keys_version;
22-
};
23-
24-
#ifndef WITH_FREELISTS
25-
// without freelists
26-
# define PyDict_MAXFREELIST 0
27-
#endif
28-
29-
#ifndef PyDict_MAXFREELIST
30-
# define PyDict_MAXFREELIST 80
31-
#endif
32-
33-
struct _Py_dict_state {
34-
#if PyDict_MAXFREELIST > 0
35-
/* Dictionary reuse scheme to save calls to malloc and free */
36-
PyDictObject *free_list[PyDict_MAXFREELIST];
37-
int numfree;
38-
PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST];
39-
int keys_numfree;
40-
#endif
41-
};
42-
4323
typedef struct {
4424
/* Cached hash code of me_key. */
4525
Py_hash_t me_hash;
@@ -156,13 +136,11 @@ struct _dictvalues {
156136
(PyDictUnicodeEntry*)(&((int8_t*)((dk)->dk_indices))[(size_t)1 << (dk)->dk_log2_index_bytes]))
157137
#define DK_IS_UNICODE(dk) ((dk)->dk_kind != DICT_KEYS_GENERAL)
158138

159-
extern uint64_t _pydict_global_version;
160-
161-
#define DICT_MAX_WATCHERS 8
162139
#define DICT_VERSION_INCREMENT (1 << DICT_MAX_WATCHERS)
163140
#define DICT_VERSION_MASK (DICT_VERSION_INCREMENT - 1)
164141

165-
#define DICT_NEXT_VERSION() (_pydict_global_version += DICT_VERSION_INCREMENT)
142+
#define DICT_NEXT_VERSION() \
143+
(_PyRuntime.dict_state.global_version += DICT_VERSION_INCREMENT)
166144

167145
void
168146
_PyDict_SendEvent(int watcher_bits,

Include/internal/pycore_dict_state.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#ifndef Py_INTERNAL_DICT_STATE_H
2+
#define Py_INTERNAL_DICT_STATE_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
#ifndef Py_BUILD_CORE
8+
# error "this header requires Py_BUILD_CORE define"
9+
#endif
10+
11+
12+
struct _Py_dict_runtime_state {
13+
/*Global counter used to set ma_version_tag field of dictionary.
14+
* It is incremented each time that a dictionary is created and each
15+
* time that a dictionary is modified. */
16+
uint64_t global_version;
17+
uint32_t next_keys_version;
18+
};
19+
20+
21+
#ifndef WITH_FREELISTS
22+
// without freelists
23+
# define PyDict_MAXFREELIST 0
24+
#endif
25+
26+
#ifndef PyDict_MAXFREELIST
27+
# define PyDict_MAXFREELIST 80
28+
#endif
29+
30+
#define DICT_MAX_WATCHERS 8
31+
32+
struct _Py_dict_state {
33+
#if PyDict_MAXFREELIST > 0
34+
/* Dictionary reuse scheme to save calls to malloc and free */
35+
PyDictObject *free_list[PyDict_MAXFREELIST];
36+
int numfree;
37+
PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST];
38+
int keys_numfree;
39+
#endif
40+
PyDict_WatchCallback watchers[DICT_MAX_WATCHERS];
41+
};
42+
43+
44+
#ifdef __cplusplus
45+
}
46+
#endif
47+
#endif /* !Py_INTERNAL_DICT_STATE_H */

Include/internal/pycore_interp.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ extern "C" {
1414
#include "pycore_ast_state.h" // struct ast_state
1515
#include "pycore_code.h" // struct callable_cache
1616
#include "pycore_context.h" // struct _Py_context_state
17-
#include "pycore_dict.h" // struct _Py_dict_state
17+
#include "pycore_dict_state.h" // struct _Py_dict_state
1818
#include "pycore_exceptions.h" // struct _Py_exc_state
1919
#include "pycore_floatobject.h" // struct _Py_float_state
2020
#include "pycore_genobject.h" // struct _Py_async_gen_state
@@ -171,8 +171,6 @@ struct _is {
171171
// Initialized to _PyEval_EvalFrameDefault().
172172
_PyFrameEvalFunction eval_frame;
173173

174-
PyDict_WatchCallback dict_watchers[DICT_MAX_WATCHERS];
175-
176174
Py_ssize_t co_extra_user_count;
177175
freefunc co_extra_freefuncs[MAX_CO_EXTRA_USERS];
178176

Include/internal/pycore_runtime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ extern "C" {
99
#endif
1010

1111
#include "pycore_atomic.h" /* _Py_atomic_address */
12-
#include "pycore_dict.h" // struct _Py_dict_runtime_state
12+
#include "pycore_dict_state.h" // struct _Py_dict_runtime_state
1313
#include "pycore_dtoa.h" // struct _dtoa_runtime_state
1414
#include "pycore_floatobject.h" // struct _Py_float_runtime_state
1515
#include "pycore_gil.h" // struct _gil_runtime_state

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,7 @@ PYTHON_HEADERS= \
16271627
$(srcdir)/Include/internal/pycore_condvar.h \
16281628
$(srcdir)/Include/internal/pycore_context.h \
16291629
$(srcdir)/Include/internal/pycore_dict.h \
1630+
$(srcdir)/Include/internal/pycore_dict_state.h \
16301631
$(srcdir)/Include/internal/pycore_descrobject.h \
16311632
$(srcdir)/Include/internal/pycore_dtoa.h \
16321633
$(srcdir)/Include/internal/pycore_exceptions.h \

Modules/_functoolsmodule.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "Python.h"
22
#include "pycore_call.h" // _PyObject_CallNoArgs()
3+
#include "pycore_dict.h" // _PyDict_Pop_KnownHash()
34
#include "pycore_long.h" // _PyLong_GetZero()
45
#include "pycore_moduleobject.h" // _PyModule_GetState()
56
#include "pycore_object.h" // _PyObject_GC_TRACK

Objects/call.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "Python.h"
22
#include "pycore_call.h" // _PyObject_CallNoArgsTstate()
33
#include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
4+
#include "pycore_dict.h" // _PyDict_FromItems()
45
#include "pycore_object.h" // _PyCFunctionWithKeywords_TrampolineCall()
56
#include "pycore_pyerrors.h" // _PyErr_Occurred()
67
#include "pycore_pystate.h" // _PyThreadState_GET()

Objects/dictobject.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -236,11 +236,6 @@ static int dictresize(PyDictObject *mp, uint8_t log_newsize, int unicode);
236236

237237
static PyObject* dict_iter(PyDictObject *dict);
238238

239-
/*Global counter used to set ma_version_tag field of dictionary.
240-
* It is incremented each time that a dictionary is created and each
241-
* time that a dictionary is modified. */
242-
uint64_t _pydict_global_version = 0;
243-
244239
#include "clinic/dictobject.c.h"
245240

246241

@@ -5681,7 +5676,7 @@ validate_watcher_id(PyInterpreterState *interp, int watcher_id)
56815676
PyErr_Format(PyExc_ValueError, "Invalid dict watcher ID %d", watcher_id);
56825677
return -1;
56835678
}
5684-
if (!interp->dict_watchers[watcher_id]) {
5679+
if (!interp->dict_state.watchers[watcher_id]) {
56855680
PyErr_Format(PyExc_ValueError, "No dict watcher set for ID %d", watcher_id);
56865681
return -1;
56875682
}
@@ -5724,8 +5719,8 @@ PyDict_AddWatcher(PyDict_WatchCallback callback)
57245719
PyInterpreterState *interp = _PyInterpreterState_GET();
57255720

57265721
for (int i = 0; i < DICT_MAX_WATCHERS; i++) {
5727-
if (!interp->dict_watchers[i]) {
5728-
interp->dict_watchers[i] = callback;
5722+
if (!interp->dict_state.watchers[i]) {
5723+
interp->dict_state.watchers[i] = callback;
57295724
return i;
57305725
}
57315726
}
@@ -5741,7 +5736,7 @@ PyDict_ClearWatcher(int watcher_id)
57415736
if (validate_watcher_id(interp, watcher_id)) {
57425737
return -1;
57435738
}
5744-
interp->dict_watchers[watcher_id] = NULL;
5739+
interp->dict_state.watchers[watcher_id] = NULL;
57455740
return 0;
57465741
}
57475742

@@ -5755,7 +5750,7 @@ _PyDict_SendEvent(int watcher_bits,
57555750
PyInterpreterState *interp = _PyInterpreterState_GET();
57565751
for (int i = 0; i < DICT_MAX_WATCHERS; i++) {
57575752
if (watcher_bits & 1) {
5758-
PyDict_WatchCallback cb = interp->dict_watchers[i];
5753+
PyDict_WatchCallback cb = interp->dict_state.watchers[i];
57595754
if (cb && (cb(event, (PyObject*)mp, key, value) < 0)) {
57605755
// some dict modification paths (e.g. PyDict_Clear) can't raise, so we
57615756
// can't propagate exceptions from dict watchers.

Objects/typeobject.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "pycore_call.h"
55
#include "pycore_code.h" // CO_FAST_FREE
66
#include "pycore_compile.h" // _Py_Mangle()
7+
#include "pycore_dict.h" // _PyDict_KeysSize()
78
#include "pycore_initconfig.h" // _PyStatus_OK()
89
#include "pycore_moduleobject.h" // _PyModule_GetDef()
910
#include "pycore_object.h" // _PyType_HasFeature()

PCbuild/pythoncore.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@
208208
<ClInclude Include="..\Include\internal\pycore_condvar.h" />
209209
<ClInclude Include="..\Include\internal\pycore_context.h" />
210210
<ClInclude Include="..\Include\internal\pycore_descrobject.h" />
211+
<ClInclude Include="..\Include\internal\pycore_dict.h" />
212+
<ClInclude Include="..\Include\internal\pycore_dict_state.h" />
211213
<ClInclude Include="..\Include\internal\pycore_dtoa.h" />
212214
<ClInclude Include="..\Include\internal\pycore_exceptions.h" />
213215
<ClInclude Include="..\Include\internal\pycore_fileutils.h" />

PCbuild/pythoncore.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,12 @@
531531
<ClInclude Include="..\Include\internal\pycore_descrobject.h">
532532
<Filter>Include\internal</Filter>
533533
</ClInclude>
534+
<ClInclude Include="..\Include\internal\pycore_dict.h">
535+
<Filter>Include\internal</Filter>
536+
</ClInclude>
537+
<ClInclude Include="..\Include\internal\pycore_dict_state.h">
538+
<Filter>Include\internal</Filter>
539+
</ClInclude>
534540
<ClInclude Include="..\Include\internal\pycore_dtoa.h">
535541
<Filter>Include\internal</Filter>
536542
</ClInclude>

Python/pystate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
458458
Py_CLEAR(interp->interpreter_trampoline);
459459

460460
for (int i=0; i < DICT_MAX_WATCHERS; i++) {
461-
interp->dict_watchers[i] = NULL;
461+
interp->dict_state.watchers[i] = NULL;
462462
}
463463

464464
// XXX Once we have one allocator per interpreter (i.e.

Tools/c-analyzer/cpython/globals-to-fix.tsv

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,6 @@ Objects/unicodeobject.c - ucnhash_capi -
328328
Python/suggestions.c levenshtein_distance buffer -
329329

330330
# other
331-
Objects/dictobject.c - _pydict_global_version -
332331
Objects/funcobject.c - next_func_version -
333332
Objects/object.c - _Py_RefTotal -
334333
Python/perf_trampoline.c - perf_status -

0 commit comments

Comments
 (0)