diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-06-18 23:49:49 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-06-18 23:49:49 +0000 |
commit | 8381eda7ff1e5a2874d708573654e64a4efcfb4f (patch) | |
tree | 1a7d38cd8be5484451189338ed6f4b76d8521f31 /libgo/runtime | |
parent | 2851d736ebf1e8cceebb9106cab69d2c3fdc7624 (diff) | |
download | gcc-8381eda7ff1e5a2874d708573654e64a4efcfb4f.tar.gz |
compiler, runtime: Use function descriptors.
This changes the representation of a Go value of function type
from being a pointer to function code (like a C function
pointer) to being a pointer to a struct. The first field of
the struct points to the function code. The remaining fields,
if any, are the addresses of variables referenced in enclosing
functions. For each call to a function, the address of the
function descriptor is passed as the last argument.
This lets us avoid generating trampolines, and removes the use
of writable/executable sections of the heap.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@200181 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/runtime')
-rw-r--r-- | libgo/runtime/go-reflect-call.c | 33 | ||||
-rw-r--r-- | libgo/runtime/malloc.h | 3 | ||||
-rw-r--r-- | libgo/runtime/mfinal.c | 8 | ||||
-rw-r--r-- | libgo/runtime/mgc0.c | 10 | ||||
-rw-r--r-- | libgo/runtime/parfor.c | 2 | ||||
-rw-r--r-- | libgo/runtime/runtime.h | 12 | ||||
-rw-r--r-- | libgo/runtime/time.goc | 13 |
7 files changed, 55 insertions, 26 deletions
diff --git a/libgo/runtime/go-reflect-call.c b/libgo/runtime/go-reflect-call.c index a66f92868f8..83b9eba0436 100644 --- a/libgo/runtime/go-reflect-call.c +++ b/libgo/runtime/go-reflect-call.c @@ -302,7 +302,9 @@ 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); + num_args = (num_params + + (is_interface ? 1 : 0) + + (!is_interface && !is_method ? 1 : 0)); args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *)); i = 0; off = 0; @@ -319,6 +321,12 @@ 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); @@ -491,11 +499,24 @@ go_set_results (const struct __go_func_type *func, unsigned char *call_result, } /* Call a function. The type of the function is FUNC_TYPE, and the - address is FUNC_ADDR. PARAMS is an array of parameter addresses. - RESULTS is an array of result addresses. */ + closure is FUNC_VAL. PARAMS is an array of parameter addresses. + RESULTS is an array of result addresses. + + If IS_INTERFACE is true this is a call to an interface method and + the first argument is the receiver, which is always a pointer. + This argument, the receiver, is not described in FUNC_TYPE. + + 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 the caller is responsible for passing a + trailing closure argument, a pointer, which is not described in + FUNC_TYPE. */ void -reflect_call (const struct __go_func_type *func_type, const void *func_addr, +reflect_call (const struct __go_func_type *func_type, FuncVal *func_val, _Bool is_interface, _Bool is_method, void **params, void **results) { @@ -507,7 +528,7 @@ reflect_call (const struct __go_func_type *func_type, const void *func_addr, call_result = (unsigned char *) malloc (go_results_size (func_type)); - ffi_call (&cif, func_addr, call_result, params); + ffi_call (&cif, func_val->fn, call_result, params); /* Some day we may need to free result values if RESULTS is NULL. */ @@ -521,7 +542,7 @@ reflect_call (const struct __go_func_type *func_type, const void *func_addr, void reflect_call (const struct __go_func_type *func_type __attribute__ ((unused)), - const void *func_addr __attribute__ ((unused)), + FuncVal *func_val __attribute__ ((unused)), _Bool is_interface __attribute__ ((unused)), _Bool is_method __attribute__ ((unused)), void **params __attribute__ ((unused)), diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h index a8207742031..7ebb762450e 100644 --- a/libgo/runtime/malloc.h +++ b/libgo/runtime/malloc.h @@ -485,7 +485,7 @@ void runtime_helpgc(int32 nproc); void runtime_gchelper(void); struct __go_func_type; -bool runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft); +bool runtime_getfinalizer(void *p, bool del, FuncVal **fn, const struct __go_func_type **ft); void runtime_walkfintab(void (*fn)(void*), void (*scan)(Obj)); enum @@ -505,4 +505,3 @@ void runtime_gc_itab_ptr(Eface*); void runtime_memorydump(void); void runtime_time_scan(void (*)(Obj)); -void runtime_trampoline_scan(void (*)(Obj)); diff --git a/libgo/runtime/mfinal.c b/libgo/runtime/mfinal.c index 7c906daf347..407092bf392 100644 --- a/libgo/runtime/mfinal.c +++ b/libgo/runtime/mfinal.c @@ -11,7 +11,7 @@ enum { debug = 0 }; typedef struct Fin Fin; struct Fin { - void (*fn)(void*); + FuncVal *fn; const struct __go_func_type *ft; }; @@ -42,7 +42,7 @@ static struct { } fintab[TABSZ]; static void -addfintab(Fintab *t, void *k, void (*fn)(void*), const struct __go_func_type *ft) +addfintab(Fintab *t, void *k, FuncVal *fn, const struct __go_func_type *ft) { int32 i, j; @@ -137,7 +137,7 @@ resizefintab(Fintab *tab) } bool -runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft) +runtime_addfinalizer(void *p, FuncVal *f, const struct __go_func_type *ft) { Fintab *tab; byte *base; @@ -175,7 +175,7 @@ runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft) // get finalizer; if del, delete finalizer. // caller is responsible for updating RefHasFinalizer (special) bit. bool -runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft) +runtime_getfinalizer(void *p, bool del, FuncVal **fn, const struct __go_func_type **ft) { Fintab *tab; bool res; diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c index ffbe2cefb2d..88283ccab2b 100644 --- a/libgo/runtime/mgc0.c +++ b/libgo/runtime/mgc0.c @@ -120,7 +120,7 @@ struct Workbuf typedef struct Finalizer Finalizer; struct Finalizer { - void (*fn)(void*); + FuncVal *fn; void *arg; const struct __go_func_type *ft; }; @@ -1130,7 +1130,6 @@ addroots(void) addroot((Obj){(byte*)&runtime_allm, sizeof runtime_allm, 0}); runtime_MProf_Mark(addroot); runtime_time_scan(addroot); - runtime_trampoline_scan(addroot); // MSpan.types allspans = runtime_mheap.allspans; @@ -1182,7 +1181,7 @@ addroots(void) static bool handlespecial(byte *p, uintptr size) { - void (*fn)(void*); + FuncVal *fn; const struct __go_func_type *ft; FinBlock *block; Finalizer *f; @@ -1731,11 +1730,12 @@ runfinq(void* dummy __attribute__ ((unused))) for(; fb; fb=next) { next = fb->next; for(i=0; i<(uint32)fb->cnt; i++) { - void *params[1]; + void *params[2]; f = &fb->fin[i]; params[0] = &f->arg; - reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil); + params[1] = f; + reflect_call(f->ft, f->fn, 0, 0, params, nil); f->fn = nil; f->arg = nil; } diff --git a/libgo/runtime/parfor.c b/libgo/runtime/parfor.c index 591b968c039..65ca586eadb 100644 --- a/libgo/runtime/parfor.c +++ b/libgo/runtime/parfor.c @@ -83,7 +83,7 @@ void runtime_parforsetup2(ParFor *, uint32, uint32, void *, bool, void *) void runtime_parforsetup2(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void *body) { - runtime_parforsetup(desc, nthr, n, ctx, wait, (void(*)(ParFor*, uint32))body); + runtime_parforsetup(desc, nthr, n, ctx, wait, *(void(**)(ParFor*, uint32))body); } void diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index 9392df162bf..959220d734c 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -57,6 +57,7 @@ typedef struct G G; typedef union Lock Lock; typedef struct M M; typedef union Note Note; +typedef struct FuncVal FuncVal; typedef struct SigTab SigTab; typedef struct MCache MCache; typedef struct FixAlloc FixAlloc; @@ -147,6 +148,11 @@ struct String const byte* str; intgo len; }; +struct FuncVal +{ + void (*fn)(void); + // variable-size, fn-specific data here +}; struct GCStats { // the struct must consist of only uint64's, @@ -313,7 +319,7 @@ struct Timer // a well-behaved function and not block. int64 when; int64 period; - void (*f)(int64, Eface); + FuncVal *fv; Eface arg; }; @@ -540,7 +546,7 @@ void runtime_printslice(Slice); void runtime_printcomplex(__complex double); struct __go_func_type; -void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool, +void reflect_call(const struct __go_func_type *, FuncVal *, _Bool, _Bool, void **, void **) __asm__ (GOSYM_PREFIX "reflect.call"); @@ -570,7 +576,7 @@ void free(void *v); #define PREFETCH(p) __builtin_prefetch(p) struct __go_func_type; -bool runtime_addfinalizer(void*, void(*fn)(void*), const struct __go_func_type *); +bool runtime_addfinalizer(void*, FuncVal *fn, const struct __go_func_type *); #define runtime_getcallersp(p) __builtin_frame_address(1) int32 runtime_mcount(void); int32 runtime_gcount(void); diff --git a/libgo/runtime/time.goc b/libgo/runtime/time.goc index 9a5cbdfed3b..e9f087ac884 100644 --- a/libgo/runtime/time.goc +++ b/libgo/runtime/time.goc @@ -49,13 +49,16 @@ static void siftdown(int32); // Ready the goroutine e.data. static void -ready(int64 now, Eface e) +ready(int64 now, Eface e, void *closure) { USED(now); + USED(closure); runtime_ready(e.__object); } +static FuncVal readyv = {(void(*)(void))ready}; + // Put the current goroutine to sleep for ns nanoseconds. void runtime_tsleep(int64 ns, const char *reason) @@ -70,7 +73,7 @@ runtime_tsleep(int64 ns, const char *reason) t.when = runtime_nanotime() + ns; t.period = 0; - t.f = ready; + t.fv = &readyv; t.arg.__object = g; runtime_lock(&timers); addtimer(&t); @@ -158,7 +161,7 @@ timerproc(void* dummy __attribute__ ((unused))) { int64 delta, now; Timer *t; - void (*f)(int64, Eface); + void (*f)(int64, Eface, void *); Eface arg; for(;;) { @@ -184,12 +187,12 @@ timerproc(void* dummy __attribute__ ((unused))) siftdown(0); t->i = -1; // mark as removed } - f = t->f; + f = (void*)t->fv->fn; arg = t->arg; runtime_unlock(&timers); if(raceenabled) runtime_raceacquire(t); - f(now, arg); + f(now, arg, &t->fv); runtime_lock(&timers); } if(delta < 0) { |