aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/reflect/makefunc_ffi.go
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2015-01-16 14:58:53 -0800
committerIan Lance Taylor <ian@gcc.gnu.org>2015-01-16 22:58:53 +0000
commit38bf819a5f995ae4621496df2324d68b9e24900f (patch)
treec90d2bfba44756e26640c50ad1389375693ef832 /libgo/go/reflect/makefunc_ffi.go
parent21cb351825d45c42e9e5148715a2fd2051cf4ed1 (diff)
downloadgcc-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.go67
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")
}