Skip to content

Commit 7ad9131

Browse files
committed
Proposed code changes for [PEP XXX](link).
Signed-off-by: Matthew A Johnson <matjoh@microsoft.com>
1 parent 0fb18b0 commit 7ad9131

49 files changed

Lines changed: 2031 additions & 409 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,6 @@ Python/frozen_modules/MANIFEST
156156
# Ignore ./python binary on Unix but still look into ./Python/ directory.
157157
/python
158158
!/Python/
159+
160+
# Ignore the build directory.
161+
build*

Doc/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@
215215
('c:data', 'PyExc_UnicodeError'),
216216
('c:data', 'PyExc_UnicodeTranslateError'),
217217
('c:data', 'PyExc_ValueError'),
218+
('c:data', 'PyExc_NotWriteableError'),
218219
('c:data', 'PyExc_ZeroDivisionError'),
219220
# C API: Standard Python warning classes
220221
('c:data', 'PyExc_BytesWarning'),

Doc/data/stable_abi.dat

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/cpython/pyerrors.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,13 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFormat(
168168
const char *format,
169169
...);
170170

171+
PyAPI_FUNC(PyObject *) _PyErr_WriteToImmutable(const char* file, int line, PyObject *obj);
172+
#define PyErr_WriteToImmutable(obj) _PyErr_WriteToImmutable(__FILE__, __LINE__, _PyObject_CAST(obj))
173+
174+
PyAPI_FUNC(PyObject *) _PyErr_WriteToImmutableKey(const char* file, int line, PyObject *key);
175+
#define PyErr_WriteToImmutableKey(key) _PyErr_WriteToImmutableKey(__FILE__, __LINE__, _PyObject_CAST(key))
176+
177+
171178
extern PyObject *_PyErr_SetImportErrorWithNameFrom(
172179
PyObject *,
173180
PyObject *,

Include/internal/pycore_dict.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,24 @@ typedef struct {
2424
/* Cached hash code of me_key. */
2525
Py_hash_t me_hash;
2626
PyObject *me_key;
27-
PyObject *me_value; /* This field is only meaningful for combined tables */
27+
PyObject *_me_value; /* This field is only meaningful for combined tables */
2828
} PyDictKeyEntry;
2929

3030
typedef struct {
3131
PyObject *me_key; /* The key must be Unicode and have hash. */
32-
PyObject *me_value; /* This field is only meaningful for combined tables */
32+
PyObject *_me_value; /* This field is only meaningful for combined tables */
3333
} PyDictUnicodeEntry;
3434

35+
#define _PyDictEntry_IsImmutable(entry) (((uintptr_t)((entry)->_me_value)) & 0x1)
36+
#define _PyDictEntry_SetImmutable(entry) ((entry)->_me_value = (PyObject*)((uintptr_t)(entry)->_me_value | 0x1))
37+
#define _PyDictEntry_Hash(entry) ((entry)->me_hash)
38+
#define _PyDictEntry_Key(entry) ((entry)->me_key)
39+
#define _PyDictEntry_Value(entry) ((PyObject*)((((uintptr_t)((entry)->_me_value)) >> 1) << 1))
40+
#define _PyDictEntry_SetValue(entry, value) ((entry)->_me_value = value)
41+
#define _PyDictEntry_IsEmpty(entry) ((entry)->_me_value == NULL)
42+
43+
extern PyObject *_PyDict_IsKeyImmutable(PyObject* op, PyObject* key);
44+
3545
extern PyDictKeysObject *_PyDict_NewKeysForClass(void);
3646
extern PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *);
3747

@@ -50,6 +60,7 @@ extern Py_ssize_t _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t has
5060
extern Py_ssize_t _PyDict_LookupIndex(PyDictObject *, PyObject *);
5161
extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject *key);
5262
extern PyObject *_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *);
63+
extern PyObject *_PyDict_SetKeyImmutable(PyDictObject *mp, PyObject *key);
5364

5465
/* Consumes references to key and value */
5566
extern int _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value);

Include/internal/pycore_frame.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame);
198198

