Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
7 changes: 7 additions & 0 deletions Lib/test/test_ast/test_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ def test_AST_objects(self):
# "ast.AST constructor takes 0 positional arguments"
ast.AST(2)

@unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi")
def test_nodes_have_inline_values(self):
tree = ast.parse("x = f(y, z=1)")
for node in ast.walk(tree):
with self.subTest(node=type(node).__name__):
self.assertTrue(_testinternalcapi.has_inline_values(node))

def test_AST_fields_NULL_check(self):
# See: https://github.com/python/cpython/issues/126105
old_value = ast.AST._fields
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -2042,7 +2042,7 @@ def test_pythontypes(self):
check = self.check_sizeof
# _ast.AST
import _ast
check(_ast.Module(), size('3P'))
check(_ast.Module(), size('2P'))
try:
raise TypeError
except TypeError as e:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Speed up :func:`ast.parse` and reduce the memory used by AST nodes by storing
node attributes as inline values instead of a separate per-node dictionary.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Speed up :func:`ast.parse` by ~15.8% and reduce the memory used by ~51.6% by
storing node attributes as inline values instead of in a per-node
dictionary.
18 changes: 5 additions & 13 deletions Parser/asdl_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,6 @@ def visitModule(self, mod):

typedef struct {
PyObject_HEAD
PyObject *dict;
} AST_object;

static void
Expand All @@ -923,7 +922,7 @@ def visitModule(self, mod):
/* bpo-31095: UnTrack is needed before calling any callbacks */
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
Py_CLEAR(self->dict);
PyObject_ClearManagedDict(op);
freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
assert(free_func != NULL);
free_func(self);
Expand All @@ -935,15 +934,13 @@ def visitModule(self, mod):
{
AST_object *self = (AST_object*)op;
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->dict);
return 0;
return PyObject_VisitManagedDict(op, visit, arg);
}

static int
ast_clear(PyObject *op)
{
AST_object *self = (AST_object*)op;
Py_CLEAR(self->dict);
PyObject_ClearManagedDict(op);
return 0;
}

Expand Down Expand Up @@ -1419,11 +1416,6 @@ def visitModule(self, mod):
return result;
}

static PyMemberDef ast_type_members[] = {
{"__dictoffset__", Py_T_PYSSIZET, offsetof(AST_object, dict), Py_READONLY},
{NULL} /* Sentinel */
};

static PyMethodDef ast_type_methods[] = {
{"__reduce__", ast_type_reduce, METH_NOARGS, NULL},
{"__replace__", _PyCFunction_CAST(ast_type_replace), METH_VARARGS | METH_KEYWORDS,
Expand Down Expand Up @@ -1668,7 +1660,6 @@ def visitModule(self, mod):
{Py_tp_setattro, PyObject_GenericSetAttr},
{Py_tp_traverse, ast_traverse},
{Py_tp_clear, ast_clear},
{Py_tp_members, ast_type_members},
{Py_tp_methods, ast_type_methods},
{Py_tp_getset, ast_type_getsets},
{Py_tp_init, ast_type_init},
Expand All @@ -1682,7 +1673,8 @@ def visitModule(self, mod):
"ast.AST",
sizeof(AST_object),
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_MANAGED_DICT,
AST_type_slots
};

Expand Down
18 changes: 5 additions & 13 deletions Python/Python-ast.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading