Commit 6ccbc0d0 authored by Stefan Behnel's avatar Stefan Behnel

cache constant tuples (including constant call arg tuples)

parent 1c288d08
......@@ -421,6 +421,7 @@ class GlobalState(object):
'all_the_rest',
'pystring_table',
'cached_builtins',
'cached_constants',
'init_globals',
'init_module',
'cleanup_globals',
......@@ -462,7 +463,12 @@ class GlobalState(object):
w.enter_cfunc_scope()
w.putln("static int __Pyx_InitCachedBuiltins(void) {")
w = self.parts['cached_constants']
w.enter_cfunc_scope()
w.putln("")
w.putln("static int __Pyx_InitCachedConstants(void) {")
w.put_setup_refcount_context("__Pyx_InitCachedConstants")
w = self.parts['init_globals']
w.enter_cfunc_scope()
w.putln("")
......@@ -509,15 +515,27 @@ class GlobalState(object):
if Options.cache_builtins:
w = self.parts['cached_builtins']
w.putln("return 0;")
w.put_label(w.error_label)
w.putln("return -1;")
if w.label_used(w.error_label):
w.put_label(w.error_label)
w.putln("return -1;")
w.putln("}")
w.exit_cfunc_scope()
w = self.parts['cached_constants']
w.put_finish_refcount_context()
w.putln("return 0;")
if w.label_used(w.error_label):
w.put_label(w.error_label)
w.put_finish_refcount_context()
w.putln("return -1;")
w.putln("}")
w.exit_cfunc_scope()
w = self.parts['init_globals']
w.putln("return 0;")
w.put_label(w.error_label)
w.putln("return -1;")
if w.label_used(w.error_label):
w.put_label(w.error_label)
w.putln("return -1;")
w.putln("}")
w.exit_cfunc_scope()
......@@ -536,6 +554,12 @@ class GlobalState(object):
# constant handling at code generation time
def get_cached_constants_writer(self):
return self.parts['cached_constants']
def get_globals_cleanup_writer(self):
return self.parts['cleanup_globals']
def get_int_const(self, str_value, longness=False):
longness = bool(longness)
try:
......@@ -544,9 +568,9 @@ class GlobalState(object):
c = self.new_int_const(str_value, longness)
return c
def get_py_const(self, type):
def get_py_const(self, type, prefix=''):
# create a new Python object constant
return self.new_py_const(type)
return self.new_py_const(type, prefix)
def get_string_const(self, text):
# return a C string constant, creating a new one if necessary
......@@ -581,8 +605,8 @@ class GlobalState(object):
self.int_const_index[(value, longness)] = c
return c
def new_py_const(self, type):
cname = self.new_const_cname()
def new_py_const(self, type, prefix=''):
cname = self.new_const_cname(prefix)
c = PyObjectConst(cname, type)
self.py_constants.append(c)
return c
......@@ -938,6 +962,9 @@ class CCodeWriter(object):
def get_py_num(self, str_value, longness):
return self.globalstate.get_int_const(str_value, longness).cname
def get_py_const(self, type, prefix=''):
return self.globalstate.get_py_const(type, prefix).cname
def get_string_const(self, text):
return self.globalstate.get_string_const(text).cname
......@@ -953,6 +980,12 @@ class CCodeWriter(object):
def intern_identifier(self, text):
return self.get_py_string_const(text, identifier=True)
def get_cached_constants_writer(self):
return self.globalstate.get_cached_constants_writer()
def get_globals_cleanup_writer(self):
return self.globalstate.get_globals_cleanup_writer()
# code generation
def putln(self, code = "", safe=False):
......
......@@ -3932,10 +3932,16 @@ class TupleNode(SequenceNode):
self.is_literal = 1
else:
SequenceNode.analyse_types(self, env, skip_children)
for child in self.args:
if not child.is_literal:
break
else:
self.is_temp = 0
self.is_literal = 1
def calculate_result_code(self):
if len(self.args) > 0:
error(self.pos, "Positive length tuples must be constructed.")
return self.result_code
else:
return Naming.empty_tuple
......@@ -3954,6 +3960,16 @@ class TupleNode(SequenceNode):
if len(self.args) == 0:
# result_code is Naming.empty_tuple
return
if self.is_literal:
# non-empty cached tuple => result is global constant,
# creation code goes into separate code writer
self.result_code = code.get_py_const(py_object_type, 'tuple_')
if Options.generate_cleanup_code >= 2:
cleanup_writer = code.get_globals_cleanup_writer()
cleanup_writer.put_xdecref_clear(self.result(), py_object_type, nanny=False)
code = code.get_cached_constants_writer()
code.mark_pos(self.pos)
code.putln(
"%s = PyTuple_New(%s); %s" % (
self.result(),
......@@ -3970,6 +3986,8 @@ class TupleNode(SequenceNode):
i,
arg.py_result()))
code.put_giveref(arg.py_result())
if self.is_literal:
code.put_giveref(self.py_result())
def generate_subexpr_disposal_code(self, code):
# We call generate_post_assignment_code here instead
......
......@@ -1746,8 +1746,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if Options.cache_builtins:
code.putln("/*--- Builtin init code ---*/")
code.putln(code.error_goto_if_neg("__Pyx_InitCachedBuiltins()",
self.pos))
code.putln(code.error_goto_if_neg("__Pyx_InitCachedBuiltins()", self.pos))
code.putln("/*--- Constants init code ---*/")
code.putln(code.error_goto_if_neg("__Pyx_InitCachedConstants()", self.pos))
code.putln("/*--- Global init code ---*/")
self.generate_global_init_code(env, code)
......
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