Commit 5f7ad124 authored by Stefan Behnel's avatar Stefan Behnel

cache Python float constants

--HG--
extra : amend_source : a382ac055ce79771e0457bed2e3b8d253581a54f
parent 92685f5b
...@@ -703,17 +703,21 @@ class FunctionState(object): ...@@ -703,17 +703,21 @@ class FunctionState(object):
self.closure_temps = ClosureTempAllocator(scope) self.closure_temps = ClosureTempAllocator(scope)
class IntConst(object): class NumConst(object):
"""Global info about a Python integer constant held by GlobalState. """Global info about a Python number constant held by GlobalState.
cname string
value string
py_type string int, long, float
value_code string evaluation code if different from value
""" """
# cname string
# value int
# is_long boolean
def __init__(self, cname, value, is_long): def __init__(self, cname, value, py_type, value_code=None):
self.cname = cname self.cname = cname
self.value = value self.value = value
self.is_long = is_long self.py_type = py_type
self.value_code = value_code or value
class PyObjectConst(object): class PyObjectConst(object):
"""Global info about a generic constant held by GlobalState. """Global info about a generic constant held by GlobalState.
...@@ -725,6 +729,7 @@ class PyObjectConst(object): ...@@ -725,6 +729,7 @@ class PyObjectConst(object):
self.cname = cname self.cname = cname
self.type = type self.type = type
cython.declare(possible_unicode_identifier=object, possible_bytes_identifier=object, cython.declare(possible_unicode_identifier=object, possible_bytes_identifier=object,
replace_identifier=object, find_alphanums=object) replace_identifier=object, find_alphanums=object)
possible_unicode_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match possible_unicode_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
...@@ -908,7 +913,7 @@ class GlobalState(object): ...@@ -908,7 +913,7 @@ class GlobalState(object):
self.const_cnames_used = {} self.const_cnames_used = {}
self.string_const_index = {} self.string_const_index = {}
self.pyunicode_ptr_const_index = {} self.pyunicode_ptr_const_index = {}
self.int_const_index = {} self.num_const_index = {}
self.py_constants = [] self.py_constants = []
assert writer.globalstate is None assert writer.globalstate is None
...@@ -1022,11 +1027,18 @@ class GlobalState(object): ...@@ -1022,11 +1027,18 @@ class GlobalState(object):
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):
longness = bool(longness) py_type = longness and 'long' or 'int'
try: try:
c = self.int_const_index[(str_value, longness)] c = self.num_const_index[(str_value, py_type)]
except KeyError: except KeyError:
c = self.new_int_const(str_value, longness) c = self.new_num_const(str_value, py_type)
return c
def get_float_const(self, str_value, value_code):
try:
c = self.num_const_index[(str_value, 'float')]
except KeyError:
c = self.new_num_const(str_value, 'float', value_code)
return c return c
def get_py_const(self, type, prefix='', cleanup_level=None): def get_py_const(self, type, prefix='', cleanup_level=None):
...@@ -1083,10 +1095,10 @@ class GlobalState(object): ...@@ -1083,10 +1095,10 @@ class GlobalState(object):
self.string_const_index[byte_string] = c self.string_const_index[byte_string] = c
return c return c
def new_int_const(self, value, longness): def new_num_const(self, value, py_type, value_code=None):
cname = self.new_int_const_cname(value, longness) cname = self.new_num_const_cname(value, py_type)
c = IntConst(cname, value, longness) c = NumConst(cname, value, py_type, value_code)
self.int_const_index[(value, longness)] = c self.num_const_index[(value, py_type)] = c
return c return c
def new_py_const(self, type, prefix=''): def new_py_const(self, type, prefix=''):
...@@ -1100,11 +1112,14 @@ class GlobalState(object): ...@@ -1100,11 +1112,14 @@ class GlobalState(object):
value = bytes_value.decode('ASCII', 'ignore') value = bytes_value.decode('ASCII', 'ignore')
return self.new_const_cname(value=value) return self.new_const_cname(value=value)
def new_int_const_cname(self, value, longness): def new_num_const_cname(self, value, py_type):
if longness: prefix = Naming.interned_int_prefix
if py_type == 'long':
value += 'L' value += 'L'
cname = "%s%s" % (Naming.interned_num_prefix, value) elif py_type == 'float':
cname = cname.replace('-', 'neg_').replace('.','_') prefix = Naming.interned_float_prefix
cname = "%s%s" % (prefix, value)
cname = cname.replace('-', 'neg_').replace('.', '_')
return cname return cname
def new_const_cname(self, prefix='', value=''): def new_const_cname(self, prefix='', value=''):
...@@ -1149,7 +1164,7 @@ class GlobalState(object): ...@@ -1149,7 +1164,7 @@ class GlobalState(object):
def generate_const_declarations(self): def generate_const_declarations(self):
self.generate_string_constants() self.generate_string_constants()
self.generate_int_constants() self.generate_num_constants()
self.generate_object_constant_decls() self.generate_object_constant_decls()
def generate_object_constant_decls(self): def generate_object_constant_decls(self):
...@@ -1242,24 +1257,25 @@ class GlobalState(object): ...@@ -1242,24 +1257,25 @@ class GlobalState(object):
Naming.stringtab_cname, Naming.stringtab_cname,
init_globals.error_goto(self.module_pos))) init_globals.error_goto(self.module_pos)))
def generate_int_constants(self): def generate_num_constants(self):
consts = [ (len(c.value), c.value, c.is_long, c) consts = [(c.py_type, len(c.value), c.value, c.value_code, c)
for c in self.int_const_index.values() ] for c in self.num_const_index.values()]
consts.sort() consts.sort()
decls_writer = self.parts['decls'] decls_writer = self.parts['decls']
for _, value, longness, c in consts: init_globals = self.parts['init_globals']
for py_type, _, value, value_code, c in consts:
cname = c.cname cname = c.cname
decls_writer.putln("static PyObject *%s;" % cname) decls_writer.putln("static PyObject *%s;" % cname)
if longness: if py_type == 'float':
function = '%s = PyFloat_FromDouble(%s); %s;'
elif py_type == 'long':
function = '%s = PyLong_FromString((char *)"%s", 0, 0); %s;' function = '%s = PyLong_FromString((char *)"%s", 0, 0); %s;'
elif Utils.long_literal(value): elif Utils.long_literal(value):
function = '%s = PyInt_FromString((char *)"%s", 0, 0); %s;' function = '%s = PyInt_FromString((char *)"%s", 0, 0); %s;'
else: else:
function = "%s = PyInt_FromLong(%s); %s;" function = "%s = PyInt_FromLong(%s); %s;"
init_globals = self.parts['init_globals']
init_globals.putln(function % ( init_globals.putln(function % (
cname, cname, value_code,
value,
init_globals.error_goto_if_null(cname, self.module_pos))) init_globals.error_goto_if_null(cname, self.module_pos)))
# The functions below are there in a transition phase only # The functions below are there in a transition phase only
...@@ -1478,9 +1494,12 @@ class CCodeWriter(object): ...@@ -1478,9 +1494,12 @@ class CCodeWriter(object):
# constant handling # constant handling
def get_py_num(self, str_value, longness): def get_py_int(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_float(self, str_value, value_code):
return self.globalstate.get_float_const(str_value, value_code).cname
def get_py_const(self, type, prefix='', cleanup_level=None): def get_py_const(self, type, prefix='', cleanup_level=None):
return self.globalstate.get_py_const(type, prefix, cleanup_level).cname return self.globalstate.get_py_const(type, prefix, cleanup_level).cname
......
...@@ -1053,7 +1053,7 @@ class IntNode(ConstNode): ...@@ -1053,7 +1053,7 @@ class IntNode(ConstNode):
if self.type.is_pyobject: if self.type.is_pyobject:
# pre-allocate a Python version of the number # pre-allocate a Python version of the number
plain_integer_string = self.value_as_c_integer_string(plain_digits=True) plain_integer_string = self.value_as_c_integer_string(plain_digits=True)
self.result_code = code.get_py_num(plain_integer_string, self.longness) self.result_code = code.get_py_int(plain_integer_string, self.longness)
else: else:
self.result_code = self.get_constant_c_result_code() self.result_code = self.get_constant_c_result_code()
...@@ -1094,7 +1094,18 @@ class FloatNode(ConstNode): ...@@ -1094,7 +1094,18 @@ class FloatNode(ConstNode):
def compile_time_value(self, denv): def compile_time_value(self, denv):
return float(self.value) return float(self.value)
def coerce_to(self, dst_type, env):
if dst_type.is_pyobject and self.type.is_float:
return FloatNode(
self.pos, value=self.value,
constant_result=self.constant_result,
type=Builtin.float_type)
return ConstNode.coerce_to(self, dst_type, env)
def calculate_result_code(self): def calculate_result_code(self):
return self.result_code
def as_c_constant(self):
strval = self.value strval = self.value
assert isinstance(strval, (str, unicode)) assert isinstance(strval, (str, unicode))
cmpval = repr(float(strval)) cmpval = repr(float(strval))
...@@ -1107,6 +1118,13 @@ class FloatNode(ConstNode): ...@@ -1107,6 +1118,13 @@ class FloatNode(ConstNode):
else: else:
return strval return strval
def generate_evaluation_code(self, code):
if self.type.is_pyobject:
self.result_code = code.get_py_float(
self.value, self.as_c_constant())
else:
self.result_code = self.as_c_constant()
class BytesNode(ConstNode): class BytesNode(ConstNode):
# A char* or bytes literal # A char* or bytes literal
......
...@@ -30,7 +30,8 @@ pymethdef_prefix = pyrex_prefix + "mdef_" ...@@ -30,7 +30,8 @@ pymethdef_prefix = pyrex_prefix + "mdef_"
methtab_prefix = pyrex_prefix + "methods_" methtab_prefix = pyrex_prefix + "methods_"
memtab_prefix = pyrex_prefix + "members_" memtab_prefix = pyrex_prefix + "members_"
interned_str_prefix = pyrex_prefix + "n_" interned_str_prefix = pyrex_prefix + "n_"
interned_num_prefix = pyrex_prefix + "int_" interned_int_prefix = pyrex_prefix + "int_"
interned_float_prefix = pyrex_prefix + "float_"
objstruct_prefix = pyrex_prefix + "obj_" objstruct_prefix = pyrex_prefix + "obj_"
typeptr_prefix = pyrex_prefix + "ptype_" typeptr_prefix = pyrex_prefix + "ptype_"
prop_set_prefix = pyrex_prefix + "setprop_" prop_set_prefix = pyrex_prefix + "setprop_"
......
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