diff options
author | Richard Henderson <rth@redhat.com> | 2015-01-16 14:58:53 -0800 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2015-01-16 22:58:53 +0000 |
commit | 38bf819a5f995ae4621496df2324d68b9e24900f (patch) | |
tree | c90d2bfba44756e26640c50ad1389375693ef832 /libgo/go/reflect/makefunc_ffi.go | |
parent | 21cb351825d45c42e9e5148715a2fd2051cf4ed1 (diff) | |
download | gcc-38bf819a5f995ae4621496df2324d68b9e24900f.zip gcc-38bf819a5f995ae4621496df2324d68b9e24900f.tar.gz gcc-38bf819a5f995ae4621496df2324d68b9e24900f.tar.bz2 |
compiler, reflect, runtime: Use static chain for closures.
Change from using __go_set_closure to passing the closure
value in the static chain field. Uses new backend support for
setting the closure chain in a call from C via
__builtin_call_with_static_chain. Uses new support in libffi
for Go closures.
The old architecture specific support for reflect.MakeFunc is
removed, replaced by the libffi support.
All work done by Richard Henderson.
* go-gcc.cc (Gcc_backend::call_expression): Add chain_expr argument.
(Gcc_backend::static_chain_variable): New method.
From-SVN: r219776
Diffstat (limited to 'libgo/go/reflect/makefunc_ffi.go')
-rw-r--r-- | libgo/go/reflect/makefunc_ffi.go | 67 |
1 files changed, 21 insertions, 46 deletions
diff --git a/libgo/go/reflect/makefunc_ffi.go b/libgo/go/reflect/makefunc_ffi.go index 40c1ea8..6b61f23 100644 --- a/libgo/go/reflect/makefunc_ffi.go +++ b/libgo/go/reflect/makefunc_ffi.go @@ -5,52 +5,27 @@ package reflect import ( - "runtime" "unsafe" ) -// The ffi function, written in C, allocates an FFI closure. It -// returns the code and data pointers. When the code pointer is -// called, it will call callback. CIF is an FFI data structure -// allocated as part of the closure, and is returned to ensure that -// the GC retains it. -func ffi(ftyp *funcType, callback func(unsafe.Pointer, unsafe.Pointer)) (code uintptr, data uintptr, cif unsafe.Pointer) - -// The ffiFree function, written in C, releases the FFI closure. -func ffiFree(uintptr) - -// An ffiData holds the information needed to preserve an FFI closure -// for the garbage collector. -type ffiData struct { - code uintptr - data uintptr - cif unsafe.Pointer - callback func(unsafe.Pointer, unsafe.Pointer) -} - -// The makeFuncFFI function uses libffi closures to implement -// reflect.MakeFunc. This is used for processors for which we don't -// have more efficient support. -func makeFuncFFI(ftyp *funcType, fn func(args []Value) (results []Value)) (uintptr, *ffiData) { - callback := func(params, results unsafe.Pointer) { - ffiCall(ftyp, fn, params, results) - } - - code, data, cif := ffi(ftyp, callback) - - c := &ffiData{code: code, data: data, cif: cif, callback: callback} - - runtime.SetFinalizer(c, - func(p *ffiData) { - ffiFree(p.data) - }) - - return code, c -} - -// ffiCall takes pointers to the parameters, calls the function, and -// stores the results back into memory. -func ffiCall(ftyp *funcType, fn func([]Value) []Value, params unsafe.Pointer, results unsafe.Pointer) { +// The makeFuncFFI function, written in C, fills in an FFI closure. +// It arranges for ffiCall to be invoked directly from FFI. +func makeFuncFFI(ftyp *funcType, impl *makeFuncImpl) + +// FFICallbackGo implements the Go side of the libffi callback. +// It is exported so that C code can call it. +// +// The call chain arriving here looks like +// some_go_caller +// ->some_ffi_internals +// ->ffi_callback (in C) +// ->FFICallbackGo +// +// The ffi_callback handles __go_makefunc_can_recover, and +// then passes off the data as received from ffi here. + +func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFuncImpl) { + ftyp := impl.typ in := make([]Value, 0, len(ftyp.in)) ap := params for _, rt := range ftyp.in { @@ -61,18 +36,18 @@ func ffiCall(ftyp *funcType, fn func([]Value) []Value, params unsafe.Pointer, re ap = (unsafe.Pointer)(uintptr(ap) + ptrSize) } - out := fn(in) + out := impl.call(in) off := uintptr(0) for i, typ := range ftyp.out { v := out[i] if v.typ != typ { - panic("reflect: function created by MakeFunc using " + funcName(fn) + + panic("reflect: function created by MakeFunc using " + funcName(impl.fn) + " returned wrong type: have " + out[i].typ.String() + " for " + typ.String()) } if v.flag&flagRO != 0 { - panic("reflect: function created by MakeFunc using " + funcName(fn) + + panic("reflect: function created by MakeFunc using " + funcName(impl.fn) + " returned value obtained from unexported field") } |