Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Include/internal/pycore_dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif

#include "pycore_freelist.h" // _PyFreeListState
#include "pycore_identifier.h" // _Py_Identifier
#include "pycore_object.h" // PyDictOrValues

Expand Down Expand Up @@ -69,7 +70,7 @@ extern PyObject* _PyDictView_Intersect(PyObject* self, PyObject *other);

/* runtime lifecycle */

extern void _PyDict_Fini(PyInterpreterState *interp);
extern void _PyDict_Fini(_PyFreeListState *state);


/* other API */
Expand Down Expand Up @@ -210,7 +211,7 @@ static inline PyDictUnicodeEntry* DK_UNICODE_ENTRIES(PyDictKeysObject *dk) {
#define DICT_VERSION_MASK (DICT_VERSION_INCREMENT - 1)

#define DICT_NEXT_VERSION(INTERP) \
((INTERP)->dict_state.global_version += DICT_VERSION_INCREMENT)
((INTERP)->global_dict_state.global_version += DICT_VERSION_INCREMENT)

void
_PyDict_SendEvent(int watcher_bits,
Expand Down
13 changes: 13 additions & 0 deletions Include/internal/pycore_freelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ extern "C" {
# define PyTuple_NFREELISTS PyTuple_MAXSAVESIZE
# define PyTuple_MAXFREELIST 2000
# define PyList_MAXFREELIST 80
# define PyDict_MAXFREELIST 80
# define PyFloat_MAXFREELIST 100
# define PyContext_MAXFREELIST 255
# define _PyAsyncGen_MAXFREELIST 80
#else
# define PyTuple_NFREELISTS 0
# define PyTuple_MAXFREELIST 0
# define PyList_MAXFREELIST 0
# define PyDict_MAXFREELIST 0
# define PyFloat_MAXFREELIST 0
# define PyContext_MAXFREELIST 0
# define _PyAsyncGen_MAXFREELIST 0
Expand Down Expand Up @@ -63,6 +65,16 @@ struct _Py_float_state {
#endif
};

struct _Py_dict_state {
#ifdef WITH_FREELISTS
/* Dictionary reuse scheme to save calls to malloc and free */
PyDictObject *free_list[PyDict_MAXFREELIST];
PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST];
int numfree;
int keys_numfree;
#endif
};

struct _Py_slice_state {
#ifdef WITH_FREELISTS
/* Using a cache is very effective since typically only a single slice is
Expand Down Expand Up @@ -97,6 +109,7 @@ typedef struct _Py_freelist_state {
struct _Py_float_state float_state;
struct _Py_tuple_state tuple_state;
struct _Py_list_state list_state;
struct _Py_dict_state dict_state;
struct _Py_slice_state slice_state;
struct _Py_context_state context_state;
struct _Py_async_gen_state async_gen_state;
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ extern void _PyTuple_ClearFreeList(_PyFreeListState *state, int is_finalization)
extern void _PyFloat_ClearFreeList(_PyFreeListState *state, int is_finalization);
extern void _PyList_ClearFreeList(_PyFreeListState *state, int is_finalization);
extern void _PySlice_ClearCache(_PyFreeListState *state);
extern void _PyDict_ClearFreeList(PyInterpreterState *interp);
extern void _PyDict_ClearFreeList(_PyFreeListState *state, int is_finalization);
extern void _PyAsyncGen_ClearFreeLists(_PyFreeListState *state, int is_finalization);
extern void _PyContext_ClearFreeList(_PyFreeListState *state, int is_finalization);
extern void _Py_ScheduleGC(PyInterpreterState *interp);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef Py_INTERNAL_DICT_STATE_H
#define Py_INTERNAL_DICT_STATE_H
#ifndef Py_INTERNAL_GLOBAL_DICT_STATE_H
#define Py_INTERNAL_GLOBAL_DICT_STATE_H
#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -8,33 +8,14 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif


#ifndef WITH_FREELISTS
// without freelists
# define PyDict_MAXFREELIST 0
#endif

#ifndef PyDict_MAXFREELIST
# define PyDict_MAXFREELIST 80
#endif

#define DICT_MAX_WATCHERS 8

struct _Py_dict_state {
struct _Py_global_dict_state {
Copy link
Contributor

@colesbury colesbury Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe _Py_dict_interp_state?

In some places we use "global_state" to mean runtime-global (not interpreter). For example, we have:

  • _dtoa_interp_state (per-interpreter)
  • _mimalloc_interp_state (per-interpreter)
  • _obmalloc_global_state (in PyRuntime)

/*Global counter used to set ma_version_tag field of dictionary.
* It is incremented each time that a dictionary is created and each
* time that a dictionary is modified. */
uint64_t global_version;
uint32_t next_keys_version;

#if PyDict_MAXFREELIST > 0
/* Dictionary reuse scheme to save calls to malloc and free */
PyDictObject *free_list[PyDict_MAXFREELIST];
PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST];
int numfree;
int keys_numfree;
#endif

PyDict_WatchCallback watchers[DICT_MAX_WATCHERS];
};

Expand All @@ -47,4 +28,4 @@ struct _Py_dict_state {
#ifdef __cplusplus
}
#endif
#endif /* !Py_INTERNAL_DICT_STATE_H */
#endif /* !Py_INTERNAL_GLOBAL_DICT_STATE_H */
58 changes: 29 additions & 29 deletions Include/internal/pycore_interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,34 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif

#include <stdbool.h> // bool

#include "pycore_ast_state.h" // struct ast_state
#include "pycore_atexit.h" // struct atexit_state
#include "pycore_ceval_state.h" // struct _ceval_state
#include "pycore_code.h" // struct callable_cache
#include "pycore_context.h" // struct _Py_context_state
#include "pycore_crossinterp.h" // struct _xidregistry
#include "pycore_dict_state.h" // struct _Py_dict_state
#include "pycore_dtoa.h" // struct _dtoa_state
#include "pycore_exceptions.h" // struct _Py_exc_state
#include "pycore_floatobject.h" // struct _Py_float_state
#include "pycore_function.h" // FUNC_MAX_WATCHERS
#include "pycore_gc.h" // struct _gc_runtime_state
#include "pycore_genobject.h" // struct _Py_async_gen_state
#include "pycore_global_objects.h"// struct _Py_interp_cached_objects
#include "pycore_import.h" // struct _import_state
#include "pycore_instruments.h" // _PY_MONITORING_EVENTS
#include "pycore_list.h" // struct _Py_list_state
#include "pycore_mimalloc.h" // struct _mimalloc_interp_state
#include "pycore_object_state.h" // struct _py_object_state
#include "pycore_obmalloc.h" // struct _obmalloc_state
#include "pycore_tstate.h" // _PyThreadStateImpl
#include "pycore_tuple.h" // struct _Py_tuple_state
#include "pycore_typeobject.h" // struct types_state
#include "pycore_unicodeobject.h" // struct _Py_unicode_state
#include "pycore_warnings.h" // struct _warnings_runtime_state
#include <stdbool.h> // bool

#include "pycore_ast_state.h" // struct ast_state
#include "pycore_atexit.h" // struct atexit_state
#include "pycore_ceval_state.h" // struct _ceval_state
#include "pycore_code.h" // struct callable_cache
#include "pycore_context.h" // struct _Py_context_state
#include "pycore_crossinterp.h" // struct _xidregistry
#include "pycore_dtoa.h" // struct _dtoa_state
#include "pycore_exceptions.h" // struct _Py_exc_state
#include "pycore_floatobject.h" // struct _Py_float_state
#include "pycore_freelist.h" // struct _Py_freelist_state
#include "pycore_function.h" // FUNC_MAX_WATCHERS
#include "pycore_gc.h" // struct _gc_runtime_state
#include "pycore_genobject.h" // struct _Py_async_gen_state
#include "pycore_global_dict_state.h" // struct _Py_global_dict_state
#include "pycore_global_objects.h" // struct _Py_interp_cached_objects
#include "pycore_import.h" // struct _import_state
#include "pycore_instruments.h" // _PY_MONITORING_EVENTS
#include "pycore_list.h" // struct _Py_list_state
#include "pycore_mimalloc.h" // struct _mimalloc_interp_state
#include "pycore_object_state.h" // struct _py_object_state
#include "pycore_obmalloc.h" // struct _obmalloc_state
#include "pycore_tstate.h" // _PyThreadStateImpl
#include "pycore_tuple.h" // struct _Py_tuple_state
#include "pycore_typeobject.h" // struct types_state
#include "pycore_unicodeobject.h" // struct _Py_unicode_state
#include "pycore_warnings.h" // struct _warnings_runtime_state


struct _Py_long_state {
Expand Down Expand Up @@ -188,8 +189,7 @@ struct _is {
struct _dtoa_state dtoa;
struct _py_func_state func_state;

struct _Py_tuple_state tuple;
struct _Py_dict_state dict_state;
struct _Py_global_dict_state global_dict_state;
struct _Py_exc_state exc_state;

struct ast_state ast;
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ extern PyTypeObject _PyExc_MemoryError;
}, \
.object_state = _py_object_state_INIT(INTERP), \
.dtoa = _dtoa_state_INIT(&(INTERP)), \
.dict_state = _dict_state_INIT, \
.global_dict_state = _dict_state_INIT, \
.func_state = { \
.next_version = 1, \
}, \
Expand Down
2 changes: 1 addition & 1 deletion Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -1821,7 +1821,6 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_critical_section.h \
$(srcdir)/Include/internal/pycore_crossinterp.h \
$(srcdir)/Include/internal/pycore_dict.h \
$(srcdir)/Include/internal/pycore_dict_state.h \
$(srcdir)/Include/internal/pycore_descrobject.h \
$(srcdir)/Include/internal/pycore_dtoa.h \
$(srcdir)/Include/internal/pycore_exceptions.h \
Expand All @@ -1835,6 +1834,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_genobject.h \
$(srcdir)/Include/internal/pycore_getopt.h \
$(srcdir)/Include/internal/pycore_gil.h \
$(srcdir)/Include/internal/pycore_global_dict_state.h \
$(srcdir)/Include/internal/pycore_global_objects.h \
$(srcdir)/Include/internal/pycore_global_objects_fini_generated.h \
$(srcdir)/Include/internal/pycore_hamt.h \
Expand Down
Loading