diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2014-07-19 21:36:26 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2014-07-19 21:36:26 +0000 |
commit | dffa7328356257772dc7c00fe73aeb315229b373 (patch) | |
tree | b56b22f6c7e733e05e3f634ca63f18e10bc1b304 /libgo/runtime | |
parent | 0c92e4881a61a2483c2878f9953ff92188e9661e (diff) | |
download | gcc-dffa7328356257772dc7c00fe73aeb315229b373.zip gcc-dffa7328356257772dc7c00fe73aeb315229b373.tar.gz gcc-dffa7328356257772dc7c00fe73aeb315229b373.tar.bz2 |
reflect, runtime: Use libffi closures to implement reflect.MakeFunc.
Keep using the existing 386 and amd64 code on those archs,
since it is more efficient.
From-SVN: r212853
Diffstat (limited to 'libgo/runtime')
-rw-r--r-- | libgo/runtime/go-caller.c | 2 | ||||
-rw-r--r-- | libgo/runtime/go-callers.c | 8 | ||||
-rw-r--r-- | libgo/runtime/go-ffi.c | 338 | ||||
-rw-r--r-- | libgo/runtime/go-ffi.h | 16 | ||||
-rw-r--r-- | libgo/runtime/go-panic.h | 6 | ||||
-rw-r--r-- | libgo/runtime/go-recover.c | 9 | ||||
-rw-r--r-- | libgo/runtime/go-reflect-call.c | 319 | ||||
-rw-r--r-- | libgo/runtime/go-traceback.c | 2 | ||||
-rw-r--r-- | libgo/runtime/mprof.goc | 6 | ||||
-rw-r--r-- | libgo/runtime/proc.c | 6 | ||||
-rw-r--r-- | libgo/runtime/runtime.h | 2 |
11 files changed, 381 insertions, 333 deletions
diff --git a/libgo/runtime/go-caller.c b/libgo/runtime/go-caller.c index e97b850..a5c687d 100644 --- a/libgo/runtime/go-caller.c +++ b/libgo/runtime/go-caller.c @@ -177,7 +177,7 @@ Caller (int skip) int32 n; runtime_memclr (&ret, sizeof ret); - n = runtime_callers (skip + 1, &loc, 1); + n = runtime_callers (skip + 1, &loc, 1, false); if (n < 1) return ret; ret.pc = loc.pc; diff --git a/libgo/runtime/go-callers.c b/libgo/runtime/go-callers.c index 2136869..0470345 100644 --- a/libgo/runtime/go-callers.c +++ b/libgo/runtime/go-callers.c @@ -26,6 +26,7 @@ struct callers_data int skip; int index; int max; + int keep_thunks; }; /* Callback function for backtrace_full. Just collect the locations. @@ -63,7 +64,7 @@ callback (void *data, uintptr_t pc, const char *filename, int lineno, /* Skip thunks and recover functions. There is no equivalent to these functions in the gc toolchain, so returning them here means significantly different results for runtime.Caller(N). */ - if (function != NULL) + if (function != NULL && !arg->keep_thunks) { const char *p; @@ -136,7 +137,7 @@ error_callback (void *data __attribute__ ((unused)), /* Gather caller PC's. */ int32 -runtime_callers (int32 skip, Location *locbuf, int32 m) +runtime_callers (int32 skip, Location *locbuf, int32 m, bool keep_thunks) { struct callers_data data; @@ -144,6 +145,7 @@ runtime_callers (int32 skip, Location *locbuf, int32 m) data.skip = skip + 1; data.index = 0; data.max = m; + data.keep_thunks = keep_thunks; runtime_xadd (&runtime_in_callers, 1); backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback, &data); @@ -167,7 +169,7 @@ Callers (int skip, struct __go_open_array pc) which we can not correct because it would break backward compatibility. Normally we would add 1 to SKIP here, but we don't so that we are compatible. */ - ret = runtime_callers (skip, locbuf, pc.__count); + ret = runtime_callers (skip, locbuf, pc.__count, false); for (i = 0; i < ret; i++) ((uintptr *) pc.__values)[i] = locbuf[i].pc; diff --git a/libgo/runtime/go-ffi.c b/libgo/runtime/go-ffi.c new file mode 100644 index 0000000..21879b9 --- /dev/null +++ b/libgo/runtime/go-ffi.c @@ -0,0 +1,338 @@ +/* go-ffi.c -- convert Go type description to libffi. + + Copyright 2009 The Go Authors. All rights reserved. + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. */ + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> + +#include "runtime.h" +#include "go-alloc.h" +#include "go-assert.h" +#include "go-type.h" + +#ifdef USE_LIBFFI + +#include "ffi.h" + +/* The functions in this file are only called from reflect_call and + reflect.ffi. As these functions call libffi functions, which will + be compiled without -fsplit-stack, they will always run with a + large stack. */ + +static ffi_type *go_array_to_ffi (const struct __go_array_type *) + __attribute__ ((no_split_stack)); +static ffi_type *go_slice_to_ffi (const struct __go_slice_type *) + __attribute__ ((no_split_stack)); +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 *) + __attribute__ ((no_split_stack)); + +/* Return an ffi_type for a Go array type. The libffi library does + not have any builtin support for passing arrays as values. We work + around this by pretending that the array is a struct. */ + +static ffi_type * +go_array_to_ffi (const struct __go_array_type *descriptor) +{ + ffi_type *ret; + uintptr_t len; + ffi_type *element; + uintptr_t i; + + ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); + ret->type = FFI_TYPE_STRUCT; + len = descriptor->__len; + ret->elements = (ffi_type **) __go_alloc ((len + 1) * sizeof (ffi_type *)); + element = go_type_to_ffi (descriptor->__element_type); + for (i = 0; i < len; ++i) + ret->elements[i] = element; + ret->elements[len] = NULL; + return ret; +} + +/* Return an ffi_type for a Go slice type. This describes the + __go_open_array type defines in array.h. */ + +static ffi_type * +go_slice_to_ffi ( + const struct __go_slice_type *descriptor __attribute__ ((unused))) +{ + ffi_type *ret; + ffi_type *ffi_intgo; + + ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); + ret->type = FFI_TYPE_STRUCT; + ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *)); + ret->elements[0] = &ffi_type_pointer; + ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64; + ret->elements[1] = ffi_intgo; + ret->elements[2] = ffi_intgo; + ret->elements[3] = NULL; + return ret; +} + +/* Return an ffi_type for a Go struct type. */ + +static ffi_type * +go_struct_to_ffi (const struct __go_struct_type *descriptor) +{ + ffi_type *ret; + int field_count; + const struct __go_struct_field *fields; + int i; + + field_count = descriptor->__fields.__count; + if (field_count == 0) { + return &ffi_type_void; + } + ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); + ret->type = FFI_TYPE_STRUCT; + fields = (const struct __go_struct_field *) descriptor->__fields.__values; + ret->elements = (ffi_type **) __go_alloc ((field_count + 1) + * sizeof (ffi_type *)); + for (i = 0; i < field_count; ++i) + ret->elements[i] = go_type_to_ffi (fields[i].__type); + ret->elements[field_count] = NULL; + return ret; +} + +/* Return an ffi_type for a Go string type. This describes the String + struct. */ + +static ffi_type * +go_string_to_ffi (void) +{ + ffi_type *ret; + ffi_type *ffi_intgo; + + ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); + ret->type = FFI_TYPE_STRUCT; + ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *)); + ret->elements[0] = &ffi_type_pointer; + ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64; + ret->elements[1] = ffi_intgo; + ret->elements[2] = NULL; + return ret; +} + +/* Return an ffi_type for a Go interface type. This describes the + __go_interface and __go_empty_interface structs. */ + +static ffi_type * +go_interface_to_ffi (void) +{ + ffi_type *ret; + + ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); + ret->type = FFI_TYPE_STRUCT; + ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *)); + ret->elements[0] = &ffi_type_pointer; + ret->elements[1] = &ffi_type_pointer; + ret->elements[2] = NULL; + return ret; +} + +/* Return an ffi_type for a Go complex type. */ + +static ffi_type * +go_complex_to_ffi (ffi_type *float_type) +{ + ffi_type *ret; + + ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); + ret->type = FFI_TYPE_STRUCT; + ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *)); + ret->elements[0] = float_type; + ret->elements[1] = float_type; + ret->elements[2] = NULL; + return ret; +} + +/* Return an ffi_type for a type described by a + __go_type_descriptor. */ + +static ffi_type * +go_type_to_ffi (const struct __go_type_descriptor *descriptor) +{ + switch (descriptor->__code & GO_CODE_MASK) + { + case GO_BOOL: + if (sizeof (_Bool) == 1) + return &ffi_type_uint8; + else if (sizeof (_Bool) == sizeof (int)) + return &ffi_type_uint; + abort (); + case GO_FLOAT32: + if (sizeof (float) == 4) + return &ffi_type_float; + abort (); + case GO_FLOAT64: + if (sizeof (double) == 8) + 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 (); +#endif + 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 (); +#endif + case GO_INT16: + return &ffi_type_sint16; + case GO_INT32: + return &ffi_type_sint32; + case GO_INT64: + return &ffi_type_sint64; + case GO_INT8: + return &ffi_type_sint8; + case GO_INT: + return sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64; + case GO_UINT16: + return &ffi_type_uint16; + case GO_UINT32: + return &ffi_type_uint32; + case GO_UINT64: + return &ffi_type_uint64; + case GO_UINT8: + return &ffi_type_uint8; + case GO_UINT: + return sizeof (uintgo) == 4 ? &ffi_type_uint32 : &ffi_type_uint64; + case GO_UINTPTR: + if (sizeof (void *) == 2) + return &ffi_type_uint16; + else if (sizeof (void *) == 4) + return &ffi_type_uint32; + else if (sizeof (void *) == 8) + return &ffi_type_uint64; + abort (); + case GO_ARRAY: + return go_array_to_ffi ((const struct __go_array_type *) descriptor); + case GO_SLICE: + return go_slice_to_ffi ((const struct __go_slice_type *) descriptor); + case GO_STRUCT: + return go_struct_to_ffi ((const struct __go_struct_type *) descriptor); + case GO_STRING: + return go_string_to_ffi (); + case GO_INTERFACE: + return go_interface_to_ffi (); + case GO_CHAN: + case GO_FUNC: + case GO_MAP: + case GO_PTR: + case GO_UNSAFE_POINTER: + /* These types are always pointers, and for FFI purposes nothing + else matters. */ + return &ffi_type_pointer; + default: + abort (); + } +} + +/* Return the return type for a function, given the number of out + parameters and their types. */ + +static ffi_type * +go_func_return_ffi (const struct __go_func_type *func) +{ + int count; + const struct __go_type_descriptor **types; + ffi_type *ret; + int i; + + count = func->__out.__count; + if (count == 0) + return &ffi_type_void; + + types = (const struct __go_type_descriptor **) func->__out.__values; + + if (count == 1) + { + +#if defined (__i386__) && !defined (__x86_64__) + /* FFI does not support complex types. On 32-bit x86, a + complex64 will be returned in %eax/%edx. We normally tell + FFI that a complex64 is a struct of two floats. On 32-bit + x86 a struct of two floats is returned via a hidden first + pointer parameter. Fortunately we can make everything work + by pretending that complex64 is int64. */ + if ((types[0]->__code & GO_CODE_MASK) == GO_COMPLEX64) + return &ffi_type_sint64; +#endif + + return go_type_to_ffi (types[0]); + } + + ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); + ret->type = FFI_TYPE_STRUCT; + ret->elements = (ffi_type **) __go_alloc ((count + 1) * sizeof (ffi_type *)); + for (i = 0; i < count; ++i) + ret->elements[i] = go_type_to_ffi (types[i]); + ret->elements[count] = NULL; + return ret; +} + +/* Build an ffi_cif structure for a function described by a + __go_func_type structure. */ + +void +__go_func_to_cif (const struct __go_func_type *func, _Bool is_interface, + _Bool is_method, ffi_cif *cif) +{ + int num_params; + const struct __go_type_descriptor **in_types; + size_t num_args; + ffi_type **args; + int off; + int i; + ffi_type *rettype; + ffi_status status; + + num_params = func->__in.__count; + in_types = ((const struct __go_type_descriptor **) + func->__in.__values); + + num_args = num_params + (is_interface ? 1 : 0); + args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *)); + i = 0; + off = 0; + if (is_interface) + { + args[0] = &ffi_type_pointer; + off = 1; + } + else if (is_method) + { + args[0] = &ffi_type_pointer; + i = 1; + } + for (; i < num_params; ++i) + args[i + off] = go_type_to_ffi (in_types[i]); + + rettype = go_func_return_ffi (func); + + status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, num_args, rettype, args); + __go_assert (status == FFI_OK); +} + +#endif /* defined(USE_LIBFFI) */ diff --git a/libgo/runtime/go-ffi.h b/libgo/runtime/go-ffi.h new file mode 100644 index 0000000..afae4b6 --- /dev/null +++ b/libgo/runtime/go-ffi.h @@ -0,0 +1,16 @@ +/* go-ffi.c -- convert Go type description to libffi. + + Copyright 2014 The Go Authors. All rights reserved. + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. */ + +#include "config.h" +#include "go-type.h" + +#ifdef USE_LIBFFI + +#include "ffi.h" + +void __go_func_to_cif (const struct __go_func_type *, _Bool, _Bool, ffi_cif *); + +#endif diff --git a/libgo/runtime/go-panic.h b/libgo/runtime/go-panic.h index e7031d4..bcaa7e1 100644 --- a/libgo/runtime/go-panic.h +++ b/libgo/runtime/go-panic.h @@ -38,6 +38,12 @@ extern void __go_print_string (struct String); extern struct __go_empty_interface __go_recover (void); +extern _Bool __go_can_recover (const void *); + +extern void __go_makefunc_can_recover (const void *retaddr); + +extern void __go_makefunc_returning (void); + extern void __go_unwind_stack (void); #endif /* !defined(LIBGO_GO_PANIC_H) */ diff --git a/libgo/runtime/go-recover.c b/libgo/runtime/go-recover.c index ceb9b57..2d3db55 100644 --- a/libgo/runtime/go-recover.c +++ b/libgo/runtime/go-recover.c @@ -63,7 +63,7 @@ __go_can_recover (const void *retaddr) if (!d->__makefunc_can_recover) return 0; - if (runtime_callers (2, &loc, 1) < 1) + if (runtime_callers (2, &loc, 1, false) < 1) return 0; /* If we have no function name, then we weren't called by Go code. @@ -84,9 +84,10 @@ __go_can_recover (const void *retaddr) if (name[0] == 'f' && name[1] == 'f' && name[2] == 'i' && name[3] == '_') return 1; - /* We may also be called by reflect.makeFuncImpl.call, for a - function created by reflect.MakeFunc. */ - if (__builtin_strstr ((const char *) name, "makeFuncImpl") != NULL) + /* We may also be called by reflect.makeFuncImpl.call or + reflect.ffiCall, for a function created by reflect.MakeFunc. */ + if (__builtin_strstr ((const char *) name, "makeFuncImpl") != NULL + || __builtin_strcmp ((const char *) name, "reflect.ffiCall") == 0) return 1; return 0; diff --git a/libgo/runtime/go-reflect-call.c b/libgo/runtime/go-reflect-call.c index 07b99d7..dfc703e 100644 --- a/libgo/runtime/go-reflect-call.c +++ b/libgo/runtime/go-reflect-call.c @@ -15,333 +15,18 @@ #ifdef USE_LIBFFI -#include "ffi.h" +#include "go-ffi.h" /* 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. */ -static ffi_type *go_array_to_ffi (const struct __go_array_type *) - __attribute__ ((no_split_stack)); -static ffi_type *go_slice_to_ffi (const struct __go_slice_type *) - __attribute__ ((no_split_stack)); -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 *) - __attribute__ ((no_split_stack)); -static void go_func_to_cif (const struct __go_func_type *, _Bool, _Bool, - ffi_cif *) - __attribute__ ((no_split_stack)); static size_t go_results_size (const struct __go_func_type *) __attribute__ ((no_split_stack)); static void go_set_results (const struct __go_func_type *, unsigned char *, void **) __attribute__ ((no_split_stack)); -/* Return an ffi_type for a Go array type. The libffi library does - not have any builtin support for passing arrays as values. We work - around this by pretending that the array is a struct. */ - -static ffi_type * -go_array_to_ffi (const struct __go_array_type *descriptor) -{ - ffi_type *ret; - uintptr_t len; - ffi_type *element; - uintptr_t i; - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - len = descriptor->__len; - ret->elements = (ffi_type **) __go_alloc ((len + 1) * sizeof (ffi_type *)); - element = go_type_to_ffi (descriptor->__element_type); - for (i = 0; i < len; ++i) - ret->elements[i] = element; - ret->elements[len] = NULL; - return ret; -} - -/* Return an ffi_type for a Go slice type. This describes the - __go_open_array type defines in array.h. */ - -static ffi_type * -go_slice_to_ffi ( - const struct __go_slice_type *descriptor __attribute__ ((unused))) -{ - ffi_type *ret; - ffi_type *ffi_intgo; - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *)); - ret->elements[0] = &ffi_type_pointer; - ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64; - ret->elements[1] = ffi_intgo; - ret->elements[2] = ffi_intgo; - ret->elements[3] = NULL; - return ret; -} - -/* Return an ffi_type for a Go struct type. */ - -static ffi_type * -go_struct_to_ffi (const struct __go_struct_type *descriptor) -{ - ffi_type *ret; - int field_count; - const struct __go_struct_field *fields; - int i; - - field_count = descriptor->__fields.__count; - if (field_count == 0) { - return &ffi_type_void; - } - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - fields = (const struct __go_struct_field *) descriptor->__fields.__values; - ret->elements = (ffi_type **) __go_alloc ((field_count + 1) - * sizeof (ffi_type *)); - for (i = 0; i < field_count; ++i) - ret->elements[i] = go_type_to_ffi (fields[i].__type); - ret->elements[field_count] = NULL; - return ret; -} - -/* Return an ffi_type for a Go string type. This describes the String - struct. */ - -static ffi_type * -go_string_to_ffi (void) -{ - ffi_type *ret; - ffi_type *ffi_intgo; - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *)); - ret->elements[0] = &ffi_type_pointer; - ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64; - ret->elements[1] = ffi_intgo; - ret->elements[2] = NULL; - return ret; -} - -/* Return an ffi_type for a Go interface type. This describes the - __go_interface and __go_empty_interface structs. */ - -static ffi_type * -go_interface_to_ffi (void) -{ - ffi_type *ret; - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *)); - ret->elements[0] = &ffi_type_pointer; - ret->elements[1] = &ffi_type_pointer; - ret->elements[2] = NULL; - return ret; -} - -/* Return an ffi_type for a Go complex type. */ - -static ffi_type * -go_complex_to_ffi (ffi_type *float_type) -{ - ffi_type *ret; - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *)); - ret->elements[0] = float_type; - ret->elements[1] = float_type; - ret->elements[2] = NULL; - return ret; -} - -/* Return an ffi_type for a type described by a - __go_type_descriptor. */ - -static ffi_type * -go_type_to_ffi (const struct __go_type_descriptor *descriptor) -{ - switch (descriptor->__code & GO_CODE_MASK) - { - case GO_BOOL: - if (sizeof (_Bool) == 1) - return &ffi_type_uint8; - else if (sizeof (_Bool) == sizeof (int)) - return &ffi_type_uint; - abort (); - case GO_FLOAT32: - if (sizeof (float) == 4) - return &ffi_type_float; - abort (); - case GO_FLOAT64: - if (sizeof (double) == 8) - 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 (); -#endif - 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 (); -#endif - case GO_INT16: - return &ffi_type_sint16; - case GO_INT32: - return &ffi_type_sint32; - case GO_INT64: - return &ffi_type_sint64; - case GO_INT8: - return &ffi_type_sint8; - case GO_INT: - return sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64; - case GO_UINT16: - return &ffi_type_uint16; - case GO_UINT32: - return &ffi_type_uint32; - case GO_UINT64: - return &ffi_type_uint64; - case GO_UINT8: - return &ffi_type_uint8; - case GO_UINT: - return sizeof (uintgo) == 4 ? &ffi_type_uint32 : &ffi_type_uint64; - case GO_UINTPTR: - if (sizeof (void *) == 2) - return &ffi_type_uint16; - else if (sizeof (void *) == 4) - return &ffi_type_uint32; - else if (sizeof (void *) == 8) - return &ffi_type_uint64; - abort (); - case GO_ARRAY: - return go_array_to_ffi ((const struct __go_array_type *) descriptor); - case GO_SLICE: - return go_slice_to_ffi ((const struct __go_slice_type *) descriptor); - case GO_STRUCT: - return go_struct_to_ffi ((const struct __go_struct_type *) descriptor); - case GO_STRING: - return go_string_to_ffi (); - case GO_INTERFACE: - return go_interface_to_ffi (); - case GO_CHAN: - case GO_FUNC: - case GO_MAP: - case GO_PTR: - case GO_UNSAFE_POINTER: - /* These types are always pointers, and for FFI purposes nothing - else matters. */ - return &ffi_type_pointer; - default: - abort (); - } -} - -/* Return the return type for a function, given the number of out - parameters and their types. */ - -static ffi_type * -go_func_return_ffi (const struct __go_func_type *func) -{ - int count; - const struct __go_type_descriptor **types; - ffi_type *ret; - int i; - - count = func->__out.__count; - if (count == 0) - return &ffi_type_void; - - types = (const struct __go_type_descriptor **) func->__out.__values; - - if (count == 1) - { - -#if defined (__i386__) && !defined (__x86_64__) - /* FFI does not support complex types. On 32-bit x86, a - complex64 will be returned in %eax/%edx. We normally tell - FFI that a complex64 is a struct of two floats. On 32-bit - x86 a struct of two floats is returned via a hidden first - pointer parameter. Fortunately we can make everything work - by pretending that complex64 is int64. */ - if ((types[0]->__code & GO_CODE_MASK) == GO_COMPLEX64) - return &ffi_type_sint64; -#endif - - return go_type_to_ffi (types[0]); - } - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - ret->elements = (ffi_type **) __go_alloc ((count + 1) * sizeof (ffi_type *)); - for (i = 0; i < count; ++i) - ret->elements[i] = go_type_to_ffi (types[i]); - ret->elements[count] = NULL; - return ret; -} - -/* Build an ffi_cif structure for a function described by a - __go_func_type structure. */ - -static void -go_func_to_cif (const struct __go_func_type *func, _Bool is_interface, - _Bool is_method, ffi_cif *cif) -{ - int num_params; - const struct __go_type_descriptor **in_types; - size_t num_args; - ffi_type **args; - int off; - int i; - ffi_type *rettype; - ffi_status status; - - num_params = func->__in.__count; - in_types = ((const struct __go_type_descriptor **) - func->__in.__values); - - num_args = num_params + (is_interface ? 1 : 0); - args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *)); - i = 0; - off = 0; - if (is_interface) - { - args[0] = &ffi_type_pointer; - off = 1; - } - else if (is_method) - { - args[0] = &ffi_type_pointer; - i = 1; - } - for (; i < num_params; ++i) - args[i + off] = go_type_to_ffi (in_types[i]); - - rettype = go_func_return_ffi (func); - - status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, num_args, rettype, args); - __go_assert (status == FFI_OK); -} - /* Get the total size required for the result parameters of a function. */ @@ -532,7 +217,7 @@ reflect_call (const struct __go_func_type *func_type, FuncVal *func_val, unsigned char *call_result; __go_assert ((func_type->__common.__code & GO_CODE_MASK) == GO_FUNC); - go_func_to_cif (func_type, is_interface, is_method, &cif); + __go_func_to_cif (func_type, is_interface, is_method, &cif); call_result = (unsigned char *) malloc (go_results_size (func_type)); diff --git a/libgo/runtime/go-traceback.c b/libgo/runtime/go-traceback.c index f397f07..7b33cca 100644 --- a/libgo/runtime/go-traceback.c +++ b/libgo/runtime/go-traceback.c @@ -16,7 +16,7 @@ runtime_traceback () Location locbuf[100]; int32 c; - c = runtime_callers (1, locbuf, nelem (locbuf)); + c = runtime_callers (1, locbuf, nelem (locbuf), false); runtime_printtrace (locbuf, c, true); } diff --git a/libgo/runtime/mprof.goc b/libgo/runtime/mprof.goc index 8bd56ba..d9c220b 100644 --- a/libgo/runtime/mprof.goc +++ b/libgo/runtime/mprof.goc @@ -186,7 +186,7 @@ runtime_MProf_Malloc(void *p, uintptr size) Bucket *b; int32 nstk; - nstk = runtime_callers(1, stk, nelem(stk)); + nstk = runtime_callers(1, stk, nelem(stk), false); runtime_lock(&proflock); b = stkbucket(MProf, size, stk, nstk, true); b->recent_allocs++; @@ -249,7 +249,7 @@ runtime_blockevent(int64 cycles, int32 skip) if(rate <= 0 || (rate > cycles && runtime_fastrand1()%rate > cycles)) return; - nstk = runtime_callers(skip, stk, nelem(stk)); + nstk = runtime_callers(skip, stk, nelem(stk), false); runtime_lock(&proflock); b = stkbucket(BProf, 0, stk, nstk, true); b->count++; @@ -449,7 +449,7 @@ saveg(G *gp, TRecord *r) Location locstk[nelem(r->stk)]; if(gp == runtime_g()) { - n = runtime_callers(0, locstk, nelem(r->stk)); + n = runtime_callers(0, locstk, nelem(r->stk), false); for(i = 0; i < n; i++) r->stk[i] = locstk[i].pc; } diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index 363cc19..4195aff 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -756,7 +756,7 @@ gtraceback(G* gp) traceback = gp->traceback; gp->traceback = nil; traceback->c = runtime_callers(1, traceback->locbuf, - sizeof traceback->locbuf / sizeof traceback->locbuf[0]); + sizeof traceback->locbuf / sizeof traceback->locbuf[0], false); runtime_gogo(traceback->gp); } @@ -766,7 +766,7 @@ mcommoninit(M *mp) // If there is no mcache runtime_callers() will crash, // and we are most likely in sysmon thread so the stack is senseless anyway. if(m->mcache) - runtime_callers(1, mp->createstack, nelem(mp->createstack)); + runtime_callers(1, mp->createstack, nelem(mp->createstack), false); mp->fastrand = 0x49f6428aUL + mp->id + runtime_cputicks(); @@ -2584,7 +2584,7 @@ runtime_sigprof() } if(traceback) { - n = runtime_callers(0, prof.locbuf, nelem(prof.locbuf)); + n = runtime_callers(0, prof.locbuf, nelem(prof.locbuf), false); for(i = 0; i < n; i++) prof.pcbuf[i] = prof.locbuf[i].pc; } diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index 8fc10ff..6650be1 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -609,7 +609,7 @@ void runtime_exitsyscall(void) __asm__ (GOSYM_PREFIX "syscall.Exitsyscall"); G* __go_go(void (*pfn)(void*), void*); void siginit(void); bool __go_sigsend(int32 sig); -int32 runtime_callers(int32, Location*, int32); +int32 runtime_callers(int32, Location*, int32, bool keep_callers); int64 runtime_nanotime(void); // monotonic time int64 runtime_unixnanotime(void); // real time, can skip void runtime_dopanic(int32) __attribute__ ((noreturn)); |