summaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2013-09-03 21:52:37 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2013-09-03 21:52:37 +0000
commit05a7d566782733230696a51ab8575261b8f9f162 (patch)
tree5f956e4c89959ef335ef73b7ec6e00e4bc2c12d5 /libgo
parent3b18bc426a5c853bda2bdb9e646c5b00483e982a (diff)
downloadgcc-05a7d566782733230696a51ab8575261b8f9f162.tar.gz
compiler, runtime: Use runtime functions to pass closure value.
This changes the compiler and runtime to not pass a closure value as the last argument, but to instead pass it via __go_set_closure and retrieve it via __go_get_closure. This eliminates the need for function descriptor wrapper functions. It will make it possible to retrieve the closure value in a reflect.MakeFunc function. From-SVN: r202233
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/reflect/value.go7
-rw-r--r--libgo/runtime/go-reflect-call.c17
-rw-r--r--libgo/runtime/mgc0.c7
-rw-r--r--libgo/runtime/proc.c20
-rw-r--r--libgo/runtime/runtime.h4
-rw-r--r--libgo/runtime/time.goc8
6 files changed, 36 insertions, 27 deletions
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index 6bf66c8caf6..45a08587973 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -434,9 +434,6 @@ func (v Value) call(op string, in []Value) []Value {
nin++
}
firstPointer := len(in) > 0 && Kind(t.In(0).(*rtype).kind) != Ptr && v.flag&flagMethod == 0 && isMethod(v.typ)
- if v.flag&flagMethod == 0 && !firstPointer {
- nin++
- }
params := make([]unsafe.Pointer, nin)
off := 0
if v.flag&flagMethod != 0 {
@@ -464,10 +461,6 @@ func (v Value) call(op string, in []Value) []Value {
}
off++
}
- if v.flag&flagMethod == 0 && !firstPointer {
- // Closure argument.
- params[off] = unsafe.Pointer(&fn)
- }
ret := make([]Value, nout)
results := make([]unsafe.Pointer, nout)
diff --git a/libgo/runtime/go-reflect-call.c b/libgo/runtime/go-reflect-call.c
index 83b9eba0436..5cf370798bf 100644
--- a/libgo/runtime/go-reflect-call.c
+++ b/libgo/runtime/go-reflect-call.c
@@ -302,9 +302,7 @@ go_func_to_cif (const struct __go_func_type *func, _Bool is_interface,
in_types = ((const struct __go_type_descriptor **)
func->__in.__values);
- num_args = (num_params
- + (is_interface ? 1 : 0)
- + (!is_interface && !is_method ? 1 : 0));
+ num_args = num_params + (is_interface ? 1 : 0);
args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *));
i = 0;
off = 0;
@@ -321,12 +319,6 @@ go_func_to_cif (const struct __go_func_type *func, _Bool is_interface,
for (; i < num_params; ++i)
args[i + off] = go_type_to_ffi (in_types[i]);
- if (!is_interface && !is_method)
- {
- // There is a closure argument, a pointer.
- args[i + off] = &ffi_type_pointer;
- }
-
rettype = go_func_return_ffi (func);
status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, num_args, rettype, args);
@@ -511,9 +503,8 @@ go_set_results (const struct __go_func_type *func, unsigned char *call_result,
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 the caller is responsible for passing a
- trailing closure argument, a pointer, which is not described in
- FUNC_TYPE. */
+ function indirectly, and we must pass a closure pointer via
+ __go_set_closure. The pointer to pass is simply FUNC_VAL. */
void
reflect_call (const struct __go_func_type *func_type, FuncVal *func_val,
@@ -528,6 +519,8 @@ 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);
/* Some day we may need to free result values if RESULTS is
diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c
index 36afd2b964d..c3b32111ca0 100644
--- a/libgo/runtime/mgc0.c
+++ b/libgo/runtime/mgc0.c
@@ -2263,12 +2263,11 @@ runfinq(void* dummy __attribute__ ((unused)))
for(; fb; fb=next) {
next = fb->next;
for(i=0; i<(uint32)fb->cnt; i++) {
- void *params[2];
+ void *param;
f = &fb->fin[i];
- params[0] = &f->arg;
- params[1] = f;
- reflect_call(f->ft, f->fn, 0, 0, params, nil);
+ param = &f->arg;
+ reflect_call(f->ft, f->fn, 0, 0, &param, nil);
f->fn = nil;
f->arg = nil;
}
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index d42ff3362ee..0e77a3e0603 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -2832,3 +2832,23 @@ runtime_proc_scan(void (*addroot)(Obj))
{
addroot((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;
+}
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index 78fd388186a..d2e7d4c11bc 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -190,6 +190,7 @@ struct Location
struct G
{
+ void* closure; // Closure value.
Defer* defer;
Panic* panic;
void* exception; // current exception being thrown
@@ -759,3 +760,6 @@ extern void runtime_main(void*);
int32 getproccount(void);
#define PREFETCH(p) __builtin_prefetch(p)
+
+void __go_set_closure(void*);
+void* __go_get_closure(void);
diff --git a/libgo/runtime/time.goc b/libgo/runtime/time.goc
index e06b75ccb3d..8d12fe01080 100644
--- a/libgo/runtime/time.goc
+++ b/libgo/runtime/time.goc
@@ -46,10 +46,9 @@ static void siftdown(int32);
// Ready the goroutine e.data.
static void
-ready(int64 now, Eface e, void *closure)
+ready(int64 now, Eface e)
{
USED(now);
- USED(closure);
runtime_ready(e.__object);
}
@@ -166,7 +165,7 @@ timerproc(void* dummy __attribute__ ((unused)))
{
int64 delta, now;
Timer *t;
- void (*f)(int64, Eface, void *);
+ void (*f)(int64, Eface);
Eface arg;
for(;;) {
@@ -197,7 +196,8 @@ timerproc(void* dummy __attribute__ ((unused)))
runtime_unlock(&timers);
if(raceenabled)
runtime_raceacquire(t);
- f(now, arg, &t->fv);
+ __go_set_closure(t->fv);
+ f(now, arg);
runtime_lock(&timers);
}
if(delta < 0) {