aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/malloc.h1
-rw-r--r--src/runtime/mgc0.c6
-rw-r--r--src/runtime/runtime.h2
-rw-r--r--src/runtime/stack.c14
-rw-r--r--src/runtime/traceback.go16
5 files changed, 31 insertions, 8 deletions
diff --git a/src/runtime/malloc.h b/src/runtime/malloc.h
index 5441691940..b6856768db 100644
--- a/src/runtime/malloc.h
+++ b/src/runtime/malloc.h
@@ -586,7 +586,6 @@ void runtime·queuefinalizer(byte *p, FuncVal *fn, uintptr nret, Type *fint, Ptr
bool runtime·freespecial(Special *s, void *p, uintptr size, bool freed);
// Information from the compiler about the layout of stack frames.
-typedef struct BitVector BitVector;
struct BitVector
{
int32 n; // # of bits
diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c
index da0455d923..af0b6285a3 100644
--- a/src/runtime/mgc0.c
+++ b/src/runtime/mgc0.c
@@ -673,8 +673,10 @@ scanframe(Stkframe *frame, void *unused)
// Scan arguments.
// Use pointer information if known.
- stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
- if(stackmap != nil) {
+ if(frame->argmap != nil) {
+ bv = *frame->argmap;
+ scanblock((byte*)frame->argp, bv.n/BitsPerPointer*PtrSize, (byte*)bv.data);
+ } else if((stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps)) != nil) {
bv = runtime·stackmapdata(stackmap, pcdata);
scanblock((byte*)frame->argp, bv.n/BitsPerPointer*PtrSize, (byte*)bv.data);
} else {
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index 01923c61e0..6300b83c97 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -666,6 +666,7 @@ struct Panic
* stack traces
*/
typedef struct Stkframe Stkframe;
+typedef struct BitVector BitVector;
struct Stkframe
{
Func* fn; // function being run
@@ -677,6 +678,7 @@ struct Stkframe
uintptr varp; // top of local variables
uintptr argp; // pointer to function arguments
uintptr arglen; // number of bytes at argp
+ BitVector* argmap; // force use of this argmap
};
intgo runtime·gentraceback(uintptr, uintptr, uintptr, G*, intgo, uintptr*, intgo, bool(**)(Stkframe*, void*), void*, bool);
diff --git a/src/runtime/stack.c b/src/runtime/stack.c
index cc2857ac81..53ad90a5de 100644
--- a/src/runtime/stack.c
+++ b/src/runtime/stack.c
@@ -481,12 +481,16 @@ adjustframe(Stkframe *frame, void *arg)
}
// adjust inargs and outargs
if(frame->arglen != 0) {
- stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
- if(stackmap == nil) {
- runtime·printf("size %d\n", (int32)frame->arglen);
- runtime·throw("no arg info");
+ if(frame->argmap != nil) {
+ bv = *frame->argmap;
+ } else {
+ stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
+ if(stackmap == nil) {
+ runtime·printf("size %d\n", (int32)frame->arglen);
+ runtime·throw("no arg info");
+ }
+ bv = runtime·stackmapdata(stackmap, pcdata);
}
- bv = runtime·stackmapdata(stackmap, pcdata);
if(StackDebug >= 3)
runtime·printf(" args\n");
adjustpointers((byte**)frame->argp, &bv, adjinfo, nil);
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index ca3b862102..84cb08c9e1 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -189,6 +189,21 @@ func gentraceback(pc0 uintptr, sp0 uintptr, lr0 uintptr, gp *g, skip int, pcbuf
}
if f.args != _ArgsSizeUnknown {
frame.arglen = uintptr(f.args)
+ } else if callback != nil && (gofuncname(f) == "reflect.makeFuncStub" || gofuncname(f) == "reflect.methodValueCall") {
+ // NOTE: Two calls to gofuncname on line above will be
+ // collapsed to one when we pull out all the imprecise fallback code.
+ arg0 := frame.sp
+ if usesLR {
+ arg0 += ptrSize
+ }
+ fn := *(**[2]uintptr)(unsafe.Pointer(arg0))
+ if fn[0] != f.entry {
+ print("runtime: confused by ", gofuncname(f), "\n")
+ gothrow("reflect mismatch")
+ }
+ bv := (*bitvector)(unsafe.Pointer(fn[1]))
+ frame.arglen = uintptr(bv.n / 2 * ptrSize)
+ frame.argmap = bv
} else if flr == nil {
frame.arglen = 0
} else {
@@ -332,6 +347,7 @@ func gentraceback(pc0 uintptr, sp0 uintptr, lr0 uintptr, gp *g, skip int, pcbuf
frame.lr = 0
frame.sp = frame.fp
frame.fp = 0
+ frame.argmap = nil
// On link register architectures, sighandler saves the LR on stack
// before faking a call to sigpanic.