]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: more cgocallback_gofunc work
authorRuss Cox <rsc@golang.org>
Wed, 24 Jul 2013 13:01:57 +0000 (09:01 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 24 Jul 2013 13:01:57 +0000 (09:01 -0400)
Debugging the Windows breakage I noticed that SEH
only exists on 386, so we can balance the two stacks
a little more on amd64 and reclaim another word.

Now we're down to just one word consumed by
cgocallback_gofunc, having reclaimed 25% of the
overall budget (4 words out of 16).

Separately, fix windows/386 - the SEH must be on the
m0 stack, as must the saved SP, so we are forced to have
a three-word frame for 386. It matters much less for
386, because there 128 bytes gives 32 words to use.

R=dvyukov, alex.brainman
CC=golang-dev
https://golang.org/cl/11551044

src/pkg/runtime/asm_386.s
src/pkg/runtime/asm_amd64.s
src/pkg/runtime/cgocall.c
src/pkg/runtime/proc.c

index b66879935781bf642119bd804227763303a2dd34..79fb4e9f961df67bce3776b557b69d2c4e11c809 100644 (file)
@@ -524,7 +524,7 @@ TEXT runtime·cgocallback(SB),7,$12-12
 
 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
 // See cgocall.c for more details.
-TEXT runtime·cgocallback_gofunc(SB),7,$8-12
+TEXT runtime·cgocallback_gofunc(SB),7,$12-12
        // If m 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
@@ -537,12 +537,14 @@ TEXT runtime·cgocallback_gofunc(SB),7,$8-12
        JEQ     2(PC)
 #endif
        MOVL    m(CX), BP
-       MOVL    BP, 4(SP)
+       MOVL    BP, DX // saved copy of oldm
        CMPL    BP, $0
        JNE     havem
 needm:
+       MOVL    DX, 0(SP)
        MOVL    $runtime·needm(SB), AX
        CALL    AX
+       MOVL    0(SP), DX
        get_tls(CX)
        MOVL    m(CX), BP
 
@@ -552,6 +554,7 @@ havem:
        // Save current sp in m->g0->sched.sp in preparation for
        // switch back to m->curg stack.
        // NOTE: unwindm knows that the saved g->sched.sp is at 0(SP).
+       // On Windows, the SEH is at 4(SP) and 8(SP).
        MOVL    m_g0(BP), SI
        MOVL    (g_sched+gobuf_sp)(SI), AX
        MOVL    AX, 0(SP)
@@ -571,22 +574,24 @@ havem:
        // so that the traceback will seamlessly trace back into
        // the earlier calls.
        //
-       // In the new goroutine, 0(SP) and 4(SP) are unused except
-       // on Windows, where they are the SEH block.
+       // In the new goroutine, 0(SP) holds the saved oldm (DX) register.
+       // 4(SP) and 8(SP) are unused.
        MOVL    m_curg(BP), SI
        MOVL    SI, g(CX)
        MOVL    (g_sched+gobuf_sp)(SI), DI // prepare stack as DI
        MOVL    (g_sched+gobuf_pc)(SI), BP
        MOVL    BP, -4(DI)
-       LEAL    -(4+8)(DI), SP
+       LEAL    -(4+12)(DI), SP
+       MOVL    DX, 0(SP)
        CALL    runtime·cgocallbackg(SB)
+       MOVL    0(SP), DX
 
        // Restore g->sched (== m->curg->sched) from saved values.
        get_tls(CX)
        MOVL    g(CX), SI
-       MOVL    8(SP), BP
+       MOVL    12(SP), BP
        MOVL    BP, (g_sched+gobuf_pc)(SI)
-       LEAL    (8+4)(SP), DI
+       LEAL    (12+4)(SP), DI
        MOVL    DI, (g_sched+gobuf_sp)(SI)
 
        // Switch back to m->g0's stack and restore m->g0->sched.sp.
@@ -601,8 +606,7 @@ havem:
        
        // If the m on entry was nil, we called needm above to borrow an m
        // for the duration of the call. Since the call is over, return it with dropm.
-       MOVL    8(SP), BP
-       CMPL    BP, $0
+       CMPL    DX, $0
        JNE 3(PC)
        MOVL    $runtime·dropm(SB), AX
        CALL    AX
index 96af61265c963efd0899e7f271ae22d2a4a14793..e7cef0232960dface3bf3fef697070a2332a871a 100644 (file)
@@ -563,7 +563,7 @@ TEXT runtime·cgocallback(SB),7,$24-24
 
 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
 // See cgocall.c for more details.
-TEXT runtime·cgocallback_gofunc(SB),7,$16-24
+TEXT runtime·cgocallback_gofunc(SB),7,$8-24
        // If m 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
@@ -576,12 +576,14 @@ TEXT runtime·cgocallback_gofunc(SB),7,$16-24
        JEQ     2(PC)
 #endif
        MOVQ    m(CX), BP
-       MOVQ    BP, 8(SP)
+       MOVQ    BP, R8 // holds oldm until end of function
        CMPQ    BP, $0
        JNE     havem
 needm:
+       MOVQ    R8, 0(SP)
        MOVQ    $runtime·needm(SB), AX
        CALL    AX
+       MOVQ    0(SP), R8
        get_tls(CX)
        MOVQ    m(CX), BP
 
@@ -610,22 +612,23 @@ havem:
        // so that the traceback will seamlessly trace back into
        // the earlier calls.
        //
-       // In the new goroutine, 0(SP) and 8(SP) are unused except
-       // on Windows, where they are the SEH block.
+       // In the new goroutine, 0(SP) holds the saved R8.
        MOVQ    m_curg(BP), SI
        MOVQ    SI, g(CX)
        MOVQ    (g_sched+gobuf_sp)(SI), DI  // prepare stack as DI
        MOVQ    (g_sched+gobuf_pc)(SI), BP
        MOVQ    BP, -8(DI)
-       LEAQ    -(8+16)(DI), SP
+       LEAQ    -(8+8)(DI), SP
+       MOVQ    R8, 0(SP)
        CALL    runtime·cgocallbackg(SB)
+       MOVQ    0(SP), R8
 
        // Restore g->sched (== m->curg->sched) from saved values.
        get_tls(CX)
        MOVQ    g(CX), SI
-       MOVQ    16(SP), BP
+       MOVQ    8(SP), BP
        MOVQ    BP, (g_sched+gobuf_pc)(SI)
-       LEAQ    (16+8)(SP), DI
+       LEAQ    (8+8)(SP), DI
        MOVQ    DI, (g_sched+gobuf_sp)(SI)
 
        // Switch back to m->g0's stack and restore m->g0->sched.sp.
@@ -640,8 +643,7 @@ havem:
        
        // If the m on entry was nil, we called needm above to borrow an m
        // for the duration of the call. Since the call is over, return it with dropm.
-       MOVQ    8(SP), BP
-       CMPQ    BP, $0
+       CMPQ    R8, $0
        JNE 3(PC)
        MOVQ    $runtime·dropm(SB), AX
        CALL    AX
index a624509cfef2cf20d01e943430d48eea9ff81fbf..888e09c56160f754fe281289c531773140a569fa 100644 (file)
@@ -236,7 +236,24 @@ struct CallbackArgs
        uintptr argsize;
 };
 
