]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.2] cmd/5l, runtime: fix divide for profiling tracebacks on ARM
authorAndrew Gerrand <adg@golang.org>
Fri, 1 Nov 2013 00:34:40 +0000 (11:34 +1100)
committerAndrew Gerrand <adg@golang.org>
Fri, 1 Nov 2013 00:34:40 +0000 (11:34 +1100)
««« CL 19910044 / 9eb64f5ef3a6
cmd/5l, runtime: fix divide for profiling tracebacks on ARM

Two bugs:
1. The first iteration of the traceback always uses LR when provided,
which it is (only) during a profiling signal, but in fact LR is correct
only if the stack frame has not been allocated yet. Otherwise an
intervening call may have changed LR, and the saved copy in the stack
frame should be used. Fix in traceback_arm.c.

2. The division runtime call adds 8 bytes to the stack. In order to
keep the traceback routines happy, it must copy the saved LR into
the new 0(SP). Change

        SUB $8, SP

into

        MOVW    0(SP), R11 // r11 is temporary, for use by linker
        MOVW.W  R11, -8(SP)

to update SP and 0(SP) atomically, so that the traceback always
sees a saved LR at 0(SP).

Fixes #6681.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/19910044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20170048

src/cmd/5l/noop.c
src/pkg/runtime/pprof/pprof_test.go
src/pkg/runtime/traceback_arm.c

index fb70599b514951ec60533faea0f6cf9339c59fa4..305ed684ee4d2c0a09aaad78060293abaad5a5ec 100644 (file)
@@ -472,14 +472,27 @@ noops(void)
                                p->to.reg = REGSP;
                                p->spadj = -8;
        
-                               /* SUB $8,SP */
-                               q1->as = ASUB;
-                               q1->from.type = D_CONST;
-                               q1->from.offset = 8;
-                               q1->from.reg = NREG;
+                               /* Keep saved LR at 0(SP) after SP change. */
+                               /* MOVW 0(SP), REGTMP; MOVW REGTMP, -8!(SP) */
+                               /* TODO: Remove SP adjustments; see issue 6699. */
+                               q1->as = AMOVW;
+                               q1->from.type = D_OREG;
+                               q1->from.reg = REGSP;
+                               q1->from.offset = 0;
                                q1->reg = NREG;
                                q1->to.type = D_REG;
+                               q1->to.reg = REGTMP;
+
+                               /* SUB $8,SP */
+                               q1 = appendp(q1);
+                               q1->as = AMOVW;
+                               q1->from.type = D_REG;
+                               q1->from.reg = REGTMP;
+                               q1->reg = NREG;
+                               q1->to.type = D_OREG;
                                q1->to.reg = REGSP;
+                               q1->to.offset = -8;
+                               q1->scond |= C_WBIT;
                                q1->spadj = 8;
        
                                break;
index f1fc5faec689d050fc7124a8f0621801f36af4f8..eb76b93c44cfe2e584f28d49eec470f7f550fd4f 100644 (file)
@@ -8,6 +8,7 @@ import (
        "bytes"
        "fmt"
        "hash/crc32"
+       "math/big"
        "os/exec"
        "regexp"
        "runtime"
@@ -123,6 +124,10 @@ func testCPUProfile(t *testing.T, need []string, f func()) {
                }
        })
 
+       if len(need) == 0 {
+               return
+       }
+
        var total uintptr
        for i, name := range need {
                total += have[i]
@@ -237,6 +242,26 @@ func TestGoroutineSwitch(t *testing.T) {
        }
 }
 
+// Test that profiling of division operations is okay, especially on ARM. See issue 6681.
+func TestMathBigDivide(t *testing.T) {
+       testCPUProfile(t, nil, func() {
+               t := time.After(5 * time.Second)
+               pi := new(big.Int)
+               for {
+                       for i := 0; i < 100; i++ {
+                               n := big.NewInt(2646693125139304345)
+                               d := big.NewInt(842468587426513207)
+                               pi.Div(n, d)
+                       }
+                       select {
+                       case <-t:
+                               return
+                       default:
+                       }
+               }
+       })
+}
+
 // Operating systems that are expected to fail the tests. See issue 6047.
 var badOS = map[string]bool{
        "darwin":  true,
index 02586f036bba6dad9d60a27fab63b8b14ea5a510..341aa20588010d7a3a0574dce69732a431084e7b 100644 (file)
@@ -84,7 +84,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
                        frame.lr = 0;
                        flr = nil;
                } else {
-                       if(frame.lr == 0)
+                       if((n == 0 && frame.sp < frame.fp) || frame.lr == 0)
                                frame.lr = *(uintptr*)frame.sp;
                        flr = runtime·findfunc(frame.lr);
                        if(flr == nil) {