9d1e3afb54
The actual stack unwind code is still in C, but the rest of the code, notably all the memory allocation, is now in Go. The names are changed to the names used in the Go 1.7 runtime, but the code is necessarily somewhat different. The __go_makefunc_can_recover function is dropped, as the uses of it were removed in https://golang.org/cl/198770044. Reviewed-on: https://go-review.googlesource.com/33414 From-SVN: r242715
101 lines
2.5 KiB
C
101 lines
2.5 KiB
C
// 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 "runtime.h"
|
|
#include "go-type.h"
|
|
|
|
#ifdef USE_LIBFFI
|
|
|
|
#include "ffi.h"
|
|
|
|
#if FFI_GO_CLOSURES
|
|
#define USE_LIBFFI_CLOSURES
|
|
#endif
|
|
|
|
#endif /* defined(USE_LIBFFI) */
|
|
|
|
/* Declare C functions with the names used to call from Go. */
|
|
|
|
void makeFuncFFI(void *cif, void *impl)
|
|
__asm__ (GOSYM_PREFIX "reflect.makeFuncFFI");
|
|
|
|
#ifdef USE_LIBFFI_CLOSURES
|
|
|
|
/* The function that we pass to ffi_prep_closure_loc. This calls the Go
|
|
function ffiCall with the pointer to the arguments, the results area,
|
|
and the closure structure. */
|
|
|
|
extern void FFICallbackGo(void *result, void **args, ffi_go_closure *closure)
|
|
__asm__ (GOSYM_PREFIX "reflect.FFICallbackGo");
|
|
|
|
extern void makefuncfficanrecover(Slice)
|
|
__asm__ (GOSYM_PREFIX "runtime.makefuncfficanrecover");
|
|
|
|
extern void makefuncreturning(void)
|
|
__asm__ (GOSYM_PREFIX "runtime.makefuncreturning");
|
|
|
|
static void ffi_callback (ffi_cif *, void *, void **, void *)
|
|
__asm__ ("reflect.ffi_callback");
|
|
|
|
static void
|
|
ffi_callback (ffi_cif* cif __attribute__ ((unused)), void *results,
|
|
void **args, void *closure)
|
|
{
|
|
Location locs[8];
|
|
int n;
|
|
int i;
|
|
|
|
/* This function is called from some series of FFI closure functions
|
|
called by a Go function. We want to see whether the caller of
|
|
the closure functions can recover. Look up the stack and skip
|
|
the FFI functions. */
|
|
n = runtime_callers (1, &locs[0], sizeof locs / sizeof locs[0], true);
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
const byte *name;
|
|
|
|
if (locs[i].function.len == 0)
|
|
continue;
|
|
if (locs[i].function.len < 4)
|
|
break;
|
|
name = locs[i].function.str;
|
|
if (name[0] != 'f' || name[1] != 'f' || name[2] != 'i' || name[3] != '_')
|
|
break;
|
|
}
|
|
if (i < n)
|
|
{
|
|
Slice s;
|
|
|
|
s.__values = (void *) &locs[i];
|
|
s.__count = n - i;
|
|
s.__capacity = n - i;
|
|
makefuncfficanrecover (s);
|
|
}
|
|
|
|
FFICallbackGo(results, args, closure);
|
|
|
|
if (i < n)
|
|
makefuncreturning ();
|
|
}
|
|
|
|
/* Allocate an FFI closure and arrange to call ffi_callback. */
|
|
|
|
void
|
|
makeFuncFFI(void *cif, void *impl)
|
|
{
|
|
ffi_prep_go_closure(impl, (ffi_cif*)cif, ffi_callback);
|
|
}
|
|
|
|
#else /* !defined(USE_LIBFFI_CLOSURES) */
|
|
|
|
void
|
|
makeFuncFFI(void *cif __attribute__ ((unused)),
|
|
void *impl __attribute__ ((unused)))
|
|
{
|
|
runtime_panicstring ("libgo built without FFI does not support "
|
|
"reflect.MakeFunc");
|
|
}
|
|
|
|
#endif
|