Commit 9cc77c6b authored by Stefan Behnel's avatar Stefan Behnel

Refactor the code for generating cached unbound method calls to avoid code duplication.

parent 5ba79e49
......@@ -507,15 +507,18 @@ class UtilityCode(UtilityCodeBase):
utility_code = set()
def externalise(matchobj):
type_cname, method_name, args = matchobj.groups()
args = [arg.strip() for arg in args[1:].split(',')]
assert 1 <= len(args) <= 3, "CALL_UNBOUND_METHOD() does not support %d call arguments" % len(args)
call = '__Pyx_CallUnboundCMethod%d' % (len(args) - 1,)
utility_code.add("CallUnboundCMethod%d" % (len(args) - 1,))
cname = output.get_cached_unbound_method(type_cname, method_name)
return '%s(&%s, %s)' % (call, cname, ', '.join(args))
impl = re.sub(r'CALL_UNBOUND_METHOD\(([a-zA-Z_]+),\s*"([^"]+)"((?:,\s*[^),]+)+)\)', externalise, impl)
type_cname, method_name, obj_cname, args = matchobj.groups()
args = [arg.strip() for arg in args[1:].split(',')] if args else []
assert len(args) < 3, "CALL_UNBOUND_METHOD() does not support %d call arguments" % len(args)
return output.cached_unbound_method_call_code(obj_cname, type_cname, method_name, args)
impl = re.sub(
r'CALL_UNBOUND_METHOD\('
r'([a-zA-Z_]+),' # type cname
r'\s*"([^"]+)",' # method name
r'\s*([^),]+)' # object cname
r'((?:,\s*[^),]+)*)' # args*
r'\)', externalise, impl)
assert 'CALL_UNBOUND_METHOD(' not in impl
for helper in sorted(utility_code):
......@@ -1319,6 +1322,18 @@ class GlobalState(object):
'umethod', '%s_%s' % (type_cname, method_name))
return cname
def cached_unbound_method_call_code(self, obj_cname, type_cname, method_name, arg_cnames):
# admittedly, not the best place to put this method, but it is reused by UtilityCode and ExprNodes ...
utility_code_name = "CallUnboundCMethod%d" % len(arg_cnames)
self.use_utility_code(UtilityCode.load_cached(utility_code_name, "ObjectHandling.c"))
cache_cname = self.get_cached_unbound_method(type_cname, method_name)
args = [obj_cname] + arg_cnames
return "__Pyx_%s(&%s, %s)" % (
utility_code_name,
cache_cname,
', '.join(args),
)
def add_cached_builtin_decl(self, entry):
if entry.is_builtin and entry.is_const:
if self.should_declare(entry.cname, entry):
......@@ -2364,6 +2379,7 @@ class CCodeWriter(object):
self.putln(" #define unlikely(x) __builtin_expect(!!(x), 0)")
self.putln("#endif")
class PyrexCodeWriter(object):
# f file output file
# level int indentation level
......
......@@ -6129,19 +6129,13 @@ class CachedBuiltinMethodCallNode(CallNode):
return ExprNode.may_be_none(self)
def generate_result_code(self, code):
arg_count = len(self.args)
obj_type = self.obj.type
call_func = '__Pyx_CallUnboundCMethod%d' % arg_count
utility_code_name = "CallUnboundCMethod%d" % arg_count
code.globalstate.use_utility_code(UtilityCode.load_cached(utility_code_name, "ObjectHandling.c"))
cache_cname = code.globalstate.get_cached_unbound_method(
obj_type.cname, self.method_name)
args = [self.obj] + self.args
code.putln("%s = %s(&%s, %s); %s" % (
self.result(),
call_func,
cache_cname,
', '.join(arg.py_result() for arg in args),
type_cname = self.obj.type.cname
obj_cname = self.obj.py_result()
args = [arg.py_result() for arg in self.args]
call_code = code.globalstate.cached_unbound_method_call_code(
obj_cname, type_cname, self.method_name, args)
code.putln("%s = %s; %s" % (
self.result(), call_code,
code.error_goto_if_null(self.result(), self.pos)
))
code.put_gotref(self.result())
......
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