diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-01-16 22:58:53 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-01-16 22:58:53 +0000 |
commit | 1ecc61579adbbe6be91ba4847de3dd47615f2da9 (patch) | |
tree | c90d2bfba44756e26640c50ad1389375693ef832 /libgo/runtime | |
parent | 3bb12d97b7bf4bc70ce53e33a51085adf768f600 (diff) | |
download | gcc-1ecc61579adbbe6be91ba4847de3dd47615f2da9.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@219776 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/runtime')
-rw-r--r-- | libgo/runtime/go-ffi.c | 39 | ||||
-rw-r--r-- | libgo/runtime/go-reflect-call.c | 15 | ||||
-rw-r--r-- | libgo/runtime/malloc.goc | 8 | ||||
-rw-r--r-- | libgo/runtime/mgc0.c | 4 | ||||
-rw-r--r-- | libgo/runtime/proc.c | 20 | ||||
-rw-r--r-- | libgo/runtime/runtime.h | 4 | ||||
-rw-r--r-- | libgo/runtime/time.goc | 3 |
7 files changed, 31 insertions, 62 deletions
diff --git a/libgo/runtime/go-ffi.c b/libgo/runtime/go-ffi.c index 175c583bf45..89da23dab1b 100644 --- a/libgo/runtime/go-ffi.c +++ b/libgo/runtime/go-ffi.c @@ -30,8 +30,6 @@ static ffi_type *go_struct_to_ffi (const struct __go_struct_type *) __attribute__ ((no_split_stack)); static ffi_type *go_string_to_ffi (void) __attribute__ ((no_split_stack)); static ffi_type *go_interface_to_ffi (void) __attribute__ ((no_split_stack)); -static ffi_type *go_complex_to_ffi (ffi_type *) - __attribute__ ((no_split_stack, unused)); static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *) __attribute__ ((no_split_stack)); static ffi_type *go_func_return_ffi (const struct __go_func_type *) @@ -155,7 +153,15 @@ go_interface_to_ffi (void) return ret; } -/* Return an ffi_type for a Go complex type. */ + +#ifndef FFI_TARGET_HAS_COMPLEX_TYPE +/* If libffi hasn't been updated for this target to support complex, + pretend complex is a structure. Warning: This does not work for + all ABIs. Eventually libffi should be updated for all targets + and this should go away. */ + +static ffi_type *go_complex_to_ffi (ffi_type *) + __attribute__ ((no_split_stack)); static ffi_type * go_complex_to_ffi (ffi_type *float_type) @@ -170,6 +176,7 @@ go_complex_to_ffi (ffi_type *float_type) ret->elements[2] = NULL; return ret; } +#endif /* Return an ffi_type for a type described by a __go_type_descriptor. */ @@ -194,23 +201,25 @@ go_type_to_ffi (const struct __go_type_descriptor *descriptor) return &ffi_type_double; abort (); case GO_COMPLEX64: -#ifdef __alpha__ - runtime_throw("the libffi library does not support Complex64 type with " - "reflect.Call or runtime.SetFinalizer"); -#else if (sizeof (float) == 4) - return go_complex_to_ffi (&ffi_type_float); - abort (); + { +#ifdef FFI_TARGET_HAS_COMPLEX_TYPE + return &ffi_type_complex_float; +#else + return go_complex_to_ffi (&ffi_type_float); #endif + } + abort (); case GO_COMPLEX128: -#ifdef __alpha__ - runtime_throw("the libffi library does not support Complex128 type with " - "reflect.Call or runtime.SetFinalizer"); -#else if (sizeof (double) == 8) - return go_complex_to_ffi (&ffi_type_double); - abort (); + { +#ifdef FFI_TARGET_HAS_COMPLEX_TYPE + return &ffi_type_complex_double; +#else + return go_complex_to_ffi (&ffi_type_double); #endif + } + abort (); case GO_INT16: return &ffi_type_sint16; case GO_INT32: diff --git a/libgo/runtime/go-reflect-call.c b/libgo/runtime/go-reflect-call.c index dfc703eb2c8..29e814a793f 100644 --- a/libgo/runtime/go-reflect-call.c +++ b/libgo/runtime/go-reflect-call.c @@ -12,11 +12,10 @@ #include "go-alloc.h" #include "go-assert.h" #include "go-type.h" - -#ifdef USE_LIBFFI - #include "go-ffi.h" +#if defined(USE_LIBFFI) && FFI_GO_CLOSURES + /* The functions in this file are only called from reflect_call. As reflect_call calls a libffi function, which will be compiled without -fsplit-stack, it will always run with a large stack. */ @@ -202,11 +201,7 @@ go_set_results (const struct __go_func_type *func, unsigned char *call_result, If IS_METHOD is true this is a call to a method expression. The first argument is the receiver. It is described in FUNC_TYPE, but - regardless of FUNC_TYPE, it is passed as a pointer. - - If neither IS_INTERFACE nor IS_METHOD is true then we are calling a - function indirectly, and we must pass a closure pointer via - __go_set_closure. The pointer to pass is simply FUNC_VAL. */ + regardless of FUNC_TYPE, it is passed as a pointer. */ void reflect_call (const struct __go_func_type *func_type, FuncVal *func_val, @@ -221,9 +216,7 @@ reflect_call (const struct __go_func_type *func_type, FuncVal *func_val, call_result = (unsigned char *) malloc (go_results_size (func_type)); - if (!is_interface && !is_method) - __go_set_closure (func_val); - ffi_call (&cif, func_val->fn, call_result, params); + ffi_call_go (&cif, func_val->fn, call_result, params, func_val); /* Some day we may need to free result values if RESULTS is NULL. */ diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc index b05c5fa4e22..43323e25874 100644 --- a/libgo/runtime/malloc.goc +++ b/libgo/runtime/malloc.goc @@ -84,7 +84,6 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag) MLink *v, *next; byte *tiny; bool incallback; - void *closure; if(size == 0) { // All 0-length allocations use this pointer. @@ -96,10 +95,6 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag) m = runtime_m(); g = runtime_g(); - // We should not be called in between __go_set_closure and the - // actual function call, but cope with it if we are. - closure = g->closure; - incallback = false; if(m->mcache == nil && g->ncgo > 0) { // For gccgo this case can occur when a cgo or SWIG function @@ -180,7 +175,6 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag) m->locks--; if(incallback) runtime_entersyscall(); - g->closure = closure; return v; } } @@ -267,8 +261,6 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag) if(incallback) runtime_entersyscall(); - g->closure = closure; - return v; } diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c index 0867abfd168..662dd875762 100644 --- a/libgo/runtime/mgc0.c +++ b/libgo/runtime/mgc0.c @@ -133,8 +133,8 @@ clearpools(void) // clear sync.Pool's if(poolcleanup != nil) { - __go_set_closure(poolcleanup); - poolcleanup->fn(); + __builtin_call_with_static_chain(poolcleanup->fn(), + poolcleanup); } for(pp=runtime_allp; (p=*pp) != nil; pp++) { diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index 20fbc0a6182..c4f27fb6bbb 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -3310,26 +3310,6 @@ runtime_proc_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj enqueue1(wbufp, (Obj){(byte*)&runtime_sched, sizeof runtime_sched, 0}); } -// When a function calls a closure, it passes the closure value to -// __go_set_closure immediately before the function call. When a -// function uses a closure, it calls __go_get_closure immediately on -// function entry. This is a hack, but it will work on any system. -// It would be better to use the static chain register when there is -// one. It is also worth considering expanding these functions -// directly in the compiler. - -void -__go_set_closure(void* v) -{ - g->closure = v; -} - -void * -__go_get_closure(void) -{ - return g->closure; -} - // Return whether we are waiting for a GC. This gc toolchain uses // preemption instead. bool diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index 1f1358ae947..515ae58ff85 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -195,7 +195,6 @@ struct Location struct G { - void* closure; // Closure value. Defer* defer; Panic* panic; void* exception; // current exception being thrown @@ -833,9 +832,6 @@ int32 getproccount(void); #define PREFETCH(p) __builtin_prefetch(p) -void __go_set_closure(void*); -void* __go_get_closure(void); - bool runtime_gcwaiting(void); void runtime_badsignal(int); Defer* runtime_newdefer(void); diff --git a/libgo/runtime/time.goc b/libgo/runtime/time.goc index ee24b9c52df..b77ad3333d3 100644 --- a/libgo/runtime/time.goc +++ b/libgo/runtime/time.goc @@ -237,8 +237,7 @@ timerproc(void* dummy __attribute__ ((unused))) arg = t->arg; seq = t->seq; runtime_unlock(&timers); - __go_set_closure(fv); - f(arg, seq); + __builtin_call_with_static_chain(f(arg, seq), fv); // clear f and arg to avoid leak while sleeping for next timer f = nil; |