Commit cfa02c27 authored by Stefan Behnel's avatar Stefan Behnel

Prevent repeated initialisation of constants that overwrite the previously...

Prevent repeated initialisation of constants that overwrite the previously created objects without cleanup.
Closes #2750.
parent 498c05f1
...@@ -1139,6 +1139,7 @@ class GlobalState(object): ...@@ -1139,6 +1139,7 @@ class GlobalState(object):
self.num_const_index = {} self.num_const_index = {}
self.py_constants = [] self.py_constants = []
self.cached_cmethods = {} self.cached_cmethods = {}
self.initialised_constants = set()
writer.set_global_state(self) writer.set_global_state(self)
self.rootwriter = writer self.rootwriter = writer
...@@ -1248,7 +1249,12 @@ class GlobalState(object): ...@@ -1248,7 +1249,12 @@ class GlobalState(object):
# constant handling at code generation time # constant handling at code generation time
def get_cached_constants_writer(self): def get_cached_constants_writer(self, target=None):
if target is not None:
if target in self.initialised_constants:
# Return None on second/later calls to prevent duplicate creation code.
return None
self.initialised_constants.add(target)
return self.parts['cached_constants'] return self.parts['cached_constants']
def get_int_const(self, str_value, longness=False): def get_int_const(self, str_value, longness=False):
...@@ -1822,8 +1828,8 @@ class CCodeWriter(object): ...@@ -1822,8 +1828,8 @@ class CCodeWriter(object):
def intern_identifier(self, text): def intern_identifier(self, text):
return self.get_py_string_const(text, identifier=True) return self.get_py_string_const(text, identifier=True)
def get_cached_constants_writer(self): def get_cached_constants_writer(self, target=None):
return self.globalstate.get_cached_constants_writer() return self.globalstate.get_cached_constants_writer(target)
# code generation # code generation
......
...@@ -1621,15 +1621,17 @@ class UnicodeNode(ConstNode): ...@@ -1621,15 +1621,17 @@ class UnicodeNode(ConstNode):
# decoded by the UTF-8 codec in Py3.3 # decoded by the UTF-8 codec in Py3.3
self.result_code = code.get_py_const(py_object_type, 'ustring') self.result_code = code.get_py_const(py_object_type, 'ustring')
data_cname = code.get_pyunicode_ptr_const(self.value) data_cname = code.get_pyunicode_ptr_const(self.value)
code = code.get_cached_constants_writer() const_code = code.get_cached_constants_writer(self.result_code)
code.mark_pos(self.pos) if const_code is None:
code.putln( return # already initialised
const_code.mark_pos(self.pos)
const_code.putln(
"%s = PyUnicode_FromUnicode(%s, (sizeof(%s) / sizeof(Py_UNICODE))-1); %s" % ( "%s = PyUnicode_FromUnicode(%s, (sizeof(%s) / sizeof(Py_UNICODE))-1); %s" % (
self.result_code, self.result_code,
data_cname, data_cname,
data_cname, data_cname,
code.error_goto_if_null(self.result_code, self.pos))) code.error_goto_if_null(self.result_code, self.pos)))
code.put_error_if_neg( const_code.put_error_if_neg(
self.pos, "__Pyx_PyUnicode_READY(%s)" % self.result_code) self.pos, "__Pyx_PyUnicode_READY(%s)" % self.result_code)
else: else:
self.result_code = code.get_py_string_const(self.value) self.result_code = code.get_py_string_const(self.value)
...@@ -5253,7 +5255,9 @@ class SliceNode(ExprNode): ...@@ -5253,7 +5255,9 @@ class SliceNode(ExprNode):
if self.is_literal: if self.is_literal:
dedup_key = make_dedup_key(self.type, (self,)) dedup_key = make_dedup_key(self.type, (self,))
self.result_code = code.get_py_const(py_object_type, 'slice', cleanup_level=2, dedup_key=dedup_key) self.result_code = code.get_py_const(py_object_type, 'slice', cleanup_level=2, dedup_key=dedup_key)
code = code.get_cached_constants_writer() code = code.get_cached_constants_writer(self.result_code)
if code is None:
return # already initialised
code.mark_pos(self.pos) code.mark_pos(self.pos)
code.putln( code.putln(
...@@ -7985,11 +7989,11 @@ class TupleNode(SequenceNode): ...@@ -7985,11 +7989,11 @@ class TupleNode(SequenceNode):
return return
if self.is_literal or self.is_partly_literal: if self.is_literal or self.is_partly_literal:
dedup_key = None dedup_key = make_dedup_key(self.type, self.args) if self.is_literal else None
if self.is_literal:
dedup_key = make_dedup_key(self.type, self.args)
tuple_target = code.get_py_const(py_object_type, 'tuple', cleanup_level=2, dedup_key=dedup_key) tuple_target = code.get_py_const(py_object_type, 'tuple', cleanup_level=2, dedup_key=dedup_key)
const_code = code.get_cached_constants_writer() const_code = code.get_cached_constants_writer(tuple_target)
if const_code is not None:
# constant is not yet initialised
const_code.mark_pos(self.pos) const_code.mark_pos(self.pos)
self.generate_sequence_packing_code(const_code, tuple_target, plain=not self.is_literal) self.generate_sequence_packing_code(const_code, tuple_target, plain=not self.is_literal)
const_code.put_giveref(tuple_target) const_code.put_giveref(tuple_target)
...@@ -9508,7 +9512,9 @@ class CodeObjectNode(ExprNode): ...@@ -9508,7 +9512,9 @@ class CodeObjectNode(ExprNode):
if self.result_code is None: if self.result_code is None:
self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2) self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2)
code = code.get_cached_constants_writer() code = code.get_cached_constants_writer(self.result_code)
if code is None:
return # already initialised
code.mark_pos(self.pos) code.mark_pos(self.pos)
func = self.def_node func = self.def_node
func_name = code.get_py_string_const( func_name = code.get_py_string_const(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment