Skip to content

Commit c581cc3

Browse files
committed
Optimize memory usage for common cases
1 parent ec8dec2 commit c581cc3

2 files changed

Lines changed: 14 additions & 3 deletions

File tree

Lib/test/test_types.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1506,7 +1506,14 @@ def __eq__(self, other):
15061506
other[key] = 1
15071507
return other
15081508

1509-
# exposes the internals of `MappingProxyType` via richcompare:
1509+
# Checks that it does not mutate the internals of `MappingProxyType`:
1510+
dc = {}
1511+
leaked = self.mappingproxy(dc) == Evil()
1512+
self.assertIs(type(leaked), dict)
1513+
self.assertIn(key, leaked)
1514+
self.assertNotIn(key, dc)
1515+
1516+
# Exposes the internals of `MappingProxyType` via richcompare:
15101517
leaked = vars(list) == Evil()
15111518
self.assertIs(type(leaked), dict)
15121519
self.assertIn(key, leaked)

Objects/descrobject.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,9 +1235,13 @@ mappingproxy_richcompare(PyObject *self, PyObject *w, int op)
12351235
if (op == Py_EQ || op == Py_NE) {
12361236
mappingproxyobject *v = (mappingproxyobject *)self;
12371237
// We have to guard the mutable `dict` instances, because it can
1238-
// otherwise mutate the type's `__dict__` entries and cause crashes:
1238+
// otherwise mutate the type's `__dict__` entries and cause crashes.
1239+
// But, do not create copies on known types for memory optimization.
12391240
// See gh-152405 on the details.
1240-
if (PyDict_CheckExact(v->mapping)) {
1241+
if (
1242+
PyDict_CheckExact(v->mapping) &&
1243+
!(PyAnyDict_CheckExact(w) || PyODict_CheckExact(w))
1244+
) {
12411245
// So, instead we send a copy:
12421246
PyObject *copy = PyDict_Copy(v->mapping);
12431247
if (copy == NULL) {

0 commit comments

Comments
 (0)