199199
/* Gets the PyFrameObject for this frame, lazily
200200
* creating it if necessary.
201-
* Returns a borrowed referennce */
201+
* Returns a borrowed reference */
202202
static inline PyFrameObject *
203203
_PyFrame_GetFrameObject(_PyInterpreterFrame *frame)
204204
{

Include/internal/pycore_global_objects_fini_generated.h

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_global_strings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@ struct _Py_global_strings {
4848
STRUCT_FOR_STR(json_decoder, "json.decoder")
4949
STRUCT_FOR_STR(kwdefaults, ".kwdefaults")
5050
STRUCT_FOR_STR(list_err, "list index out of range")
51+
STRUCT_FOR_STR(namedtuple, "namedtuple")
5152
STRUCT_FOR_STR(newline, "\n")
5253
STRUCT_FOR_STR(open_br, "{")
5354
STRUCT_FOR_STR(percent, "%")
5455
STRUCT_FOR_STR(shim_name, "<shim>")
56+
STRUCT_FOR_STR(startswith, "startswith")
5557
STRUCT_FOR_STR(type_params, ".type_params")
5658
STRUCT_FOR_STR(utf_8, "utf-8")
5759
} literals;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef Py_FREEZE_H
2+
#define Py_FREEZE_H
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
#ifndef Py_BUILD_CORE
9+
# error "this header requires Py_BUILD_CORE define"
10+
#endif
11+
12+
PyObject* _Py_Freeze(PyObject*);
13+
#define Py_Freeze(op) _Py_Freeze(_PyObject_CAST(op))
14+
15+
#ifdef __cplusplus
16+
}
17+
#endif
18+
#endif /* !Py_FREEZE_H */

Include/internal/pycore_object.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
7171
static inline void _Py_SetImmortal(PyObject *op)
7272
{
7373
if (op) {
74-
op->ob_refcnt = _Py_IMMORTAL_REFCNT;
74+
op->ob_refcnt = (op->ob_refcnt & _Py_IMMUTABLE_MASK) | _Py_IMMORTAL_REFCNT;
7575
}
7676
}
7777
#define _Py_SetImmortal(op) _Py_SetImmortal(_PyObject_CAST(op))
@@ -80,7 +80,8 @@ static inline void _Py_SetImmortal(PyObject *op)
8080
static inline void _Py_ClearImmortal(PyObject *op)
8181
{
8282
if (op) {
83-
assert(op->ob_refcnt == _Py_IMMORTAL_REFCNT);
83+
assert((op->ob_refcnt & _Py_REFCNT_MASK) == _Py_IMMORTAL_REFCNT);
84+
// note this also clears the _Py_IMMUTABLE_FLAG, if set
8485
op->ob_refcnt = 1;
8586
Py_DECREF(op);
8687
}
@@ -91,6 +92,17 @@ static inline void _Py_ClearImmortal(PyObject *op)
9192
op = NULL; \
9293
} while (0)
9394

95+
static inline void _Py_SetImmutable(PyObject *op)
96+
{
97+
if(op) {
98+
op->ob_refcnt |= _Py_IMMUTABLE_FLAG;
99+
}
100+
}
101+
#define _Py_SetImmutable(op) _Py_SetImmutable(_PyObject_CAST(op))
102+
103+
#define Py_CHECKWRITE(op) ((op) && (!_Py_IsImmutable(op) || _Py_IsFinalizing()))
104+
#define Py_REQUIREWRITE(op, msg) {if (Py_CHECKWRITE(op)) { _PyObject_ASSERT_FAILED_MSG(op, msg); }}
105+
94106
static inline void
95107
_Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct)
96108
{
@@ -101,7 +113,8 @@ _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct)
101113
#ifdef Py_REF_DEBUG
102114
_Py_DEC_REFTOTAL(_PyInterpreterState_GET());
103115
#endif
104-
if (--op->ob_refcnt != 0) {
116+
op->ob_refcnt -= 1;
117+
if ((op->ob_refcnt & _Py_REFCNT_MASK) != 0) {
105118
assert(op->ob_refcnt > 0);
106119
}
107120
else {

0 commit comments

Comments
 (0)