aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
Diffstat (limited to 'libgo')
-rw-r--r--libgo/Makefile.am1
-rw-r--r--libgo/Makefile.in11
-rwxr-xr-xlibgo/configure2
-rw-r--r--libgo/configure.ac2
-rw-r--r--libgo/go/reflect/all_test.go3
-rw-r--r--libgo/go/reflect/type.go6
-rw-r--r--libgo/go/reflect/value.go39
-rw-r--r--libgo/go/runtime/extern.go3
-rw-r--r--libgo/go/runtime/parfor_test.go9
-rw-r--r--libgo/runtime/go-reflect-call.c33
-rw-r--r--libgo/runtime/malloc.h3
-rw-r--r--libgo/runtime/mfinal.c8
-rw-r--r--libgo/runtime/mgc0.c10
-rw-r--r--libgo/runtime/parfor.c2
-rw-r--r--libgo/runtime/runtime.h12
-rw-r--r--libgo/runtime/time.goc13
16 files changed, 104 insertions, 53 deletions
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index ea90318..d54448c 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -487,7 +487,6 @@ runtime_files = \
runtime/go-strplus.c \
runtime/go-strslice.c \
runtime/go-traceback.c \
- runtime/go-trampoline.c \
runtime/go-type-complex.c \
runtime/go-type-eface.c \
runtime/go-type-error.c \
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 2ec60d3..08eae57 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -208,7 +208,7 @@ am__objects_5 = go-append.lo go-assert.lo go-assert-interface.lo \
go-reflect-call.lo go-reflect-map.lo go-rune.lo \
go-runtime-error.lo go-setenv.lo go-signal.lo go-strcmp.lo \
go-string-to-byte-array.lo go-string-to-int-array.lo \
- go-strplus.lo go-strslice.lo go-traceback.lo go-trampoline.lo \
+ go-strplus.lo go-strslice.lo go-traceback.lo \
go-type-complex.lo go-type-eface.lo go-type-error.lo \
go-type-float.lo go-type-identity.lo go-type-interface.lo \
go-type-string.lo go-typedesc-equal.lo go-typestring.lo \
@@ -822,7 +822,6 @@ runtime_files = \
runtime/go-strplus.c \
runtime/go-strslice.c \
runtime/go-traceback.c \
- runtime/go-trampoline.c \
runtime/go-type-complex.c \
runtime/go-type-eface.c \
runtime/go-type-error.c \
@@ -2519,7 +2518,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strplus.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strslice.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-traceback.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-trampoline.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-complex.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-eface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-error.Plo@am__quote@
@@ -2959,13 +2957,6 @@ go-traceback.lo: runtime/go-traceback.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-traceback.lo `test -f 'runtime/go-traceback.c' || echo '$(srcdir)/'`runtime/go-traceback.c
-go-trampoline.lo: runtime/go-trampoline.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-trampoline.lo -MD -MP -MF $(DEPDIR)/go-trampoline.Tpo -c -o go-trampoline.lo `test -f 'runtime/go-trampoline.c' || echo '$(srcdir)/'`runtime/go-trampoline.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-trampoline.Tpo $(DEPDIR)/go-trampoline.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-trampoline.c' object='go-trampoline.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-trampoline.lo `test -f 'runtime/go-trampoline.c' || echo '$(srcdir)/'`runtime/go-trampoline.c
-
go-type-complex.lo: runtime/go-type-complex.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-complex.lo -MD -MP -MF $(DEPDIR)/go-type-complex.Tpo -c -o go-type-complex.lo `test -f 'runtime/go-type-complex.c' || echo '$(srcdir)/'`runtime/go-type-complex.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-type-complex.Tpo $(DEPDIR)/go-type-complex.Plo
diff --git a/libgo/configure b/libgo/configure
index e1d37dc..5c943ff 100755
--- a/libgo/configure
+++ b/libgo/configure
@@ -2496,7 +2496,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_headers="$ac_config_headers config.h"
-libtool_VERSION=3:1:0
+libtool_VERSION=5:0:0
# Default to --enable-multilib
diff --git a/libgo/configure.ac b/libgo/configure.ac
index 58cc045..002aa88 100644
--- a/libgo/configure.ac
+++ b/libgo/configure.ac
@@ -11,7 +11,7 @@ AC_INIT(package-unused, version-unused,, libgo)
AC_CONFIG_SRCDIR(Makefile.am)
AC_CONFIG_HEADER(config.h)
-libtool_VERSION=3:1:0
+libtool_VERSION=5:0:0
AC_SUBST(libtool_VERSION)
AM_ENABLE_MULTILIB(, ..)
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index 8a36023..5a2ae2e 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -1891,6 +1891,7 @@ func (*inner) m() {}
func (*outer) m() {}
func TestNestedMethods(t *testing.T) {
+ t.Skip("fails on gccgo due to function wrappers")
typ := TypeOf((*outer)(nil))
if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*outer).m).Pointer() {
t.Errorf("Wrong method table for outer: (m=%p)", (*outer).m)
@@ -1915,6 +1916,7 @@ func (i *InnerInt) M() int {
}
func TestEmbeddedMethods(t *testing.T) {
+ /* This part of the test fails on gccgo due to function wrappers.
typ := TypeOf((*OuterInt)(nil))
if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*OuterInt).M).Pointer() {
t.Errorf("Wrong method table for OuterInt: (m=%p)", (*OuterInt).M)
@@ -1923,6 +1925,7 @@ func TestEmbeddedMethods(t *testing.T) {
t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer())
}
}
+ */
i := &InnerInt{3}
if v := ValueOf(i).Method(0).Call(nil)[0].Int(); v != 3 {
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index 9e65870..b909177 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -243,8 +243,8 @@ type rtype struct {
size uintptr // size in bytes
hash uint32 // hash of type; avoids computation in hash tables
- hashfn func(unsafe.Pointer, uintptr) // hash function
- equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr) // equality function
+ hashfn uintptr // hash function code
+ equalfn uintptr // equality function code
string *string // string form; unnecessary but undeniably useful
*uncommonType // (relatively) uncommon fields
@@ -485,7 +485,7 @@ func (t *uncommonType) Method(i int) (m Method) {
mt := p.typ
m.Type = toType(mt)
x := new(unsafe.Pointer)
- *x = p.tfn
+ *x = unsafe.Pointer(&p.tfn)
m.Func = Value{mt, unsafe.Pointer(x), fl | flagIndir}
m.Index = i
return
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index 15f5715..f8126e6 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -377,7 +377,7 @@ func (v Value) call(method string, in []Value) []Value {
if iface.itab == nil {
panic(method + " of method on nil interface value")
}
- fn = iface.itab.fun[i]
+ fn = unsafe.Pointer(&iface.itab.fun[i])
rcvr = iface.word
} else {
ut := v.typ.uncommon()
@@ -388,7 +388,7 @@ func (v Value) call(method string, in []Value) []Value {
if m.pkgPath != nil {
panic(method + " of unexported method")
}
- fn = m.tfn
+ fn = unsafe.Pointer(&m.tfn)
t = m.mtyp
rcvr = v.iword()
}
@@ -462,6 +462,10 @@ func (v Value) call(method string, in []Value) []Value {
if v.flag&flagMethod != 0 {
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 {
@@ -471,7 +475,6 @@ func (v Value) call(method string, in []Value) []Value {
params[0] = unsafe.Pointer(p)
off = 1
}
- first_pointer := false
for i, pv := range in {
pv.mustBeExported()
targ := t.In(i).(*rtype)
@@ -483,14 +486,17 @@ func (v Value) call(method string, in []Value) []Value {
} else {
params[off] = pv.val
}
- if i == 0 && Kind(targ.kind) != Ptr && v.flag&flagMethod == 0 && isMethod(v.typ) {
+ if i == 0 && firstPointer {
p := new(unsafe.Pointer)
*p = params[off]
params[off] = unsafe.Pointer(p)
- first_pointer = true
}
off++
}
+ if v.flag&flagMethod == 0 && !firstPointer {
+ // Closure argument.
+ params[off] = unsafe.Pointer(&fn)
+ }
ret := make([]Value, nout)
results := make([]unsafe.Pointer, nout)
@@ -509,7 +515,7 @@ func (v Value) call(method string, in []Value) []Value {
pr = &results[0]
}
- call(t, fn, v.flag&flagMethod != 0, first_pointer, pp, pr)
+ call(t, fn, v.flag&flagMethod != 0, firstPointer, pp, pr)
return ret
}
@@ -1209,18 +1215,35 @@ func (v Value) OverflowUint(x uint64) bool {
// code using reflect cannot obtain unsafe.Pointers
// without importing the unsafe package explicitly.
// It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer.
+//
+// If v's Kind is Func, the returned pointer is an underlying
+// code pointer, but not necessarily enough to identify a
+// single function uniquely. The only guarantee is that the
+// result is zero if and only if v is a nil func Value.
func (v Value) Pointer() uintptr {
k := v.kind()
switch k {
- case Chan, Func, Map, Ptr, UnsafePointer:
- if k == Func && v.flag&flagMethod != 0 {
+ case Chan, Map, Ptr, UnsafePointer:
+ p := v.val
+ if v.flag&flagIndir != 0 {
+ p = *(*unsafe.Pointer)(p)
+ }
+ return uintptr(p)
+ case Func:
+ if v.flag&flagMethod != 0 {
panic("reflect.Value.Pointer of method Value")
}
p := v.val
if v.flag&flagIndir != 0 {
p = *(*unsafe.Pointer)(p)
}
+ // Non-nil func value points at data block.
+ // First word of data block is actual code.
+ if p != nil {
+ p = *(*unsafe.Pointer)(p)
+ }
return uintptr(p)
+
case Slice:
return (*SliceHeader)(v.val).Data
}
diff --git a/libgo/go/runtime/extern.go b/libgo/go/runtime/extern.go
index 2a90113..6e91ef5 100644
--- a/libgo/go/runtime/extern.go
+++ b/libgo/go/runtime/extern.go
@@ -59,9 +59,6 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) {
// implemented in symtab.c
func funcline_go(*Func, uintptr) (string, int)
-// mid returns the current OS thread (m) id.
-func mid() uint32
-
// SetFinalizer sets the finalizer associated with x to f.
// When the garbage collector finds an unreachable block
// with an associated finalizer, it clears the association and runs
diff --git a/libgo/go/runtime/parfor_test.go b/libgo/go/runtime/parfor_test.go
index b382b76..4c69a68 100644
--- a/libgo/go/runtime/parfor_test.go
+++ b/libgo/go/runtime/parfor_test.go
@@ -13,6 +13,8 @@ import (
"unsafe"
)
+var gdata []uint64
+
// Simple serial sanity test for parallelfor.
func TestParFor(t *testing.T) {
const P = 1
@@ -22,7 +24,12 @@ func TestParFor(t *testing.T) {
data[i] = i
}
desc := NewParFor(P)
+ // Avoid making func a closure: parfor cannot invoke them.
+ // Since it doesn't happen in the C code, it's not worth doing
+ // just for the test.
+ gdata = data
ParForSetup(desc, P, N, nil, true, func(desc *ParFor, i uint32) {
+ data := gdata
data[i] = data[i]*data[i] + 1
})
ParForDo(desc)
@@ -111,7 +118,9 @@ func TestParForParallel(t *testing.T) {
P := GOMAXPROCS(-1)
c := make(chan bool, P)
desc := NewParFor(uint32(P))
+ gdata = data
ParForSetup(desc, uint32(P), uint32(N), nil, false, func(desc *ParFor, i uint32) {
+ data := gdata
data[i] = data[i]*data[i] + 1
})
for p := 1; p < P; p++ {
diff --git a/libgo/runtime/go-reflect-call.c b/libgo/runtime/go-reflect-call.c
index a66f928..83b9eba 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 a820774..7ebb762 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 7c906da..407092b 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 ffbe2ce..88283cc 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 591b968..65ca586 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 9392df1..959220d 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 9a5cbdf..e9f087a 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) {