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