summaryrefslogtreecommitdiff
path: root/libgo/runtime
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-16 22:58:53 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-16 22:58:53 +0000
commit1ecc61579adbbe6be91ba4847de3dd47615f2da9 (patch)
treec90d2bfba44756e26640c50ad1389375693ef832 /libgo/runtime
parent3bb12d97b7bf4bc70ce53e33a51085adf768f600 (diff)
downloadgcc-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.c39
-rw-r--r--libgo/runtime/go-reflect-call.c15
-rw-r--r--libgo/runtime/malloc.goc8
-rw-r--r--libgo/runtime/mgc0.c4
-rw-r--r--libgo/runtime/proc.c20
-rw-r--r--libgo/runtime/runtime.h4
-rw-r--r--libgo/runtime/time.goc3
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;