// create a new goroutine to start program
PUSHL $runtime·main·f(SB) // entry
PUSHL $0 // arg size
- ARGSIZE(8)
CALL runtime·newproc(SB)
- ARGSIZE(-1)
POPL AX
POPL AX
// lives at the bottom of the G stack from the one that lives
// at the top of the M stack because the one at the top of
// the M stack terminates the stack walk (see topofstack()).
-TEXT runtime·switchtoM(SB), NOSPLIT, $0-4
+TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
RET
// func onM_signalok(fn func())
MOVL BX, SP
// call target function
- ARGSIZE(0)
MOVL DI, DX
MOVL 0(DI), DI
CALL DI
RET
TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12
+ GO_ARGS
MOVL fn+0(FP), AX
MOVL arg+4(FP), BX
CALL asmcgocall<>(SB)
// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
// See cgocall.c for more details.
TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$12-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+
// If g is nil, Go did not create the current thread.
// Call needm to obtain one for temporary use.
// In this case, we're running on the thread stack, so there's
MOVQ $runtime·main·f(SB), BP // entry
PUSHQ BP
PUSHQ $0 // arg size
- ARGSIZE(16)
CALL runtime·newproc(SB)
- ARGSIZE(-1)
POPQ AX
POPQ AX
MOVQ SI, g(CX) // g = m->g0
MOVQ (g_sched+gobuf_sp)(SI), SP // sp = m->g0->sched.sp
PUSHQ AX
- ARGSIZE(8)
MOVQ DI, DX
MOVQ 0(DI), DI
CALL DI
// lives at the bottom of the G stack from the one that lives
// at the top of the M stack because the one at the top of
// the M stack terminates the stack walk (see topofstack()).
-TEXT runtime·switchtoM(SB), NOSPLIT, $0-8
+TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
RET
// func onM_signalok(fn func())
MOVQ BX, SP
// call target function
- ARGSIZE(0)
MOVQ DI, DX
MOVQ 0(DI), DI
CALL DI
RET
TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-20
+ GO_ARGS
MOVQ fn+0(FP), AX
MOVQ arg+8(FP), BX
CALL asmcgocall<>(SB)
// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
// See cgocall.c for more details.
TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$8-24
+ GO_ARGS
+ NO_LOCAL_POINTERS
+
// If g is nil, Go did not create the current thread.
// Call needm to obtain one m for temporary use.
// In this case, we're running on the thread stack, so there's
MOVL $runtime·main·f(SB), AX // entry
MOVL $0, 0(SP)
MOVL AX, 4(SP)
- ARGSIZE(8)
CALL runtime·newproc(SB)
- ARGSIZE(-1)
// start this M
CALL runtime·mstart(SB)
MOVL SI, g(CX) // g = m->g0
MOVL (g_sched+gobuf_sp)(SI), SP // sp = m->g0->sched.sp
PUSHQ AX
- ARGSIZE(8)
MOVL DI, DX
MOVL 0(DI), DI
CALL DI
// lives at the bottom of the G stack from the one that lives
// at the top of the M stack because the one at the top of
// the M stack terminates the stack walk (see topofstack()).
-TEXT runtime·switchtoM(SB), NOSPLIT, $0-4
+TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
RET
// func onM_signalok(fn func())
MOVL (g_sched+gobuf_sp)(DX), SP
// call target function
- ARGSIZE(0)
MOVL DI, DX
MOVL 0(DI), DI
CALL DI
MOVW.W R0, -4(R13)
MOVW $0, R0
MOVW.W R0, -4(R13) // push $0 as guard
- ARGSIZE(12)
BL runtime·newproc(SB)
- ARGSIZE(-1)
MOVW $12(R13), R13 // pop args and LR
// start this M
// lives at the bottom of the G stack from the one that lives
// at the top of the M stack because the one at the top of
// the M stack terminates the stack walk (see topofstack()).
-TEXT runtime·switchtoM(SB),NOSPLIT,$0-4
+TEXT runtime·switchtoM(SB),NOSPLIT,$0-0
MOVW $0, R0
BL (R0) // clobber lr to ensure push {lr} is kept
RET
MOVW R3, SP
// call target function
- ARGSIZE(0)
MOVW R0, R7
MOVW 0(R0), R0
BL (R0)
RET
TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12
+ GO_ARGS
MOVW fn+0(FP), R1
MOVW arg+4(FP), R0
BL asmcgocall<>(SB)
// cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize)
// See cgocall.c for more details.
TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+
// Load m and g from thread-local storage.
MOVB runtime·iscgo(SB), R0
CMP $0, R0
enum {
Debug = 0,
ConcurrentSweep = 1,
- PreciseScan = 1,
WorkbufSize = 4*1024,
FinBlockSize = 4*1024,
ptrmask = nil; // use GC bitmap for pointer info
scanobj:
- if(!PreciseScan) {
- if(ptrmask == nil) {
- // Heap obj, obtain real size.
- if(!runtime·mlookup(b, &p, &n, nil))
- continue; // not an allocated obj
- if(b != p)
- runtime·throw("bad heap object");
- }
- ptrmask = ScanConservatively;
- }
// Find bits of the beginning of the object.
if(ptrmask == nil) {
off = (uintptr*)b - (uintptr*)arena_start;
Func *f;
StackMap *stackmap;
BitVector bv;
- uintptr size;
+ uintptr size, minsize;
uintptr targetpc;
int32 pcdata;
}
// Scan local variables if stack frame has been allocated.
- // Use pointer information if known.
- stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
- if(stackmap == nil) {
- // No locals information, scan everything.
- size = frame->varp - frame->sp;
- if(Debug > 2)
- runtime·printf("frame %s unsized locals %p+%p\n", runtime·funcname(f), (byte*)(frame->varp-size), size);
- scanblock((byte*)(frame->varp - size), size, ScanConservatively);
- } else if(stackmap->n < 0) {
- // Locals size information, scan just the locals.
- size = -stackmap->n;
- if(Debug > 2)
- runtime·printf("frame %s conservative locals %p+%p\n", runtime·funcname(f), (byte*)(frame->varp-size), size);
- scanblock((byte*)(frame->varp - size), size, ScanConservatively);
- } else if(stackmap->n > 0) {
+ size = frame->varp - frame->sp;
+ minsize = 0;
+ if(thechar != '6' && thechar != '8')
+ minsize = sizeof(uintptr);
+ if(size > minsize) {
+ stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
+ if(stackmap == nil || stackmap->n <= 0) {
+ runtime·printf("runtime: frame %s untyped locals %p+%p\n", runtime·funcname(f), (byte*)(frame->varp-size), size);
+ runtime·throw("missing stackmap");
+ }
+
// Locals bitmap information, scan just the pointers in locals.
if(pcdata < 0 || pcdata >= stackmap->n) {
// don't know where we are
- runtime·printf("pcdata is %d and %d stack map entries for %s (targetpc=%p)\n",
+ runtime·printf("runtime: pcdata is %d and %d locals stack map entries for %s (targetpc=%p)\n",
pcdata, stackmap->n, runtime·funcname(f), targetpc);
runtime·throw("scanframe: bad symbol table");
}
}
// Scan arguments.
- // Use pointer information if known.
- if(frame->argmap != nil) {
- bv = *frame->argmap;
- scanblock((byte*)frame->argp, bv.n/BitsPerPointer*PtrSize, bv.bytedata);
- } else if((stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps)) != nil) {
- bv = runtime·stackmapdata(stackmap, pcdata);
- scanblock((byte*)frame->argp, bv.n/BitsPerPointer*PtrSize, bv.bytedata);
- } else {
- if(Debug > 2)
- runtime·printf("frame %s conservative args %p+%p\n", runtime·funcname(f), frame->argp, (uintptr)frame->arglen);
- scanblock((byte*)frame->argp, frame->arglen, ScanConservatively);
- }
- return true;
+ if(frame->arglen > 0) {
+ if(frame->argmap != nil)
+ bv = *frame->argmap;
+ else {
+ stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
+ if(stackmap == nil || stackmap->n <= 0) {
+ runtime·printf("runtime: frame %s untyped args %p+%p\n", runtime·funcname(f), frame->argp, (uintptr)frame->arglen);
+ runtime·throw("missing stackmap");
+ }
+ if(pcdata < 0 || pcdata >= stackmap->n) {
+ // don't know where we are
+ runtime·printf("runtime: pcdata is %d and %d args stack map entries for %s (targetpc=%p)\n",
+ pcdata, stackmap->n, runtime·funcname(f), targetpc);
+ runtime·throw("scanframe: bad symbol table");
+ }
+ bv = runtime·stackmapdata(stackmap, pcdata);
+ }
+ scanblock((byte*)frame->argp, bv.n/BitsPerPointer*PtrSize, bv.bytedata);
+ }
+ return true;
}
static void
void runtime·symtabinit(void);
Func* runtime·findfunc(uintptr);
int32 runtime·funcline(Func*, uintptr, String*);
-int32 runtime·funcarglen(Func*, uintptr);
int32 runtime·funcspdelta(Func*, uintptr);
int8* runtime·funcname(Func*);
int32 runtime·pcdatavalue(Func*, int32, uintptr);
return pcvalue(f, off, targetpc, true)
}
-func funcarglen(f *_func, targetpc uintptr) int32 {
- if targetpc == f.entry {
- return 0
- }
- return pcdatavalue(f, _PCDATA_ArgSize, targetpc-_PCQuantum)
-}
-
func funcdata(f *_func, i int32) unsafe.Pointer {
if i < 0 || i >= f.nfuncdata {
return nil
if usesLR {
frame.argp += ptrSize
}
- 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 {
- i := funcarglen(flr, frame.lr)
- if i >= 0 {
- frame.arglen = uintptr(i)
- } else {
- var tmp string
- if flr != nil {
- tmp = gofuncname(flr)
- } else {
- tmp = "?"
+ frame.arglen = uintptr(f.args)
+ if callback != nil && f.args == _ArgsSizeUnknown {
+ // Extract argument bitmaps for reflect stubs from the calls they made to reflect.
+ switch gofuncname(f) {
+ case "reflect.makeFuncStub", "reflect.methodValueCall":
+ arg0 := frame.sp
+ if usesLR {
+ arg0 += ptrSize
}
- print("runtime: unknown argument frame size for ", gofuncname(f), " called from ", hex(frame.lr), " [", tmp, "]\n")
- if callback != nil {
- gothrow("invalid stack")
+ fn := *(**[2]uintptr)(unsafe.Pointer(arg0))
+ if fn[0] != f.entry {
+ print("runtime: confused by ", gofuncname(f), "\n")
+ gothrow("reflect mismatch")
}
- frame.arglen = 0
+ bv := (*bitvector)(unsafe.Pointer(fn[1]))
+ frame.arglen = uintptr(bv.n / 2 * ptrSize)
+ frame.argmap = bv
}
}
}