[pypy-commit] pypy libgccjit-backend: Split out guard failure into a tail call to another function
dmalcolm
noreply at buildbot.pypy.org
Thu Dec 18 19:01:28 CET 2014
Author: David Malcolm <dmalcolm at redhat.com>
Branch: libgccjit-backend
Changeset: r75018:eb3ba1b9910e
Date: 2014-12-17 15:43 -0500
http://bitbucket.org/pypy/pypy/changeset/eb3ba1b9910e/
Log: Split out guard failure into a tail call to another function
Eventually this could be a jump through a function pointer.
Right now it's simply a call to a internal function. The call gets
inlined away, back into the code we had before.
diff --git a/rpython/jit/backend/libgccjit/assembler.py b/rpython/jit/backend/libgccjit/assembler.py
--- a/rpython/jit/backend/libgccjit/assembler.py
+++ b/rpython/jit/backend/libgccjit/assembler.py
@@ -10,6 +10,17 @@
from rpython.rtyper.lltypesystem.rffi import *
from rpython.rtyper.lltypesystem import lltype, rffi, rstr, llmemory
+class Params:
+ def __init__(self, assembler):
+ self.paramlist = []
+ self.param_frame = assembler.ctxt.new_param(assembler.t_jit_frame_ptr,
+ "jitframe")
+ self.paramlist.append(self.param_frame)
+
+ self.param_addr = assembler.ctxt.new_param(assembler.t_void_ptr,
+ "addr")
+ self.paramlist.append(self.param_addr)
+
class AssemblerLibgccjit(BaseAssembler):
_regalloc = None
#_output_loop_log = None
@@ -34,6 +45,7 @@
#self.teardown()
self.num_anon_loops = 0
+ self.num_guard_failure_fns = 0
self.sizeof_signed = rffi.sizeof(lltype.Signed)
@@ -98,6 +110,7 @@
self.t_float = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_DOUBLE) # FIXME
self.t_bool = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_BOOL)
self.t_void_ptr = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_VOID_PTR)
+ self.t_void = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_VOID)
self.u_signed = self.ctxt.new_field(self.t_Signed, "u_signed")
self.u_float = self.ctxt.new_field(self.t_float, "u_float")
@@ -134,7 +147,7 @@
struct_jit_frame = self.ctxt.new_opaque_struct ("JITFRAME")
- t_jit_frame_ptr = struct_jit_frame.as_type().get_pointer()
+ self.t_jit_frame_ptr = struct_jit_frame.as_type().get_pointer()
fields = []
# FIXME: Does the GCStruct implicitly add any fields?
@@ -149,7 +162,7 @@
make_field('jf_extra_stack_depth', self.t_Signed)
make_field('jf_savedata', self.t_void_ptr)
make_field('jf_guard_exc', self.t_void_ptr)
- make_field('jf_forward', t_jit_frame_ptr)
+ make_field('jf_forward', self.t_jit_frame_ptr)
# FIXME: for some reason there's an implicit word here;
# create it
make_field('jf_frame', self.t_Signed)
@@ -176,22 +189,16 @@
# Make function:
#print(' inputargs: %r' % (inputargs, ))
#jitframe.JITFRAMEINFOPTR
- params = []
-
- self.param_frame = self.ctxt.new_param(t_jit_frame_ptr, "jitframe")
- params.append(self.param_frame)
-
- self.param_addr = self.ctxt.new_param(self.t_void_ptr, "addr")
- params.append(self.param_addr)
+ self.loop_params = Params(self)
if not loopname:
loopname = 'anonloop_%i' % self.num_anon_loops
self.num_anon_loops += 1
print(" loopname: %r" % loopname)
self.fn = self.ctxt.new_function(self.lib.GCC_JIT_FUNCTION_EXPORTED,
- t_jit_frame_ptr,
+ self.t_jit_frame_ptr,
loopname,
- params,
+ self.loop_params.paramlist,
r_int(0))
self.b_current = self.fn.new_block("initial")
@@ -300,7 +307,7 @@
return self.lvalue_for_box[box]
def get_arg_as_lvalue(self, idx):
- return self.param_frame.as_rvalue ().dereference_field (
+ return self.loop_params.param_frame.as_rvalue ().dereference_field (
self.field_for_arg_idx[idx])
def expr_to_lvalue(self, expr):
@@ -371,9 +378,9 @@
self.b_current.end_with_jump(self.block_for_label_descr[jumpop.getdescr()])
def emit_finish(self, resop):
- self._impl_write_output_args(resop._args)
- self._impl_write_jf_descr(resop)
- self.b_current.end_with_return(self.param_frame.as_rvalue ())
+ self._impl_write_output_args(self.loop_params, resop._args)
+ self._impl_write_jf_descr(self.loop_params, resop)
+ self.b_current.end_with_return(self.loop_params.param_frame.as_rvalue ())
def emit_label(self, resop):
print(resop)
@@ -408,15 +415,34 @@
# Write out guard failure impl:
self.b_current = b_guard_failure
- self._impl_write_output_args(resop._fail_args)
- self._impl_write_jf_descr(resop)
- self.b_current.end_with_return(self.param_frame.as_rvalue ())
+
+ # Implement it as a tail-call to a handler function
+ # This will eventually become a function ptr, allowing
+ # patchability
+ failure_params = Params(self)
+ failure_fn = (
+ self.ctxt.new_function(self.lib.GCC_JIT_FUNCTION_INTERNAL,
+ self.t_jit_frame_ptr,
+ "on_guard_failure_%i" % self.num_guard_failure_fns,
+ failure_params.paramlist,
+ r_int(0)))
+ self.num_guard_failure_fns += 1
+ call = self.ctxt.new_call (failure_fn,
+ [param.as_rvalue()
+ for param in self.loop_params.paramlist])
+ self._impl_write_output_args(self.loop_params, resop._fail_args)
+ self.b_current.end_with_return(call)
+
+ b_within_failure_fn = failure_fn.new_block("initial")
+ self.b_current = b_within_failure_fn
+ self._impl_write_jf_descr(failure_params, resop)
+ self.b_current.end_with_return(failure_params.param_frame.as_rvalue ())
rd_locs = []
for idx, arg in enumerate(resop._fail_args):
rd_locs.append(idx * self.sizeof_signed)
resop.getdescr().rd_locs = rd_locs
- # Further operations go into the guard success block:
+ # Further operations go into the guard success block in the original fn:
self.b_current = b_guard_success
def emit_guard_true(self, resop):
@@ -425,7 +451,7 @@
def emit_guard_false(self, resop):
self._impl_guard(resop, r_int(0))
- def _impl_write_output_args(self, args):
+ def _impl_write_output_args(self, params, args):
# Write outputs back:
for idx, arg in enumerate(args):
if arg is not None:
@@ -443,14 +469,14 @@
r_int(0)))
"""
- def _impl_write_jf_descr(self, resop):
+ def _impl_write_jf_descr(self, params, resop):
# Write back to the jf_descr:
# "jitframe->jf_descr = resop.getdescr();"
descr = rffi.cast(lltype.Signed,
cast_instance_to_gcref(resop.getdescr()))
self.b_current.add_assignment(
- self.param_frame.as_rvalue ().dereference_field (
+ params.param_frame.as_rvalue ().dereference_field (
self.field_jf_descr),
self.ctxt.new_rvalue_from_ptr (self.t_void_ptr,
rffi.cast(VOIDP, descr)))
@@ -603,4 +629,3 @@
self.impl_float_cmp(resop, self.lib.GCC_JIT_COMPARISON_GT)
def emit_float_ge(self, resop):
self.impl_float_cmp(resop, self.lib.GCC_JIT_COMPARISON_GE)
-
diff --git a/rpython/jit/backend/libgccjit/rffi_bindings.py b/rpython/jit/backend/libgccjit/rffi_bindings.py
--- a/rpython/jit/backend/libgccjit/rffi_bindings.py
+++ b/rpython/jit/backend/libgccjit/rffi_bindings.py
@@ -87,6 +87,8 @@
hints={'nolength': True}))
self.PARAM_P_P = lltype.Ptr(lltype.Array(self.GCC_JIT_PARAM_P,
hints={'nolength': True}))
+ self.RVALUE_P_P = lltype.Ptr(lltype.Array(self.GCC_JIT_RVALUE_P,
+ hints={'nolength': True}))
# Entrypoints:
for returntype, name, paramtypes in [
@@ -253,6 +255,13 @@
self.GCC_JIT_RVALUE_P]),
(self.GCC_JIT_RVALUE_P,
+ 'gcc_jit_context_new_call', [self.GCC_JIT_CONTEXT_P,
+ self.GCC_JIT_LOCATION_P,
+ self.GCC_JIT_FUNCTION_P,
+ INT,
+ self.RVALUE_P_P]),
+
+ (self.GCC_JIT_RVALUE_P,
'gcc_jit_context_new_cast', [self.GCC_JIT_CONTEXT_P,
self.GCC_JIT_LOCATION_P,
self.GCC_JIT_RVALUE_P,
@@ -540,6 +549,20 @@
op,
a.inner_rvalue, b.inner_rvalue))
+ def new_call(self, fn, args):
+ raw_arg_array = lltype.malloc(self.lib.RVALUE_P_P.TO,
+ len(args),
+ flavor='raw') # of maybe gc?
+ for i in range(len(args)):
+ raw_arg_array[i] = args[i].inner_rvalue
+ rvalue = self.lib.gcc_jit_context_new_call(self.inner_ctxt,
+ self.lib.null_location_ptr,
+ fn.inner_function,
+ r_int(len(args)),
+ raw_arg_array)
+ lltype.free(raw_arg_array, flavor='raw')
+ return RValue(self.lib, rvalue)
+
def new_param(self, type_, name):
name_charp = str2charp(name)
param = self.lib.gcc_jit_context_new_param(self.inner_ctxt,
More information about the pypy-commit
mailing list