runtime: fix panic/wrapper/recover math

The gp->panicwrap adjustment is just fatally flawed.
Now that there is a Panic.argp field, update that instead.
That can be done on entry only, so that unwinding doesn't
need to worry about undoing anything. The wrappers
emit a few more instructions in the prologue but everything
else in the system gets much simpler.

It also fixes (without trying) a broken test I never checked in.

Fixes #7491.

LGTM=khr
R=khr
CC=dvyukov, golang-codereviews, iant, r
https://golang.org/cl/135490044
diff --git a/test/recover.go b/test/recover.go
index 071be66..6287d65 100644
--- a/test/recover.go
+++ b/test/recover.go
@@ -47,6 +47,7 @@
 		test11reflect1()
 		test11reflect2()
 	}
+	test111()
 	test12()
 	if !interp {
 		test12reflect1()
@@ -77,7 +78,7 @@
 	}
 	v = v2
 	if v == nil {
-		println("missing recover")
+		println("missing recover", x.(int))
 		die() // panic is useless here
 	}
 	if v != x {
@@ -137,7 +138,7 @@
 		mustNotRecover()
 		v := recover()
 		if v == nil {
-			println("missing recover")
+			println("missing recover", x.(int))
 			die()
 		}
 		if v != x {
@@ -406,6 +407,49 @@
 	panic(11)
 }
 
+// tiny receiver, so basic wrapper in i.M()
+type T3deeper struct{}
+
+func (T3deeper) M() {
+	badstate() // difference from T3
+	mustRecoverBody(doubleRecover(), recover(), recover(), 111)
+}
+
+func test111() {
+	var i I = T3deeper{}
+	defer i.M()
+	panic(111)
+}
+
+type Tiny struct{}
+
+func (Tiny) M() {
+	panic(112)
+}
+
+// i.M is a wrapper, and i.M panics.
+//
+// This is a torture test for an old implementation of recover that
+// tried to deal with wrapper functions by doing some argument
+// positioning math on both entry and exit. Doing anything on exit
+// is a problem because sometimes functions exit via panic instead
+// of an ordinary return, so panic would have to know to do the
+// same math when unwinding the stack. It gets complicated fast.
+// This particular test never worked with the old scheme, because
+// panic never did the right unwinding math.
+//
+// The new scheme adjusts Panic.argp on entry to a wrapper.
+// It has no exit work, so if a wrapper is interrupted by a panic,
+// there's no cleanup that panic itself must do.
+// This test just works now.
+func badstate() {
+	defer func() {
+		recover()
+	}()
+	var i I = Tiny{}
+	i.M()
+}
+
 // large receiver, so basic wrapper in i.M()
 type T4 [2]string