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