-#define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+(3+(thechar=='5'))*sizeof(void*))
+// Location of callback arguments depends on stack frame layout
+// and size of stack frame of cgocallback_gofunc.
+
+// On arm, stack frame is two words and there's a saved LR between
+// SP and the stack frame and between the stack frame and the arguments.
+#ifdef GOARCH_arm
+#define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*))
+#endif
+
+// On amd64, stack frame is one word, plus caller PC.
+#ifdef GOARCH_amd64
+#define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+2*sizeof(void*))
+#endif
+
+// On 386, stack frame is three words, plus caller PC.
+#ifdef GOARCH_386
+#define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*))
+#endif
 
 void
 runtime·cgocallbackg(void)
index 3ae9fe7273cb3a654d1e199385b526accae3f617..9626d7980c43d739c1aaf1180cf88b57e77db0b6 100644 (file)
@@ -499,7 +499,11 @@ runtime·mstart(void)
        runtime·gosave(&m->g0->sched);
        m->g0->sched.pc = (uintptr)-1;  // make sure it is never used
        m->g0->stackguard = m->g0->stackguard0;  // cgo sets only stackguard0, copy it to stackguard
+#ifdef GOOS_windows
+#ifdef GOARCH_386
        m->seh = &seh;
+#endif
+#endif
        runtime·asminit();
        runtime·minit();
 
@@ -650,11 +654,15 @@ runtime·needm(byte x)
        g->stackguard = (uintptr)(&x - 32*1024);
        g->stackguard0 = g->stackguard;
 
+#ifdef GOOS_windows
+#ifdef GOARCH_386
        // On windows/386, we need to put an SEH frame (two words)
        // somewhere on the current stack. We are called from cgocallback_gofunc
        // and we know that it will leave two unused words below m->curg->sched.sp.
        // Use those.
-       m->seh = (SEH*)((uintptr*)m->curg->sched.sp - 3);
+       m->seh = (SEH*)((uintptr*)&x + 1);
+#endif
+#endif
 
        // Initialize this thread to use the m.
        runtime·asminit();
@@ -734,7 +742,12 @@ runtime·dropm(void)
 
        // Undo whatever initialization minit did during needm.
        runtime·unminit();
+
+#ifdef GOOS_windows
+#ifdef GOARCH_386
        m->seh = nil;  // reset dangling typed pointer
+#endif
+#endif
 
        // Clear m and g, and return m to the extra list.
        // After the call to setmg we can only call nosplit functions.