This repository has been archived by the owner on Jan 30, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
c_tuple_type_memleak.patch
124 lines (110 loc) · 5.31 KB
/
c_tuple_type_memleak.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
commit bb4d9c2de71b7c7e1e02d9dfeae53f4547fa9d7d
Author: Stefan Behnel <stefan_ml@behnel.de>
Date: Fri Apr 24 17:57:23 2015 +0200
replace the incorrect and leaky global c-tuple type cache by a per-module one
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
index 0fed86a..cce5c50 100644
--- a/Cython/Compiler/ExprNodes.py
+++ b/Cython/Compiler/ExprNodes.py
@@ -6539,9 +6539,7 @@ class TupleNode(SequenceNode):
if any(type.is_pyobject or type.is_unspecified or type.is_fused for type in arg_types):
return tuple_type
else:
- type = PyrexTypes.c_tuple_type(arg_types)
- env.declare_tuple_type(self.pos, type)
- return type
+ return env.declare_tuple_type(self.pos, arg_types).type
def analyse_types(self, env, skip_children=False):
if len(self.args) == 0:
@@ -6552,8 +6550,7 @@ class TupleNode(SequenceNode):
if not skip_children:
self.args = [arg.analyse_types(env) for arg in self.args]
if not self.mult_factor and not any(arg.type.is_pyobject or arg.type.is_fused for arg in self.args):
- self.type = PyrexTypes.c_tuple_type(arg.type for arg in self.args)
- env.declare_tuple_type(self.pos, self.type)
+ self.type = env.declare_tuple_type(self.pos, (arg.type for arg in self.args)).type
self.is_temp = 1
return self
else:
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
index d6700d0..3ee9e9a 100644
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -1180,10 +1180,9 @@ class CTupleBaseTypeNode(CBaseTypeNode):
error(c.pos, "Tuple types can't (yet) contain Python objects.")
return error_type
component_types.append(type)
- type = PyrexTypes.c_tuple_type(component_types)
- entry = env.declare_tuple_type(self.pos, type)
+ entry = env.declare_tuple_type(self.pos, component_types)
entry.used = True
- return type
+ return entry.type
class FusedTypeNode(CBaseTypeNode):
diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py
index a4fc38d..bc61b6f 100644
--- a/Cython/Compiler/PyrexTypes.py
+++ b/Cython/Compiler/PyrexTypes.py
@@ -3684,13 +3684,11 @@ class CTupleType(CType):
env.use_utility_code(self._convert_from_py_code)
return True
-c_tuple_types = {}
+
def c_tuple_type(components):
components = tuple(components)
- tuple_type = c_tuple_types.get(components)
- if tuple_type is None:
- cname = Naming.ctuple_type_prefix + type_list_identifier(components)
- tuple_type = c_tuple_types[components] = CTupleType(cname, components)
+ cname = Naming.ctuple_type_prefix + type_list_identifier(components)
+ tuple_type = CTupleType(cname, components)
return tuple_type
diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py
index 7409420..c2f3ac8 100644
--- a/Cython/Compiler/Symtab.py
+++ b/Cython/Compiler/Symtab.py
@@ -610,8 +610,8 @@ class Scope(object):
self.sue_entries.append(entry)
return entry
- def declare_tuple_type(self, pos, type):
- return self.outer_scope.declare_tuple_type(pos, type)
+ def declare_tuple_type(self, pos, components):
+ return self.outer_scope.declare_tuple_type(pos, components)
def declare_var(self, name, type, pos,
cname = None, visibility = 'private',
@@ -1056,6 +1056,7 @@ class ModuleScope(Scope):
self.cached_builtins = []
self.undeclared_cached_builtins = []
self.namespace_cname = self.module_cname
+ self._cached_tuple_types = {}
for var_name in ['__builtins__', '__name__', '__file__', '__doc__', '__path__']:
self.declare_var(EncodedString(var_name), py_object_type, None)
@@ -1075,18 +1076,24 @@ class ModuleScope(Scope):
return self.outer_scope.lookup(name, language_level=language_level)
- def declare_tuple_type(self, pos, type):
- cname = type.cname
+ def declare_tuple_type(self, pos, components):
+ components = tuple(components)
+ try:
+ ttype = self._cached_tuple_types[components]
+ except KeyError:
+ ttype = self._cached_tuple_types[components] = PyrexTypes.c_tuple_type(components)
+ cname = ttype.cname
entry = self.lookup_here(cname)
if not entry:
scope = StructOrUnionScope(cname)
- for ix, component in enumerate(type.components):
+ for ix, component in enumerate(components):
scope.declare_var(name="f%s" % ix, type=component, pos=pos)
- struct_entry = self.declare_struct_or_union(cname + '_struct', 'struct', scope, typedef_flag=True, pos=pos, cname=cname)
+ struct_entry = self.declare_struct_or_union(
+ cname + '_struct', 'struct', scope, typedef_flag=True, pos=pos, cname=cname)
self.type_entries.remove(struct_entry)
- type.struct_entry = struct_entry
- entry = self.declare_type(cname, type, pos, cname)
- type.entry = entry
+ ttype.struct_entry = struct_entry
+ entry = self.declare_type(cname, ttype, pos, cname)
+ ttype.entry = entry
return entry
def declare_builtin(self, name, pos):