From 512261e50e90c7fb064b825c7fab67e95a3142ab Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 18 Feb 2016 11:04:05 -0800 Subject: runtime: skip cgo check for non-pointer slice elements Fixes #14387. Change-Id: Icc98be80f549c5e1f55c5e693bfea97b456a6c41 Reviewed-on: https://go-review.googlesource.com/19621 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick Reviewed-on: https://go-review.googlesource.com/22036 Reviewed-by: Ian Lance Taylor --- src/runtime/cgocall.go | 3 +++ src/runtime/crash_cgo_test.go | 31 +++++++++++++++++++++++++++++++ src/runtime/testdata/testprogcgo/cgo.go | 10 ++++++++++ 3 files changed, 44 insertions(+) diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 66115fd8b4..fef8add46f 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -463,6 +463,9 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) { if !top { panic(errorString(msg)) } + if st.elem.kind&kindNoPointers != 0 { + return + } for i := 0; i < s.cap; i++ { cgoCheckArg(st.elem, p, true, false, msg) p = add(p, st.elem.size) diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index d7b367f941..7685582aa8 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -7,10 +7,12 @@ package runtime_test import ( + "internal/testenv" "os/exec" "runtime" "strings" "testing" + "time" ) func TestCgoCrashHandler(t *testing.T) { @@ -147,3 +149,32 @@ func TestEnsureDropM(t *testing.T) { t.Errorf("expected %q, got %v", want, got) } } + +// Test for issue 14387. +// Test that the program that doesn't need any cgo pointer checking +// takes about the same amount of time with it as without it. +func TestCgoCheckBytes(t *testing.T) { + // Make sure we don't count the build time as part of the run time. + testenv.MustHaveGoBuild(t) + exe, err := buildTestProg(t, "testprogcgo") + if err != nil { + t.Fatal(err) + } + + cmd := testEnv(exec.Command(exe, "CgoCheckBytes")) + + start := time.Now() + cmd.Run() + d1 := time.Since(start) + + cmd = testEnv(exec.Command(exe, "CgoCheckBytes")) + cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0") + + start = time.Now() + cmd.Run() + d2 := time.Since(start) + + if d2*10 < d1 { + t.Errorf("cgo check too slow: got %v, expected at most %v", d1, d2*10) + } +} diff --git a/src/runtime/testdata/testprogcgo/cgo.go b/src/runtime/testdata/testprogcgo/cgo.go index cf1af8268c..5d2550dbb0 100644 --- a/src/runtime/testdata/testprogcgo/cgo.go +++ b/src/runtime/testdata/testprogcgo/cgo.go @@ -6,17 +6,20 @@ package main /* void foo1(void) {} +void foo2(void* p) {} */ import "C" import ( "fmt" "runtime" "time" + "unsafe" ) func init() { register("CgoSignalDeadlock", CgoSignalDeadlock) register("CgoTraceback", CgoTraceback) + register("CgoCheckBytes", CgoCheckBytes) } func CgoSignalDeadlock() { @@ -78,3 +81,10 @@ func CgoTraceback() { runtime.Stack(buf, true) fmt.Printf("OK\n") } + +func CgoCheckBytes() { + b := make([]byte, 1e6) + for i := 0; i < 1e3; i++ { + C.foo2(unsafe.Pointer(&b[0])) + } +} -- cgit v1.2.3-54-g00ecf