---
doc/go1.16.html | 9 ------
src/cmd/compile/internal/gc/reflect.go | 3 +-
src/internal/reflectlite/type.go | 35 +++++++---------------
src/internal/reflectlite/value.go | 4 +--
src/reflect/all_test.go | 18 ++++-------
src/reflect/type.go | 55 ++++++++++++++--------------------
src/reflect/value.go | 21 ++++++-------
src/runtime/alg.go | 2 +-
src/runtime/iface.go | 12 ++++----
src/runtime/mfinal.go | 4 +--
src/runtime/type.go | 26 ++++------------
11 files changed, 64 insertions(+), 125 deletions(-)
(limited to 'src/reflect')
diff --git a/doc/go1.16.html b/doc/go1.16.html
index ba2f80f95e..3592d0b663 100644
--- a/doc/go1.16.html
+++ b/doc/go1.16.html
@@ -264,15 +264,6 @@ Do not send CLs removing the interior tags from such phrases.
On Linux kernel version 4.1 and above, the maximum is now 4294967295.
-
-
-
- For interface types and values, Method,
- MethodByName, and
- NumMethod now
- operate on the interface's exported method set, rather than its full method set.
-
-
diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index 229fcfeaee..21429af782 100644
--- a/src/cmd/compile/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -1275,9 +1275,8 @@ func dtypesym(t *types.Type) *obj.LSym {
}
ot = dgopkgpath(lsym, ot, tpkg)
- xcount := sort.Search(n, func(i int) bool { return !types.IsExported(m[i].name.Name) })
ot = dsymptr(lsym, ot, lsym, ot+3*Widthptr+uncommonSize(t))
- ot = duintptr(lsym, ot, uint64(xcount))
+ ot = duintptr(lsym, ot, uint64(n))
ot = duintptr(lsym, ot, uint64(n))
dataAdd := imethodSize() * n
ot = dextratype(lsym, ot, t, dataAdd)
diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go
index 37cf03594f..15ba30da36 100644
--- a/src/internal/reflectlite/type.go
+++ b/src/internal/reflectlite/type.go
@@ -234,13 +234,10 @@ type imethod struct {
// interfaceType represents an interface type.
type interfaceType struct {
rtype
- pkgPath name // import path
- expMethods []imethod // sorted by name, see runtime/type.go:interfacetype to see how it is encoded.
+ pkgPath name // import path
+ methods []imethod // sorted by hash
}
-func (t *interfaceType) methods() []imethod { return t.expMethods[:cap(t.expMethods)] }
-func (t *interfaceType) isEmpty() bool { return cap(t.expMethods) == 0 }
-
// mapType represents a map type.
type mapType struct {
rtype
@@ -698,7 +695,7 @@ func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
}
// NumMethod returns the number of interface methods in the type's method set.
-func (t *interfaceType) NumMethod() int { return len(t.expMethods) }
+func (t *interfaceType) NumMethod() int { return len(t.methods) }
// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
@@ -735,10 +732,9 @@ func implements(T, V *rtype) bool {
return false
}
t := (*interfaceType)(unsafe.Pointer(T))
- if t.isEmpty() {
+ if len(t.methods) == 0 {
return true
}
- tmethods := t.methods()
// The same algorithm applies in both cases, but the
// method tables for an interface type and a concrete type
@@ -755,11 +751,10 @@ func implements(T, V *rtype) bool {
if V.Kind() == Interface {
v := (*interfaceType)(unsafe.Pointer(V))
i := 0
- vmethods := v.methods()
- for j := 0; j < len(vmethods); j++ {
- tm := &tmethods[i]
+ for j := 0; j < len(v.methods); j++ {
+ tm := &t.methods[i]
tmName := t.nameOff(tm.name)
- vm := &vmethods[j]
+ vm := &v.methods[j]
vmName := V.nameOff(vm.name)
if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
if !tmName.isExported() {
@@ -775,7 +770,7 @@ func implements(T, V *rtype) bool {
continue
}
}
- if i++; i >= len(tmethods) {
+ if i++; i >= len(t.methods) {
return true
}
}
@@ -790,7 +785,7 @@ func implements(T, V *rtype) bool {
i := 0
vmethods := v.methods()
for j := 0; j < int(v.mcount); j++ {
- tm := &tmethods[i]
+ tm := &t.methods[i]
tmName := t.nameOff(tm.name)
vm := vmethods[j]
vmName := V.nameOff(vm.name)
@@ -808,7 +803,7 @@ func implements(T, V *rtype) bool {
continue
}
}
- if i++; i >= len(tmethods) {
+ if i++; i >= len(t.methods) {
return true
}
}
@@ -902,7 +897,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
case Interface:
t := (*interfaceType)(unsafe.Pointer(T))
v := (*interfaceType)(unsafe.Pointer(V))
- if t.isEmpty() && v.isEmpty() {
+ if len(t.methods) == 0 && len(v.methods) == 0 {
return true
}
// Might have the same methods but still
@@ -967,11 +962,3 @@ func toType(t *rtype) Type {
func ifaceIndir(t *rtype) bool {
return t.kind&kindDirectIface == 0
}
-
-func isEmptyIface(t *rtype) bool {
- if t.Kind() != Interface {
- return false
- }
- tt := (*interfaceType)(unsafe.Pointer(t))
- return tt.isEmpty()
-}
diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go
index fb0ec77b58..0365eeeabf 100644
--- a/src/internal/reflectlite/value.go
+++ b/src/internal/reflectlite/value.go
@@ -228,7 +228,7 @@ func (v Value) Elem() Value {
switch k {
case Interface:
var eface interface{}
- if isEmptyIface(v.typ) {
+ if v.typ.NumMethod() == 0 {
eface = *(*interface{})(v.ptr)
} else {
eface = (interface{})(*(*interface {
@@ -433,7 +433,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
return Value{dst, nil, flag(Interface)}
}
x := valueInterface(v)
- if isEmptyIface(dst) {
+ if dst.NumMethod() == 0 {
*(*interface{})(target) = x
} else {
ifaceE2I(dst, x, target)
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index be15362aae..a12712d254 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -2995,14 +2995,6 @@ func TestUnexportedMethods(t *testing.T) {
if got := typ.NumMethod(); got != 0 {
t.Errorf("NumMethod=%d, want 0 satisfied methods", got)
}
-
- var i unexpI
- if got := TypeOf(&i).Elem().NumMethod(); got != 0 {
- t.Errorf("NumMethod=%d, want 0 satisfied methods", got)
- }
- if got := ValueOf(&i).Elem().NumMethod(); got != 0 {
- t.Errorf("NumMethod=%d, want 0 satisfied methods", got)
- }
}
type InnerInt struct {
@@ -3656,21 +3648,21 @@ func TestCallPanic(t *testing.T) {
v := ValueOf(T{i, i, i, i, T2{i, i}, i, i, T2{i, i}})
badCall(func() { call(v.Field(0).Method(0)) }) // .t0.W
badCall(func() { call(v.Field(0).Elem().Method(0)) }) // .t0.W
- badMethod(func() { call(v.Field(0).Method(1)) }) // .t0.w
+ badCall(func() { call(v.Field(0).Method(1)) }) // .t0.w
badMethod(func() { call(v.Field(0).Elem().Method(2)) }) // .t0.w
ok(func() { call(v.Field(1).Method(0)) }) // .T1.Y
ok(func() { call(v.Field(1).Elem().Method(0)) }) // .T1.Y
- badMethod(func() { call(v.Field(1).Method(1)) }) // .T1.y
+ badCall(func() { call(v.Field(1).Method(1)) }) // .T1.y
badMethod(func() { call(v.Field(1).Elem().Method(2)) }) // .T1.y
ok(func() { call(v.Field(2).Method(0)) }) // .NamedT0.W
ok(func() { call(v.Field(2).Elem().Method(0)) }) // .NamedT0.W
- badMethod(func() { call(v.Field(2).Method(1)) }) // .NamedT0.w
+ badCall(func() { call(v.Field(2).Method(1)) }) // .NamedT0.w
badMethod(func() { call(v.Field(2).Elem().Method(2)) }) // .NamedT0.w
ok(func() { call(v.Field(3).Method(0)) }) // .NamedT1.Y
ok(func() { call(v.Field(3).Elem().Method(0)) }) // .NamedT1.Y
- badMethod(func() { call(v.Field(3).Method(1)) }) // .NamedT1.y
+ badCall(func() { call(v.Field(3).Method(1)) }) // .NamedT1.y
badMethod(func() { call(v.Field(3).Elem().Method(3)) }) // .NamedT1.y
ok(func() { call(v.Field(4).Field(0).Method(0)) }) // .NamedT2.T1.Y
@@ -3680,7 +3672,7 @@ func TestCallPanic(t *testing.T) {
badCall(func() { call(v.Field(5).Method(0)) }) // .namedT0.W
badCall(func() { call(v.Field(5).Elem().Method(0)) }) // .namedT0.W
- badMethod(func() { call(v.Field(5).Method(1)) }) // .namedT0.w
+ badCall(func() { call(v.Field(5).Method(1)) }) // .namedT0.w
badMethod(func() { call(v.Field(5).Elem().Method(2)) }) // .namedT0.w
badCall(func() { call(v.Field(6).Method(0)) }) // .namedT1.Y
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 0b34ca0c94..a3a616701b 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -386,14 +386,10 @@ type imethod struct {
// interfaceType represents an interface type.
type interfaceType struct {
rtype
- pkgPath name // import path
- expMethods []imethod // sorted by name, see runtime/type.go:interfacetype to see how it is encoded.
+ pkgPath name // import path
+ methods []imethod // sorted by hash
}
-// methods returns t's full method set, both exported and non-exported.
-func (t *interfaceType) methods() []imethod { return t.expMethods[:cap(t.expMethods)] }
-func (t *interfaceType) isEmpty() bool { return cap(t.expMethods) == 0 }
-
// mapType represents a map type.
type mapType struct {
rtype
@@ -1053,22 +1049,25 @@ func (d ChanDir) String() string {
// Method returns the i'th method in the type's method set.
func (t *interfaceType) Method(i int) (m Method) {
- if i < 0 || i >= len(t.expMethods) {
- panic("reflect: Method index out of range")
+ if i < 0 || i >= len(t.methods) {
+ return
}
- p := &t.expMethods[i]
+ p := &t.methods[i]
pname := t.nameOff(p.name)
m.Name = pname.name()
if !pname.isExported() {
- panic("reflect: unexported method: " + pname.name())
+ m.PkgPath = pname.pkgPath()
+ if m.PkgPath == "" {
+ m.PkgPath = t.pkgPath.name()
+ }
}
m.Type = toType(t.typeOff(p.typ))
m.Index = i
return
}
-// NumMethod returns the number of exported interface methods in the type's method set.
-func (t *interfaceType) NumMethod() int { return len(t.expMethods) }
+// NumMethod returns the number of interface methods in the type's method set.
+func (t *interfaceType) NumMethod() int { return len(t.methods) }
// MethodByName method with the given name in the type's method set.
func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
@@ -1076,8 +1075,8 @@ func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
return
}
var p *imethod
- for i := range t.expMethods {
- p = &t.expMethods[i]
+ for i := range t.methods {
+ p = &t.methods[i]
if t.nameOff(p.name).name() == name {
return t.Method(i), true
}
@@ -1486,10 +1485,9 @@ func implements(T, V *rtype) bool {
return false
}
t := (*interfaceType)(unsafe.Pointer(T))
- if t.isEmpty() {
+ if len(t.methods) == 0 {
return true
}
- tmethods := t.methods()
// The same algorithm applies in both cases, but the
// method tables for an interface type and a concrete type
@@ -1506,11 +1504,10 @@ func implements(T, V *rtype) bool {
if V.Kind() == Interface {
v := (*interfaceType)(unsafe.Pointer(V))
i := 0
- vmethods := v.methods()
- for j := 0; j < len(vmethods); j++ {
- tm := &tmethods[i]
+ for j := 0; j < len(v.methods); j++ {
+ tm := &t.methods[i]
tmName := t.nameOff(tm.name)
- vm := &vmethods[j]
+ vm := &v.methods[j]
vmName := V.nameOff(vm.name)
if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
if !tmName.isExported() {
@@ -1526,7 +1523,7 @@ func implements(T, V *rtype) bool {
continue
}
}
- if i++; i >= len(tmethods) {
+ if i++; i >= len(t.methods) {
return true
}
}
@@ -1541,7 +1538,7 @@ func implements(T, V *rtype) bool {
i := 0
vmethods := v.methods()
for j := 0; j < int(v.mcount); j++ {
- tm := &tmethods[i]
+ tm := &t.methods[i]
tmName := t.nameOff(tm.name)
vm := vmethods[j]
vmName := V.nameOff(vm.name)
@@ -1559,7 +1556,7 @@ func implements(T, V *rtype) bool {
continue
}
}
- if i++; i >= len(tmethods) {
+ if i++; i >= len(t.methods) {
return true
}
}
@@ -1661,7 +1658,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
case Interface:
t := (*interfaceType)(unsafe.Pointer(T))
v := (*interfaceType)(unsafe.Pointer(V))
- if t.isEmpty() && v.isEmpty() {
+ if len(t.methods) == 0 && len(v.methods) == 0 {
return true
}
// Might have the same methods but still
@@ -2445,7 +2442,7 @@ func StructOf(fields []StructField) Type {
switch f.typ.Kind() {
case Interface:
ift := (*interfaceType)(unsafe.Pointer(ft))
- for im, m := range ift.methods() {
+ for im, m := range ift.methods {
if ift.nameOff(m.name).pkgPath() != "" {
// TODO(sbinet). Issue 15924.
panic("reflect: embedded interface with unexported method(s) not implemented")
@@ -3152,11 +3149,3 @@ func addTypeBits(bv *bitVector, offset uintptr, t *rtype) {
}
}
}
-
-func isEmptyIface(rt *rtype) bool {
- if rt.Kind() != Interface {
- return false
- }
- tt := (*interfaceType)(unsafe.Pointer(rt))
- return len(tt.methods()) == 0
-}
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 24eab6a2c6..bf926a7453 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -636,11 +636,10 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype *rtype, t *fu
i := methodIndex
if v.typ.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(v.typ))
- ttmethods := tt.methods()
- if uint(i) >= uint(len(ttmethods)) {
+ if uint(i) >= uint(len(tt.methods)) {
panic("reflect: internal error: invalid method index")
}
- m := &ttmethods[i]
+ m := &tt.methods[i]
if !tt.nameOff(m.name).isExported() {
panic("reflect: " + op + " of unexported method")
}
@@ -814,7 +813,7 @@ func (v Value) Elem() Value {
switch k {
case Interface:
var eface interface{}
- if isEmptyIface(v.typ) {
+ if v.typ.NumMethod() == 0 {
eface = *(*interface{})(v.ptr)
} else {
eface = (interface{})(*(*interface {
@@ -1035,7 +1034,7 @@ func valueInterface(v Value, safe bool) interface{} {
// Special case: return the element inside the interface.
// Empty interface has one layout, all interfaces with
// methods have a second layout.
- if isEmptyIface(v.typ) {
+ if v.NumMethod() == 0 {
return *(*interface{})(v.ptr)
}
return *(*interface {
@@ -1919,11 +1918,10 @@ func (v Value) Type() Type {
if v.typ.Kind() == Interface {
// Method on interface.
tt := (*interfaceType)(unsafe.Pointer(v.typ))
- ttmethods := tt.methods()
- if uint(i) >= uint(len(ttmethods)) {
+ if uint(i) >= uint(len(tt.methods)) {
panic("reflect: internal error: invalid method index")
}
- m := &ttmethods[i]
+ m := &tt.methods[i]
return v.typ.typeOff(m.typ)
}
// Method on concrete type.
@@ -2441,7 +2439,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
return Value{dst, nil, flag(Interface)}
}
x := valueInterface(v, false)
- if isEmptyIface(dst) {
+ if dst.NumMethod() == 0 {
*(*interface{})(target) = x
} else {
ifaceE2I(dst, x, target)
@@ -2730,11 +2728,10 @@ func cvtDirect(v Value, typ Type) Value {
func cvtT2I(v Value, typ Type) Value {
target := unsafe_New(typ.common())
x := valueInterface(v, false)
- rt := typ.(*rtype)
- if isEmptyIface(rt) {
+ if typ.NumMethod() == 0 {
*(*interface{})(target) = x
} else {
- ifaceE2I(rt, x, target)
+ ifaceE2I(typ.(*rtype), x, target)
}
return Value{typ.common(), target, v.flag.ro() | flagIndir | flag(Interface)}
}
diff --git a/src/runtime/alg.go b/src/runtime/alg.go
index 2ec3fc3658..1b3bf1180d 100644
--- a/src/runtime/alg.go
+++ b/src/runtime/alg.go
@@ -166,7 +166,7 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
return strhash(p, h)
case kindInterface:
i := (*interfacetype)(unsafe.Pointer(t))
- if i.isEmpty() {
+ if len(i.mhdr) == 0 {
return nilinterhash(p, h)
}
return interhash(p, h)
diff --git a/src/runtime/iface.go b/src/runtime/iface.go
index f8b7d429a3..0504b89363 100644
--- a/src/runtime/iface.go
+++ b/src/runtime/iface.go
@@ -31,17 +31,16 @@ func itabHashFunc(inter *interfacetype, typ *_type) uintptr {
}
func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
- if inter.isEmpty() {
+ if len(inter.mhdr) == 0 {
throw("internal error - misuse of itab")
}
- imethods := inter.methods()
// easy case
if typ.tflag&tflagUncommon == 0 {
if canfail {
return nil
}
- name := inter.typ.nameOff(imethods[0].name)
+ name := inter.typ.nameOff(inter.mhdr[0].name)
panic(&TypeAssertionError{nil, typ, &inter.typ, name.name()})
}
@@ -64,7 +63,7 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
}
// Entry doesn't exist yet. Make a new entry & add it.
- m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(imethods)-1)*sys.PtrSize, 0, &memstats.other_sys))
+ m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*sys.PtrSize, 0, &memstats.other_sys))
m.inter = inter
m._type = typ
// The hash is used in type switches. However, compiler statically generates itab's
@@ -198,8 +197,7 @@ func (m *itab) init() string {
// and interface names are unique,
// so can iterate over both in lock step;
// the loop is O(ni+nt) not O(ni*nt).
- imethods := inter.methods()
- ni := len(imethods)
+ ni := len(inter.mhdr)
nt := int(x.mcount)
xmhdr := (*[1 << 16]method)(add(unsafe.Pointer(x), uintptr(x.moff)))[:nt:nt]
j := 0
@@ -207,7 +205,7 @@ func (m *itab) init() string {
var fun0 unsafe.Pointer
imethods:
for k := 0; k < ni; k++ {
- i := &imethods[k]
+ i := &inter.mhdr[k]
itype := inter.typ.typeOff(i.ityp)
name := inter.typ.nameOff(i.name)
iname := name.name()
diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go
index 6ec5133be0..f4dbd77252 100644
--- a/src/runtime/mfinal.go
+++ b/src/runtime/mfinal.go
@@ -210,7 +210,7 @@ func runfinq() {
// set up with empty interface
(*eface)(frame)._type = &f.ot.typ
(*eface)(frame).data = f.arg
- if !ityp.isEmpty() {
+ if len(ityp.mhdr) != 0 {
// convert to interface with methods
// this conversion is guaranteed to succeed - we checked in SetFinalizer
*(*iface)(frame) = assertE2I(ityp, *(*eface)(frame))
@@ -394,7 +394,7 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
}
case fint.kind&kindMask == kindInterface:
ityp := (*interfacetype)(unsafe.Pointer(fint))
- if ityp.isEmpty() {
+ if len(ityp.mhdr) == 0 {
// ok - satisfies empty interface
goto okarg
}
diff --git a/src/runtime/type.go b/src/runtime/type.go
index 36492619e1..81455f3532 100644
--- a/src/runtime/type.go
+++ b/src/runtime/type.go
@@ -366,19 +366,7 @@ type imethod struct {
type interfacetype struct {
typ _type
pkgpath name
- // expMethods contains all interface methods.
- //
- // - len(expMethods) returns number of exported methods.
- // - cap(expMethods) returns all interface methods, including both exported/non-exported methods.
- expMethods []imethod
-}
-
-func (it *interfacetype) methods() []imethod {
- return it.expMethods[:cap(it.expMethods)]
-}
-
-func (it *interfacetype) isEmpty() bool {
- return cap(it.expMethods) == 0
+ mhdr []imethod
}
type maptype struct {
@@ -676,15 +664,13 @@ func typesEqual(t, v *_type, seen map[_typePair]struct{}) bool {
if it.pkgpath.name() != iv.pkgpath.name() {
return false
}
- itmethods := it.methods()
- ivmethods := iv.methods()
- if len(itmethods) != len(ivmethods) {
+ if len(it.mhdr) != len(iv.mhdr) {
return false
}
- for i := range itmethods {
- tm := &itmethods[i]
- vm := &ivmethods[i]
- // Note the expMethods array can be relocated from
+ for i := range it.mhdr {
+ tm := &it.mhdr[i]
+ vm := &iv.mhdr[i]
+ // Note the mhdr array can be relocated from
// another module. See #17724.
tname := resolveNameOff(unsafe.Pointer(tm), tm.name)
vname := resolveNameOff(unsafe.Pointer(vm), vm.name)
--
cgit v1.3
From 50af50d136551e2009b2b52e829570536271cdaa Mon Sep 17 00:00:00 2001
From: Than McIntosh
Date: Wed, 14 Oct 2020 08:36:11 -0400
Subject: reflect,runtime: use internal ABI for selected ASM routines
Change the definitions of selected runtime assembly routines
from ABI0 (the default) to ABIInternal. The ABIInternal def is
intended to indicate that these functions don't follow the existing Go
runtime ABI. In addition, convert the assembly reference to
runtime.main (from runtime.mainPC) to ABIInternal. Finally, for
functions such as "runtime.duffzero" that are called directly from
generated code, make sure that the compiler looks up the correct
ABI version.
This is intended to support the register abi work, however these
changes should not have any issues even when GOEXPERIMENT=regabi is
not in effect.
Updates #27539, #40724.
Change-Id: I9846f8dcaccc95718cf2e61a18b7e924a0677e4c
Reviewed-on: https://go-review.googlesource.com/c/go/+/262319
Run-TryBot: Than McIntosh
TryBot-Result: Go Bot
Trust: Than McIntosh
Reviewed-by: Cherry Zhang
---
src/cmd/compile/internal/gc/ssa.go | 86 ++++++++++++++++----------------
src/cmd/internal/obj/wasm/wasmobj.go | 6 +--
src/reflect/asm_amd64.s | 12 +++--
src/runtime/asm_amd64.s | 96 ++++++++++++++++++++++--------------
src/runtime/asm_wasm.s | 4 +-
src/runtime/duff_amd64.s | 4 +-
src/runtime/mkpreempt.go | 3 +-
src/runtime/preempt_386.s | 3 +-
src/runtime/preempt_amd64.s | 3 +-
src/runtime/preempt_arm.s | 3 +-
src/runtime/preempt_arm64.s | 3 +-
src/runtime/preempt_mips64x.s | 3 +-
src/runtime/preempt_mipsx.s | 3 +-
src/runtime/preempt_ppc64x.s | 3 +-
src/runtime/preempt_riscv64.s | 3 +-
src/runtime/preempt_s390x.s | 3 +-
src/runtime/preempt_wasm.s | 3 +-
src/runtime/race_amd64.s | 12 +++--
src/runtime/sys_linux_amd64.s | 13 +++--
19 files changed, 154 insertions(+), 112 deletions(-)
(limited to 'src/reflect')
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 45d628cc5e..7388e4e3e8 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -72,9 +72,9 @@ func initssaconfig() {
deferproc = sysfunc("deferproc")
deferprocStack = sysfunc("deferprocStack")
Deferreturn = sysfunc("deferreturn")
- Duffcopy = sysvar("duffcopy") // asm func with special ABI
- Duffzero = sysvar("duffzero") // asm func with special ABI
- gcWriteBarrier = sysvar("gcWriteBarrier") // asm func with special ABI
+ Duffcopy = sysfunc("duffcopy")
+ Duffzero = sysfunc("duffzero")
+ gcWriteBarrier = sysfunc("gcWriteBarrier")
goschedguarded = sysfunc("goschedguarded")
growslice = sysfunc("growslice")
msanread = sysfunc("msanread")
@@ -105,51 +105,51 @@ func initssaconfig() {
// asm funcs with special ABI
if thearch.LinkArch.Name == "amd64" {
GCWriteBarrierReg = map[int16]*obj.LSym{
- x86.REG_AX: sysvar("gcWriteBarrier"),
- x86.REG_CX: sysvar("gcWriteBarrierCX"),
- x86.REG_DX: sysvar("gcWriteBarrierDX"),
- x86.REG_BX: sysvar("gcWriteBarrierBX"),
- x86.REG_BP: sysvar("gcWriteBarrierBP"),
- x86.REG_SI: sysvar("gcWriteBarrierSI"),
- x86.REG_R8: sysvar("gcWriteBarrierR8"),
- x86.REG_R9: sysvar("gcWriteBarrierR9"),
+ x86.REG_AX: sysfunc("gcWriteBarrier"),
+ x86.REG_CX: sysfunc("gcWriteBarrierCX"),
+ x86.REG_DX: sysfunc("gcWriteBarrierDX"),
+ x86.REG_BX: sysfunc("gcWriteBarrierBX"),
+ x86.REG_BP: sysfunc("gcWriteBarrierBP"),
+ x86.REG_SI: sysfunc("gcWriteBarrierSI"),
+ x86.REG_R8: sysfunc("gcWriteBarrierR8"),
+ x86.REG_R9: sysfunc("gcWriteBarrierR9"),
}
}
if thearch.LinkArch.Family == sys.Wasm {
- BoundsCheckFunc[ssa.BoundsIndex] = sysvar("goPanicIndex")
- BoundsCheckFunc[ssa.BoundsIndexU] = sysvar("goPanicIndexU")
- BoundsCheckFunc[ssa.BoundsSliceAlen] = sysvar("goPanicSliceAlen")
- BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysvar("goPanicSliceAlenU")
- BoundsCheckFunc[ssa.BoundsSliceAcap] = sysvar("goPanicSliceAcap")
- BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysvar("goPanicSliceAcapU")
- BoundsCheckFunc[ssa.BoundsSliceB] = sysvar("goPanicSliceB")
- BoundsCheckFunc[ssa.BoundsSliceBU] = sysvar("goPanicSliceBU")
- BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysvar("goPanicSlice3Alen")
- BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysvar("goPanicSlice3AlenU")
- BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysvar("goPanicSlice3Acap")
- BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysvar("goPanicSlice3AcapU")
- BoundsCheckFunc[ssa.BoundsSlice3B] = sysvar("goPanicSlice3B")
- BoundsCheckFunc[ssa.BoundsSlice3BU] = sysvar("goPanicSlice3BU")
- BoundsCheckFunc[ssa.BoundsSlice3C] = sysvar("goPanicSlice3C")
- BoundsCheckFunc[ssa.BoundsSlice3CU] = sysvar("goPanicSlice3CU")
+ BoundsCheckFunc[ssa.BoundsIndex] = sysfunc("goPanicIndex")
+ BoundsCheckFunc[ssa.BoundsIndexU] = sysfunc("goPanicIndexU")
+ BoundsCheckFunc[ssa.BoundsSliceAlen] = sysfunc("goPanicSliceAlen")
+ BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysfunc("goPanicSliceAlenU")
+ BoundsCheckFunc[ssa.BoundsSliceAcap] = sysfunc("goPanicSliceAcap")
+ BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysfunc("goPanicSliceAcapU")
+ BoundsCheckFunc[ssa.BoundsSliceB] = sysfunc("goPanicSliceB")
+ BoundsCheckFunc[ssa.BoundsSliceBU] = sysfunc("goPanicSliceBU")
+ BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysfunc("goPanicSlice3Alen")
+ BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysfunc("goPanicSlice3AlenU")
+ BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysfunc("goPanicSlice3Acap")
+ BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysfunc("goPanicSlice3AcapU")
+ BoundsCheckFunc[ssa.BoundsSlice3B] = sysfunc("goPanicSlice3B")
+ BoundsCheckFunc[ssa.BoundsSlice3BU] = sysfunc("goPanicSlice3BU")
+ BoundsCheckFunc[ssa.BoundsSlice3C] = sysfunc("goPanicSlice3C")
+ BoundsCheckFunc[ssa.BoundsSlice3CU] = sysfunc("goPanicSlice3CU")
} else {
- BoundsCheckFunc[ssa.BoundsIndex] = sysvar("panicIndex")
- BoundsCheckFunc[ssa.BoundsIndexU] = sysvar("panicIndexU")
- BoundsCheckFunc[ssa.BoundsSliceAlen] = sysvar("panicSliceAlen")
- BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysvar("panicSliceAlenU")
- BoundsCheckFunc[ssa.BoundsSliceAcap] = sysvar("panicSliceAcap")
- BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysvar("panicSliceAcapU")
- BoundsCheckFunc[ssa.BoundsSliceB] = sysvar("panicSliceB")
- BoundsCheckFunc[ssa.BoundsSliceBU] = sysvar("panicSliceBU")
- BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysvar("panicSlice3Alen")
- BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysvar("panicSlice3AlenU")
- BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysvar("panicSlice3Acap")
- BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysvar("panicSlice3AcapU")
- BoundsCheckFunc[ssa.BoundsSlice3B] = sysvar("panicSlice3B")
- BoundsCheckFunc[ssa.BoundsSlice3BU] = sysvar("panicSlice3BU")
- BoundsCheckFunc[ssa.BoundsSlice3C] = sysvar("panicSlice3C")
- BoundsCheckFunc[ssa.BoundsSlice3CU] = sysvar("panicSlice3CU")
+ BoundsCheckFunc[ssa.BoundsIndex] = sysfunc("panicIndex")
+ BoundsCheckFunc[ssa.BoundsIndexU] = sysfunc("panicIndexU")
+ BoundsCheckFunc[ssa.BoundsSliceAlen] = sysfunc("panicSliceAlen")
+ BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysfunc("panicSliceAlenU")
+ BoundsCheckFunc[ssa.BoundsSliceAcap] = sysfunc("panicSliceAcap")
+ BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysfunc("panicSliceAcapU")
+ BoundsCheckFunc[ssa.BoundsSliceB] = sysfunc("panicSliceB")
+ BoundsCheckFunc[ssa.BoundsSliceBU] = sysfunc("panicSliceBU")
+ BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysfunc("panicSlice3Alen")
+ BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysfunc("panicSlice3AlenU")
+ BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysfunc("panicSlice3Acap")
+ BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysfunc("panicSlice3AcapU")
+ BoundsCheckFunc[ssa.BoundsSlice3B] = sysfunc("panicSlice3B")
+ BoundsCheckFunc[ssa.BoundsSlice3BU] = sysfunc("panicSlice3BU")
+ BoundsCheckFunc[ssa.BoundsSlice3C] = sysfunc("panicSlice3C")
+ BoundsCheckFunc[ssa.BoundsSlice3CU] = sysfunc("panicSlice3CU")
}
if thearch.LinkArch.PtrSize == 4 {
ExtendCheckFunc[ssa.BoundsIndex] = sysvar("panicExtendIndex")
diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go
index f7f66a1255..2e9890d86c 100644
--- a/src/cmd/internal/obj/wasm/wasmobj.go
+++ b/src/cmd/internal/obj/wasm/wasmobj.go
@@ -129,7 +129,6 @@ var (
morestackNoCtxt *obj.LSym
gcWriteBarrier *obj.LSym
sigpanic *obj.LSym
- sigpanic0 *obj.LSym
deferreturn *obj.LSym
jmpdefer *obj.LSym
)
@@ -142,9 +141,8 @@ const (
func instinit(ctxt *obj.Link) {
morestack = ctxt.Lookup("runtime.morestack")
morestackNoCtxt = ctxt.Lookup("runtime.morestack_noctxt")
- gcWriteBarrier = ctxt.Lookup("runtime.gcWriteBarrier")
+ gcWriteBarrier = ctxt.LookupABI("runtime.gcWriteBarrier", obj.ABIInternal)
sigpanic = ctxt.LookupABI("runtime.sigpanic", obj.ABIInternal)
- sigpanic0 = ctxt.LookupABI("runtime.sigpanic", 0) // sigpanic called from assembly, which has ABI0
deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal)
// jmpdefer is defined in assembly as ABI0, but what we're
// looking for is the *call* to jmpdefer from the Go function
@@ -493,7 +491,7 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
}
// return value of call is on the top of the stack, indicating whether to unwind the WebAssembly stack
- if call.As == ACALLNORESUME && call.To.Sym != sigpanic && call.To.Sym != sigpanic0 { // sigpanic unwinds the stack, but it never resumes
+ if call.As == ACALLNORESUME && call.To.Sym != sigpanic { // sigpanic unwinds the stack, but it never resumes
// trying to unwind WebAssembly stack but call has no resume point, terminate with error
p = appendp(p, AIf)
p = appendp(p, obj.AUNDEF)
diff --git a/src/reflect/asm_amd64.s b/src/reflect/asm_amd64.s
index fb28ab87f1..5c8e56558c 100644
--- a/src/reflect/asm_amd64.s
+++ b/src/reflect/asm_amd64.s
@@ -9,7 +9,9 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
+// makeFuncStub must be ABIInternal because it is placed directly
+// in function values.
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVQ DX, 0(SP)
LEAQ argframe+0(FP), CX
@@ -17,14 +19,16 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
MOVB $0, 24(SP)
LEAQ 24(SP), AX
MOVQ AX, 16(SP)
- CALL ·callReflect(SB)
+ CALL ·callReflect(SB)
RET
// methodValueCall is the code half of the function returned by makeMethodValue.
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
+// methodValueCall must be ABIInternal because it is placed directly
+// in function values.
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVQ DX, 0(SP)
LEAQ argframe+0(FP), CX
@@ -32,5 +36,5 @@ TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
MOVB $0, 24(SP)
LEAQ 24(SP), AX
MOVQ AX, 16(SP)
- CALL ·callMethod(SB)
+ CALL ·callMethod(SB)
RET
diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index 19a3bb2d7d..196252e1dd 100644
--- a/src/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -84,7 +84,9 @@ GLOBL _rt0_amd64_lib_argc<>(SB),NOPTR, $8
DATA _rt0_amd64_lib_argv<>(SB)/8, $0
GLOBL _rt0_amd64_lib_argv<>(SB),NOPTR, $8
-TEXT runtime·rt0_go(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stack-based Go ABI (and
+// in addition there are no calls to this entry point from Go code).
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
// copy arguments forward on an even stack
MOVQ DI, AX // argc
MOVQ SI, BX // argv
@@ -229,10 +231,13 @@ ok:
// Prevent dead-code elimination of debugCallV1, which is
// intended to be called by debuggers.
- MOVQ $runtime·debugCallV1(SB), AX
+ MOVQ $runtime·debugCallV1(SB), AX
RET
-DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
+// mainPC is a function value for runtime.main, to be passed to newproc.
+// The reference to runtime.main is made via ABIInternal, since the
+// actual function (not the ABI0 wrapper) is needed by newproc.
+DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
GLOBL runtime·mainPC(SB),RODATA,$8
TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
@@ -468,7 +473,7 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0
JMP AX
// Note: can't just "JMP NAME(SB)" - bad inlining results.
-TEXT ·reflectcall(SB), NOSPLIT, $0-32
+TEXT ·reflectcall(SB), NOSPLIT, $0-32
MOVLQZX argsize+24(FP), CX
DISPATCH(runtime·call16, 16)
DISPATCH(runtime·call32, 32)
@@ -1354,8 +1359,11 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
RET
// The top-most function running on a goroutine
-// returns to goexit+PCQuantum.
-TEXT runtime·goexit(SB),NOSPLIT,$0-0
+// returns to goexit+PCQuantum. Defined as ABIInternal
+// so as to make it identifiable to traceback (this
+// function it used as a sentinel; traceback wants to
+// see the func PC, not a wrapper PC).
+TEXT runtime·goexit(SB),NOSPLIT,$0-0
BYTE $0x90 // NOP
CALL runtime·goexit1(SB) // does not return
// traceback from goexit1 must hit code range of goexit
@@ -1377,7 +1385,8 @@ TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
// - AX is the value being written at DI
// It clobbers FLAGS. It does not clobber any general-purpose registers,
// but may clobber others (e.g., SSE registers).
-TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$120
+// Defined as ABIInternal since it does not use the stack-based Go ABI.
+TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$120
// Save the registers clobbered by the fast path. This is slightly
// faster than having the caller spill these.
MOVQ R14, 104(SP)
@@ -1461,51 +1470,58 @@ flush:
JMP ret
// gcWriteBarrierCX is gcWriteBarrier, but with args in DI and CX.
-TEXT runtime·gcWriteBarrierCX(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierCX(SB),NOSPLIT,$0
XCHGQ CX, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ CX, AX
RET
// gcWriteBarrierDX is gcWriteBarrier, but with args in DI and DX.
-TEXT runtime·gcWriteBarrierDX(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierDX(SB),NOSPLIT,$0
XCHGQ DX, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ DX, AX
RET
// gcWriteBarrierBX is gcWriteBarrier, but with args in DI and BX.
-TEXT runtime·gcWriteBarrierBX(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierBX(SB),NOSPLIT,$0
XCHGQ BX, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ BX, AX
RET
// gcWriteBarrierBP is gcWriteBarrier, but with args in DI and BP.
-TEXT runtime·gcWriteBarrierBP(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierBP(SB),NOSPLIT,$0
XCHGQ BP, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ BP, AX
RET
// gcWriteBarrierSI is gcWriteBarrier, but with args in DI and SI.
-TEXT runtime·gcWriteBarrierSI(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierSI(SB),NOSPLIT,$0
XCHGQ SI, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ SI, AX
RET
// gcWriteBarrierR8 is gcWriteBarrier, but with args in DI and R8.
-TEXT runtime·gcWriteBarrierR8(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierR8(SB),NOSPLIT,$0
XCHGQ R8, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ R8, AX
RET
// gcWriteBarrierR9 is gcWriteBarrier, but with args in DI and R9.
-TEXT runtime·gcWriteBarrierR9(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierR9(SB),NOSPLIT,$0
XCHGQ R9, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ R9, AX
RET
@@ -1544,7 +1560,10 @@ GLOBL debugCallFrameTooLarge<>(SB), RODATA, $20 // Size duplicated below
// obey escape analysis requirements. Specifically, it must not pass
// a stack pointer to an escaping argument. debugCallV1 cannot check
// this invariant.
-TEXT runtime·debugCallV1(SB),NOSPLIT,$152-0
+//
+// This is ABIInternal because Go code injects its PC directly into new
+// goroutine stacks.
+TEXT runtime·debugCallV1(SB),NOSPLIT,$152-0
// Save all registers that may contain pointers so they can be
// conservatively scanned.
//
@@ -1705,67 +1724,68 @@ TEXT runtime·debugCallPanicked(SB),NOSPLIT,$16-16
// in the caller's stack frame. These stubs write the args into that stack space and
// then tail call to the corresponding runtime handler.
// The tail call makes these stubs disappear in backtraces.
-TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
+// Defined as ABIInternal since they do not use the stack-based Go ABI.
+TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicIndex(SB)
-TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
+TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicIndexU(SB)
-TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAlen(SB)
-TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAlenU(SB)
-TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAcap(SB)
-TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAcapU(SB)
-TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSliceB(SB)
-TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSliceBU(SB)
-TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3Alen(SB)
-TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3AlenU(SB)
-TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3Acap(SB)
-TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3AcapU(SB)
-TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSlice3B(SB)
-TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSlice3BU(SB)
-TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSlice3C(SB)
-TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSlice3CU(SB)
diff --git a/src/runtime/asm_wasm.s b/src/runtime/asm_wasm.s
index 67e81adf0b..fcb780f1dc 100644
--- a/src/runtime/asm_wasm.s
+++ b/src/runtime/asm_wasm.s
@@ -196,7 +196,7 @@ TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16
Get CTXT
I64Eqz
If
- CALLNORESUME runtime·sigpanic(SB)
+ CALLNORESUME runtime·sigpanic(SB)
End
// caller sp after CALL
@@ -300,7 +300,7 @@ TEXT ·reflectcall(SB), NOSPLIT, $0-32
I64Load fn+8(FP)
I64Eqz
If
- CALLNORESUME runtime·sigpanic(SB)
+ CALLNORESUME runtime·sigpanic(SB)
End
MOVW argsize+24(FP), R0
diff --git a/src/runtime/duff_amd64.s b/src/runtime/duff_amd64.s
index 44dc75d297..2ff5bf6dbc 100644
--- a/src/runtime/duff_amd64.s
+++ b/src/runtime/duff_amd64.s
@@ -4,7 +4,7 @@
#include "textflag.h"
-TEXT runtime·duffzero(SB), NOSPLIT, $0-0
+TEXT runtime·duffzero(SB), NOSPLIT, $0-0
MOVUPS X0,(DI)
MOVUPS X0,16(DI)
MOVUPS X0,32(DI)
@@ -103,7 +103,7 @@ TEXT runtime·duffzero(SB), NOSPLIT, $0-0
RET
-TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
+TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
MOVUPS (SI), X0
ADDQ $16, SI
MOVUPS X0, (DI)
diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go
index 286f81489a..1d614dd003 100644
--- a/src/runtime/mkpreempt.go
+++ b/src/runtime/mkpreempt.go
@@ -126,7 +126,8 @@ func header(arch string) {
}
fmt.Fprintf(out, "#include \"go_asm.h\"\n")
fmt.Fprintf(out, "#include \"textflag.h\"\n\n")
- fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n")
+ fmt.Fprintf(out, "// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.\n")
+ fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n")
}
func p(f string, args ...interface{}) {
diff --git a/src/runtime/preempt_386.s b/src/runtime/preempt_386.s
index c3a5fa1f36..a803b24dc6 100644
--- a/src/runtime/preempt_386.s
+++ b/src/runtime/preempt_386.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
PUSHFL
ADJSP $156
NOP SP
diff --git a/src/runtime/preempt_amd64.s b/src/runtime/preempt_amd64.s
index 4765e9f448..92c664d79a 100644
--- a/src/runtime/preempt_amd64.s
+++ b/src/runtime/preempt_amd64.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
PUSHQ BP
MOVQ SP, BP
// Save flags before clobbering them
diff --git a/src/runtime/preempt_arm.s b/src/runtime/preempt_arm.s
index 8f243c0dcd..bbc9fbb1ea 100644
--- a/src/runtime/preempt_arm.s
+++ b/src/runtime/preempt_arm.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVW.W R14, -188(R13)
MOVW R0, 4(R13)
MOVW R1, 8(R13)
diff --git a/src/runtime/preempt_arm64.s b/src/runtime/preempt_arm64.s
index 36ee13282c..2b70a28479 100644
--- a/src/runtime/preempt_arm64.s
+++ b/src/runtime/preempt_arm64.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVD R30, -496(RSP)
SUB $496, RSP
#ifdef GOOS_linux
diff --git a/src/runtime/preempt_mips64x.s b/src/runtime/preempt_mips64x.s
index 1e123e8077..0d0c157c36 100644
--- a/src/runtime/preempt_mips64x.s
+++ b/src/runtime/preempt_mips64x.s
@@ -5,7 +5,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVV R31, -488(R29)
SUBV $488, R29
MOVV R1, 8(R29)
diff --git a/src/runtime/preempt_mipsx.s b/src/runtime/preempt_mipsx.s
index afac33e0a0..86d3a918d3 100644
--- a/src/runtime/preempt_mipsx.s
+++ b/src/runtime/preempt_mipsx.s
@@ -5,7 +5,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVW R31, -244(R29)
SUB $244, R29
MOVW R1, 4(R29)
diff --git a/src/runtime/preempt_ppc64x.s b/src/runtime/preempt_ppc64x.s
index b2d7e30ec7..90634386db 100644
--- a/src/runtime/preempt_ppc64x.s
+++ b/src/runtime/preempt_ppc64x.s
@@ -5,7 +5,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVD R31, -488(R1)
MOVD LR, R31
MOVDU R31, -520(R1)
diff --git a/src/runtime/preempt_riscv64.s b/src/runtime/preempt_riscv64.s
index eb68dcba2b..d4f9cc277f 100644
--- a/src/runtime/preempt_riscv64.s
+++ b/src/runtime/preempt_riscv64.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOV X1, -472(X2)
ADD $-472, X2
MOV X3, 8(X2)
diff --git a/src/runtime/preempt_s390x.s b/src/runtime/preempt_s390x.s
index ca9e47cde1..c6f11571df 100644
--- a/src/runtime/preempt_s390x.s
+++ b/src/runtime/preempt_s390x.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
IPM R10
MOVD R14, -248(R15)
ADD $-248, R15
diff --git a/src/runtime/preempt_wasm.s b/src/runtime/preempt_wasm.s
index 0cf57d3d22..da90e8aa6d 100644
--- a/src/runtime/preempt_wasm.s
+++ b/src/runtime/preempt_wasm.s
@@ -3,6 +3,7 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
// No async preemption on wasm
UNDEF
diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s
index 758d543203..4a86b3371a 100644
--- a/src/runtime/race_amd64.s
+++ b/src/runtime/race_amd64.s
@@ -41,7 +41,9 @@
// func runtime·raceread(addr uintptr)
// Called from instrumented code.
-TEXT runtime·raceread(SB), NOSPLIT, $0-8
+// Defined as ABIInternal so as to avoid introducing a wrapper,
+// which would render runtime.getcallerpc ineffective.
+TEXT runtime·raceread(SB), NOSPLIT, $0-8
MOVQ addr+0(FP), RARG1
MOVQ (SP), RARG2
// void __tsan_read(ThreadState *thr, void *addr, void *pc);
@@ -65,7 +67,9 @@ TEXT runtime·racereadpc(SB), NOSPLIT, $0-24
// func runtime·racewrite(addr uintptr)
// Called from instrumented code.
-TEXT runtime·racewrite(SB), NOSPLIT, $0-8
+// Defined as ABIInternal so as to avoid introducing a wrapper,
+// which would render runtime.getcallerpc ineffective.
+TEXT runtime·racewrite(SB), NOSPLIT, $0-8
MOVQ addr+0(FP), RARG1
MOVQ (SP), RARG2
// void __tsan_write(ThreadState *thr, void *addr, void *pc);
@@ -114,7 +118,9 @@ TEXT runtime·racereadrangepc1(SB), NOSPLIT, $0-24
// func runtime·racewriterange(addr, size uintptr)
// Called from instrumented code.
-TEXT runtime·racewriterange(SB), NOSPLIT, $0-16
+// Defined as ABIInternal so as to avoid introducing a wrapper,
+// which would render runtime.getcallerpc ineffective.
+TEXT runtime·racewriterange(SB), NOSPLIT, $0-16
MOVQ addr+0(FP), RARG1
MOVQ size+8(FP), RARG2
MOVQ (SP), RARG3
diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
index 681cd20274..37cb8dad03 100644
--- a/src/runtime/sys_linux_amd64.s
+++ b/src/runtime/sys_linux_amd64.s
@@ -380,7 +380,8 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
POPQ BP
RET
-TEXT runtime·sigtramp(SB),NOSPLIT,$72
+// Defined as ABIInternal since it does not use the stack-based Go ABI.
+TEXT runtime·sigtramp(SB),NOSPLIT,$72
// Save callee-saved C registers, since the caller may be a C signal handler.
MOVQ BX, bx-8(SP)
MOVQ BP, bp-16(SP) // save in case GOEXPERIMENT=noframepointer is set
@@ -407,7 +408,8 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$72
// Used instead of sigtramp in programs that use cgo.
// Arguments from kernel are in DI, SI, DX.
-TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stack-based Go ABI.
+TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
// If no traceback function, do usual sigtramp.
MOVQ runtime·cgoTraceback(SB), AX
TESTQ AX, AX
@@ -450,12 +452,12 @@ TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
// The first three arguments, and the fifth, are already in registers.
// Set the two remaining arguments now.
MOVQ runtime·cgoTraceback(SB), CX
- MOVQ $runtime·sigtramp(SB), R9
+ MOVQ $runtime·sigtramp(SB), R9
MOVQ _cgo_callers(SB), AX
JMP AX
sigtramp:
- JMP runtime·sigtramp(SB)
+ JMP runtime·sigtramp(SB)
sigtrampnog:
// Signal arrived on a non-Go thread. If this is SIGPROF, get a
@@ -486,7 +488,8 @@ sigtrampnog:
// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/x86_64/sigaction.c
// The code that cares about the precise instructions used is:
// https://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/i386/linux-unwind.h?revision=219188&view=markup
-TEXT runtime·sigreturn(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stack-based Go ABI.
+TEXT runtime·sigreturn(SB),NOSPLIT,$0
MOVQ $SYS_rt_sigreturn, AX
SYSCALL
INT $3 // not reached
--
cgit v1.3
From ddc7e1d16f58c73a2587bba130a4a49ffac8b0d1 Mon Sep 17 00:00:00 2001
From: Than McIntosh
Date: Thu, 29 Oct 2020 15:37:35 +0000
Subject: Revert "reflect,runtime: use internal ABI for selected ASM routines"
This reverts commit 50af50d136551e2009b2b52e829570536271cdaa.
Reason for revert: Causes failures in the runtime package test on Darwin, apparently.
Change-Id: I006bc1b3443fa7207e92fb4a93e3fb438d4d3de3
Reviewed-on: https://go-review.googlesource.com/c/go/+/266257
Trust: Than McIntosh
Run-TryBot: Than McIntosh
TryBot-Result: Go Bot
Reviewed-by: Cherry Zhang
---
src/cmd/compile/internal/gc/ssa.go | 86 ++++++++++++++++----------------
src/cmd/internal/obj/wasm/wasmobj.go | 6 ++-
src/reflect/asm_amd64.s | 12 ++---
src/runtime/asm_amd64.s | 96 ++++++++++++++----------------------
src/runtime/asm_wasm.s | 4 +-
src/runtime/duff_amd64.s | 4 +-
src/runtime/mkpreempt.go | 3 +-
src/runtime/preempt_386.s | 3 +-
src/runtime/preempt_amd64.s | 3 +-
src/runtime/preempt_arm.s | 3 +-
src/runtime/preempt_arm64.s | 3 +-
src/runtime/preempt_mips64x.s | 3 +-
src/runtime/preempt_mipsx.s | 3 +-
src/runtime/preempt_ppc64x.s | 3 +-
src/runtime/preempt_riscv64.s | 3 +-
src/runtime/preempt_s390x.s | 3 +-
src/runtime/preempt_wasm.s | 3 +-
src/runtime/race_amd64.s | 12 ++---
src/runtime/sys_linux_amd64.s | 13 ++---
19 files changed, 112 insertions(+), 154 deletions(-)
(limited to 'src/reflect')
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 7388e4e3e8..45d628cc5e 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -72,9 +72,9 @@ func initssaconfig() {
deferproc = sysfunc("deferproc")
deferprocStack = sysfunc("deferprocStack")
Deferreturn = sysfunc("deferreturn")
- Duffcopy = sysfunc("duffcopy")
- Duffzero = sysfunc("duffzero")
- gcWriteBarrier = sysfunc("gcWriteBarrier")
+ Duffcopy = sysvar("duffcopy") // asm func with special ABI
+ Duffzero = sysvar("duffzero") // asm func with special ABI
+ gcWriteBarrier = sysvar("gcWriteBarrier") // asm func with special ABI
goschedguarded = sysfunc("goschedguarded")
growslice = sysfunc("growslice")
msanread = sysfunc("msanread")
@@ -105,51 +105,51 @@ func initssaconfig() {
// asm funcs with special ABI
if thearch.LinkArch.Name == "amd64" {
GCWriteBarrierReg = map[int16]*obj.LSym{
- x86.REG_AX: sysfunc("gcWriteBarrier"),
- x86.REG_CX: sysfunc("gcWriteBarrierCX"),
- x86.REG_DX: sysfunc("gcWriteBarrierDX"),
- x86.REG_BX: sysfunc("gcWriteBarrierBX"),
- x86.REG_BP: sysfunc("gcWriteBarrierBP"),
- x86.REG_SI: sysfunc("gcWriteBarrierSI"),
- x86.REG_R8: sysfunc("gcWriteBarrierR8"),
- x86.REG_R9: sysfunc("gcWriteBarrierR9"),
+ x86.REG_AX: sysvar("gcWriteBarrier"),
+ x86.REG_CX: sysvar("gcWriteBarrierCX"),
+ x86.REG_DX: sysvar("gcWriteBarrierDX"),
+ x86.REG_BX: sysvar("gcWriteBarrierBX"),
+ x86.REG_BP: sysvar("gcWriteBarrierBP"),
+ x86.REG_SI: sysvar("gcWriteBarrierSI"),
+ x86.REG_R8: sysvar("gcWriteBarrierR8"),
+ x86.REG_R9: sysvar("gcWriteBarrierR9"),
}
}
if thearch.LinkArch.Family == sys.Wasm {
- BoundsCheckFunc[ssa.BoundsIndex] = sysfunc("goPanicIndex")
- BoundsCheckFunc[ssa.BoundsIndexU] = sysfunc("goPanicIndexU")
- BoundsCheckFunc[ssa.BoundsSliceAlen] = sysfunc("goPanicSliceAlen")
- BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysfunc("goPanicSliceAlenU")
- BoundsCheckFunc[ssa.BoundsSliceAcap] = sysfunc("goPanicSliceAcap")
- BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysfunc("goPanicSliceAcapU")
- BoundsCheckFunc[ssa.BoundsSliceB] = sysfunc("goPanicSliceB")
- BoundsCheckFunc[ssa.BoundsSliceBU] = sysfunc("goPanicSliceBU")
- BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysfunc("goPanicSlice3Alen")
- BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysfunc("goPanicSlice3AlenU")
- BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysfunc("goPanicSlice3Acap")
- BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysfunc("goPanicSlice3AcapU")
- BoundsCheckFunc[ssa.BoundsSlice3B] = sysfunc("goPanicSlice3B")
- BoundsCheckFunc[ssa.BoundsSlice3BU] = sysfunc("goPanicSlice3BU")
- BoundsCheckFunc[ssa.BoundsSlice3C] = sysfunc("goPanicSlice3C")
- BoundsCheckFunc[ssa.BoundsSlice3CU] = sysfunc("goPanicSlice3CU")
+ BoundsCheckFunc[ssa.BoundsIndex] = sysvar("goPanicIndex")
+ BoundsCheckFunc[ssa.BoundsIndexU] = sysvar("goPanicIndexU")
+ BoundsCheckFunc[ssa.BoundsSliceAlen] = sysvar("goPanicSliceAlen")
+ BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysvar("goPanicSliceAlenU")
+ BoundsCheckFunc[ssa.BoundsSliceAcap] = sysvar("goPanicSliceAcap")
+ BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysvar("goPanicSliceAcapU")
+ BoundsCheckFunc[ssa.BoundsSliceB] = sysvar("goPanicSliceB")
+ BoundsCheckFunc[ssa.BoundsSliceBU] = sysvar("goPanicSliceBU")
+ BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysvar("goPanicSlice3Alen")
+ BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysvar("goPanicSlice3AlenU")
+ BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysvar("goPanicSlice3Acap")
+ BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysvar("goPanicSlice3AcapU")
+ BoundsCheckFunc[ssa.BoundsSlice3B] = sysvar("goPanicSlice3B")
+ BoundsCheckFunc[ssa.BoundsSlice3BU] = sysvar("goPanicSlice3BU")
+ BoundsCheckFunc[ssa.BoundsSlice3C] = sysvar("goPanicSlice3C")
+ BoundsCheckFunc[ssa.BoundsSlice3CU] = sysvar("goPanicSlice3CU")
} else {
- BoundsCheckFunc[ssa.BoundsIndex] = sysfunc("panicIndex")
- BoundsCheckFunc[ssa.BoundsIndexU] = sysfunc("panicIndexU")
- BoundsCheckFunc[ssa.BoundsSliceAlen] = sysfunc("panicSliceAlen")
- BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysfunc("panicSliceAlenU")
- BoundsCheckFunc[ssa.BoundsSliceAcap] = sysfunc("panicSliceAcap")
- BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysfunc("panicSliceAcapU")
- BoundsCheckFunc[ssa.BoundsSliceB] = sysfunc("panicSliceB")
- BoundsCheckFunc[ssa.BoundsSliceBU] = sysfunc("panicSliceBU")
- BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysfunc("panicSlice3Alen")
- BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysfunc("panicSlice3AlenU")
- BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysfunc("panicSlice3Acap")
- BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysfunc("panicSlice3AcapU")
- BoundsCheckFunc[ssa.BoundsSlice3B] = sysfunc("panicSlice3B")
- BoundsCheckFunc[ssa.BoundsSlice3BU] = sysfunc("panicSlice3BU")
- BoundsCheckFunc[ssa.BoundsSlice3C] = sysfunc("panicSlice3C")
- BoundsCheckFunc[ssa.BoundsSlice3CU] = sysfunc("panicSlice3CU")
+ BoundsCheckFunc[ssa.BoundsIndex] = sysvar("panicIndex")
+ BoundsCheckFunc[ssa.BoundsIndexU] = sysvar("panicIndexU")
+ BoundsCheckFunc[ssa.BoundsSliceAlen] = sysvar("panicSliceAlen")
+ BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysvar("panicSliceAlenU")
+ BoundsCheckFunc[ssa.BoundsSliceAcap] = sysvar("panicSliceAcap")
+ BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysvar("panicSliceAcapU")
+ BoundsCheckFunc[ssa.BoundsSliceB] = sysvar("panicSliceB")
+ BoundsCheckFunc[ssa.BoundsSliceBU] = sysvar("panicSliceBU")
+ BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysvar("panicSlice3Alen")
+ BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysvar("panicSlice3AlenU")
+ BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysvar("panicSlice3Acap")
+ BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysvar("panicSlice3AcapU")
+ BoundsCheckFunc[ssa.BoundsSlice3B] = sysvar("panicSlice3B")
+ BoundsCheckFunc[ssa.BoundsSlice3BU] = sysvar("panicSlice3BU")
+ BoundsCheckFunc[ssa.BoundsSlice3C] = sysvar("panicSlice3C")
+ BoundsCheckFunc[ssa.BoundsSlice3CU] = sysvar("panicSlice3CU")
}
if thearch.LinkArch.PtrSize == 4 {
ExtendCheckFunc[ssa.BoundsIndex] = sysvar("panicExtendIndex")
diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go
index 2e9890d86c..f7f66a1255 100644
--- a/src/cmd/internal/obj/wasm/wasmobj.go
+++ b/src/cmd/internal/obj/wasm/wasmobj.go
@@ -129,6 +129,7 @@ var (
morestackNoCtxt *obj.LSym
gcWriteBarrier *obj.LSym
sigpanic *obj.LSym
+ sigpanic0 *obj.LSym
deferreturn *obj.LSym
jmpdefer *obj.LSym
)
@@ -141,8 +142,9 @@ const (
func instinit(ctxt *obj.Link) {
morestack = ctxt.Lookup("runtime.morestack")
morestackNoCtxt = ctxt.Lookup("runtime.morestack_noctxt")
- gcWriteBarrier = ctxt.LookupABI("runtime.gcWriteBarrier", obj.ABIInternal)
+ gcWriteBarrier = ctxt.Lookup("runtime.gcWriteBarrier")
sigpanic = ctxt.LookupABI("runtime.sigpanic", obj.ABIInternal)
+ sigpanic0 = ctxt.LookupABI("runtime.sigpanic", 0) // sigpanic called from assembly, which has ABI0
deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal)
// jmpdefer is defined in assembly as ABI0, but what we're
// looking for is the *call* to jmpdefer from the Go function
@@ -491,7 +493,7 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
}
// return value of call is on the top of the stack, indicating whether to unwind the WebAssembly stack
- if call.As == ACALLNORESUME && call.To.Sym != sigpanic { // sigpanic unwinds the stack, but it never resumes
+ if call.As == ACALLNORESUME && call.To.Sym != sigpanic && call.To.Sym != sigpanic0 { // sigpanic unwinds the stack, but it never resumes
// trying to unwind WebAssembly stack but call has no resume point, terminate with error
p = appendp(p, AIf)
p = appendp(p, obj.AUNDEF)
diff --git a/src/reflect/asm_amd64.s b/src/reflect/asm_amd64.s
index 5c8e56558c..fb28ab87f1 100644
--- a/src/reflect/asm_amd64.s
+++ b/src/reflect/asm_amd64.s
@@ -9,9 +9,7 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-// makeFuncStub must be ABIInternal because it is placed directly
-// in function values.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVQ DX, 0(SP)
LEAQ argframe+0(FP), CX
@@ -19,16 +17,14 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
MOVB $0, 24(SP)
LEAQ 24(SP), AX
MOVQ AX, 16(SP)
- CALL ·callReflect(SB)
+ CALL ·callReflect(SB)
RET
// methodValueCall is the code half of the function returned by makeMethodValue.
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-// methodValueCall must be ABIInternal because it is placed directly
-// in function values.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVQ DX, 0(SP)
LEAQ argframe+0(FP), CX
@@ -36,5 +32,5 @@ TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
MOVB $0, 24(SP)
LEAQ 24(SP), AX
MOVQ AX, 16(SP)
- CALL ·callMethod(SB)
+ CALL ·callMethod(SB)
RET
diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index 196252e1dd..19a3bb2d7d 100644
--- a/src/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -84,9 +84,7 @@ GLOBL _rt0_amd64_lib_argc<>(SB),NOPTR, $8
DATA _rt0_amd64_lib_argv<>(SB)/8, $0
GLOBL _rt0_amd64_lib_argv<>(SB),NOPTR, $8
-// Defined as ABIInternal since it does not use the stack-based Go ABI (and
-// in addition there are no calls to this entry point from Go code).
-TEXT runtime·rt0_go(SB),NOSPLIT,$0
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
// copy arguments forward on an even stack
MOVQ DI, AX // argc
MOVQ SI, BX // argv
@@ -231,13 +229,10 @@ ok:
// Prevent dead-code elimination of debugCallV1, which is
// intended to be called by debuggers.
- MOVQ $runtime·debugCallV1(SB), AX
+ MOVQ $runtime·debugCallV1(SB), AX
RET
-// mainPC is a function value for runtime.main, to be passed to newproc.
-// The reference to runtime.main is made via ABIInternal, since the
-// actual function (not the ABI0 wrapper) is needed by newproc.
-DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
+DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
GLOBL runtime·mainPC(SB),RODATA,$8
TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
@@ -473,7 +468,7 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0
JMP AX
// Note: can't just "JMP NAME(SB)" - bad inlining results.
-TEXT ·reflectcall(SB), NOSPLIT, $0-32
+TEXT ·reflectcall(SB), NOSPLIT, $0-32
MOVLQZX argsize+24(FP), CX
DISPATCH(runtime·call16, 16)
DISPATCH(runtime·call32, 32)
@@ -1359,11 +1354,8 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
RET
// The top-most function running on a goroutine
-// returns to goexit+PCQuantum. Defined as ABIInternal
-// so as to make it identifiable to traceback (this
-// function it used as a sentinel; traceback wants to
-// see the func PC, not a wrapper PC).
-TEXT runtime·goexit(SB),NOSPLIT,$0-0
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$0-0
BYTE $0x90 // NOP
CALL runtime·goexit1(SB) // does not return
// traceback from goexit1 must hit code range of goexit
@@ -1385,8 +1377,7 @@ TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
// - AX is the value being written at DI
// It clobbers FLAGS. It does not clobber any general-purpose registers,
// but may clobber others (e.g., SSE registers).
-// Defined as ABIInternal since it does not use the stack-based Go ABI.
-TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$120
+TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$120
// Save the registers clobbered by the fast path. This is slightly
// faster than having the caller spill these.
MOVQ R14, 104(SP)
@@ -1470,58 +1461,51 @@ flush:
JMP ret
// gcWriteBarrierCX is gcWriteBarrier, but with args in DI and CX.
-// Defined as ABIInternal since it does not use the stable Go ABI.
-TEXT runtime·gcWriteBarrierCX(SB),NOSPLIT,$0
+TEXT runtime·gcWriteBarrierCX(SB),NOSPLIT,$0
XCHGQ CX, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ CX, AX
RET
// gcWriteBarrierDX is gcWriteBarrier, but with args in DI and DX.
-// Defined as ABIInternal since it does not use the stable Go ABI.
-TEXT runtime·gcWriteBarrierDX(SB),NOSPLIT,$0
+TEXT runtime·gcWriteBarrierDX(SB),NOSPLIT,$0
XCHGQ DX, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ DX, AX
RET
// gcWriteBarrierBX is gcWriteBarrier, but with args in DI and BX.
-// Defined as ABIInternal since it does not use the stable Go ABI.
-TEXT runtime·gcWriteBarrierBX(SB),NOSPLIT,$0
+TEXT runtime·gcWriteBarrierBX(SB),NOSPLIT,$0
XCHGQ BX, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ BX, AX
RET
// gcWriteBarrierBP is gcWriteBarrier, but with args in DI and BP.
-// Defined as ABIInternal since it does not use the stable Go ABI.
-TEXT runtime·gcWriteBarrierBP(SB),NOSPLIT,$0
+TEXT runtime·gcWriteBarrierBP(SB),NOSPLIT,$0
XCHGQ BP, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ BP, AX
RET
// gcWriteBarrierSI is gcWriteBarrier, but with args in DI and SI.
-// Defined as ABIInternal since it does not use the stable Go ABI.
-TEXT runtime·gcWriteBarrierSI(SB),NOSPLIT,$0
+TEXT runtime·gcWriteBarrierSI(SB),NOSPLIT,$0
XCHGQ SI, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ SI, AX
RET
// gcWriteBarrierR8 is gcWriteBarrier, but with args in DI and R8.
-// Defined as ABIInternal since it does not use the stable Go ABI.
-TEXT runtime·gcWriteBarrierR8(SB),NOSPLIT,$0
+TEXT runtime·gcWriteBarrierR8(SB),NOSPLIT,$0
XCHGQ R8, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ R8, AX
RET
// gcWriteBarrierR9 is gcWriteBarrier, but with args in DI and R9.
-// Defined as ABIInternal since it does not use the stable Go ABI.
-TEXT runtime·gcWriteBarrierR9(SB),NOSPLIT,$0
+TEXT runtime·gcWriteBarrierR9(SB),NOSPLIT,$0
XCHGQ R9, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ R9, AX
RET
@@ -1560,10 +1544,7 @@ GLOBL debugCallFrameTooLarge<>(SB), RODATA, $20 // Size duplicated below
// obey escape analysis requirements. Specifically, it must not pass
// a stack pointer to an escaping argument. debugCallV1 cannot check
// this invariant.
-//
-// This is ABIInternal because Go code injects its PC directly into new
-// goroutine stacks.
-TEXT runtime·debugCallV1(SB),NOSPLIT,$152-0
+TEXT runtime·debugCallV1(SB),NOSPLIT,$152-0
// Save all registers that may contain pointers so they can be
// conservatively scanned.
//
@@ -1724,68 +1705,67 @@ TEXT runtime·debugCallPanicked(SB),NOSPLIT,$16-16
// in the caller's stack frame. These stubs write the args into that stack space and
// then tail call to the corresponding runtime handler.
// The tail call makes these stubs disappear in backtraces.
-// Defined as ABIInternal since they do not use the stack-based Go ABI.
-TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
+TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicIndex(SB)
-TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
+TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicIndexU(SB)
-TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAlen(SB)
-TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAlenU(SB)
-TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAcap(SB)
-TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAcapU(SB)
-TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSliceB(SB)
-TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSliceBU(SB)
-TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3Alen(SB)
-TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3AlenU(SB)
-TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3Acap(SB)
-TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3AcapU(SB)
-TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSlice3B(SB)
-TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSlice3BU(SB)
-TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSlice3C(SB)
-TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSlice3CU(SB)
diff --git a/src/runtime/asm_wasm.s b/src/runtime/asm_wasm.s
index fcb780f1dc..67e81adf0b 100644
--- a/src/runtime/asm_wasm.s
+++ b/src/runtime/asm_wasm.s
@@ -196,7 +196,7 @@ TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16
Get CTXT
I64Eqz
If
- CALLNORESUME runtime·sigpanic(SB)
+ CALLNORESUME runtime·sigpanic(SB)
End
// caller sp after CALL
@@ -300,7 +300,7 @@ TEXT ·reflectcall(SB), NOSPLIT, $0-32
I64Load fn+8(FP)
I64Eqz
If
- CALLNORESUME runtime·sigpanic(SB)
+ CALLNORESUME runtime·sigpanic(SB)
End
MOVW argsize+24(FP), R0
diff --git a/src/runtime/duff_amd64.s b/src/runtime/duff_amd64.s
index 2ff5bf6dbc..44dc75d297 100644
--- a/src/runtime/duff_amd64.s
+++ b/src/runtime/duff_amd64.s
@@ -4,7 +4,7 @@
#include "textflag.h"
-TEXT runtime·duffzero(SB), NOSPLIT, $0-0
+TEXT runtime·duffzero(SB), NOSPLIT, $0-0
MOVUPS X0,(DI)
MOVUPS X0,16(DI)
MOVUPS X0,32(DI)
@@ -103,7 +103,7 @@ TEXT runtime·duffzero(SB), NOSPLIT, $0-0
RET
-TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
+TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
MOVUPS (SI), X0
ADDQ $16, SI
MOVUPS X0, (DI)
diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go
index 1d614dd003..286f81489a 100644
--- a/src/runtime/mkpreempt.go
+++ b/src/runtime/mkpreempt.go
@@ -126,8 +126,7 @@ func header(arch string) {
}
fmt.Fprintf(out, "#include \"go_asm.h\"\n")
fmt.Fprintf(out, "#include \"textflag.h\"\n\n")
- fmt.Fprintf(out, "// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.\n")
- fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n")
+ fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n")
}
func p(f string, args ...interface{}) {
diff --git a/src/runtime/preempt_386.s b/src/runtime/preempt_386.s
index a803b24dc6..c3a5fa1f36 100644
--- a/src/runtime/preempt_386.s
+++ b/src/runtime/preempt_386.s
@@ -3,8 +3,7 @@
#include "go_asm.h"
#include "textflag.h"
-// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
PUSHFL
ADJSP $156
NOP SP
diff --git a/src/runtime/preempt_amd64.s b/src/runtime/preempt_amd64.s
index 92c664d79a..4765e9f448 100644
--- a/src/runtime/preempt_amd64.s
+++ b/src/runtime/preempt_amd64.s
@@ -3,8 +3,7 @@
#include "go_asm.h"
#include "textflag.h"
-// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
PUSHQ BP
MOVQ SP, BP
// Save flags before clobbering them
diff --git a/src/runtime/preempt_arm.s b/src/runtime/preempt_arm.s
index bbc9fbb1ea..8f243c0dcd 100644
--- a/src/runtime/preempt_arm.s
+++ b/src/runtime/preempt_arm.s
@@ -3,8 +3,7 @@
#include "go_asm.h"
#include "textflag.h"
-// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVW.W R14, -188(R13)
MOVW R0, 4(R13)
MOVW R1, 8(R13)
diff --git a/src/runtime/preempt_arm64.s b/src/runtime/preempt_arm64.s
index 2b70a28479..36ee13282c 100644
--- a/src/runtime/preempt_arm64.s
+++ b/src/runtime/preempt_arm64.s
@@ -3,8 +3,7 @@
#include "go_asm.h"
#include "textflag.h"
-// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVD R30, -496(RSP)
SUB $496, RSP
#ifdef GOOS_linux
diff --git a/src/runtime/preempt_mips64x.s b/src/runtime/preempt_mips64x.s
index 0d0c157c36..1e123e8077 100644
--- a/src/runtime/preempt_mips64x.s
+++ b/src/runtime/preempt_mips64x.s
@@ -5,8 +5,7 @@
#include "go_asm.h"
#include "textflag.h"
-// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVV R31, -488(R29)
SUBV $488, R29
MOVV R1, 8(R29)
diff --git a/src/runtime/preempt_mipsx.s b/src/runtime/preempt_mipsx.s
index 86d3a918d3..afac33e0a0 100644
--- a/src/runtime/preempt_mipsx.s
+++ b/src/runtime/preempt_mipsx.s
@@ -5,8 +5,7 @@
#include "go_asm.h"
#include "textflag.h"
-// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVW R31, -244(R29)
SUB $244, R29
MOVW R1, 4(R29)
diff --git a/src/runtime/preempt_ppc64x.s b/src/runtime/preempt_ppc64x.s
index 90634386db..b2d7e30ec7 100644
--- a/src/runtime/preempt_ppc64x.s
+++ b/src/runtime/preempt_ppc64x.s
@@ -5,8 +5,7 @@
#include "go_asm.h"
#include "textflag.h"
-// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVD R31, -488(R1)
MOVD LR, R31
MOVDU R31, -520(R1)
diff --git a/src/runtime/preempt_riscv64.s b/src/runtime/preempt_riscv64.s
index d4f9cc277f..eb68dcba2b 100644
--- a/src/runtime/preempt_riscv64.s
+++ b/src/runtime/preempt_riscv64.s
@@ -3,8 +3,7 @@
#include "go_asm.h"
#include "textflag.h"
-// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOV X1, -472(X2)
ADD $-472, X2
MOV X3, 8(X2)
diff --git a/src/runtime/preempt_s390x.s b/src/runtime/preempt_s390x.s
index c6f11571df..ca9e47cde1 100644
--- a/src/runtime/preempt_s390x.s
+++ b/src/runtime/preempt_s390x.s
@@ -3,8 +3,7 @@
#include "go_asm.h"
#include "textflag.h"
-// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
IPM R10
MOVD R14, -248(R15)
ADD $-248, R15
diff --git a/src/runtime/preempt_wasm.s b/src/runtime/preempt_wasm.s
index da90e8aa6d..0cf57d3d22 100644
--- a/src/runtime/preempt_wasm.s
+++ b/src/runtime/preempt_wasm.s
@@ -3,7 +3,6 @@
#include "go_asm.h"
#include "textflag.h"
-// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
// No async preemption on wasm
UNDEF
diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s
index 4a86b3371a..758d543203 100644
--- a/src/runtime/race_amd64.s
+++ b/src/runtime/race_amd64.s
@@ -41,9 +41,7 @@
// func runtime·raceread(addr uintptr)
// Called from instrumented code.
-// Defined as ABIInternal so as to avoid introducing a wrapper,
-// which would render runtime.getcallerpc ineffective.
-TEXT runtime·raceread(SB), NOSPLIT, $0-8
+TEXT runtime·raceread(SB), NOSPLIT, $0-8
MOVQ addr+0(FP), RARG1
MOVQ (SP), RARG2
// void __tsan_read(ThreadState *thr, void *addr, void *pc);
@@ -67,9 +65,7 @@ TEXT runtime·racereadpc(SB), NOSPLIT, $0-24
// func runtime·racewrite(addr uintptr)
// Called from instrumented code.
-// Defined as ABIInternal so as to avoid introducing a wrapper,
-// which would render runtime.getcallerpc ineffective.
-TEXT runtime·racewrite(SB), NOSPLIT, $0-8
+TEXT runtime·racewrite(SB), NOSPLIT, $0-8
MOVQ addr+0(FP), RARG1
MOVQ (SP), RARG2
// void __tsan_write(ThreadState *thr, void *addr, void *pc);
@@ -118,9 +114,7 @@ TEXT runtime·racereadrangepc1(SB), NOSPLIT, $0-24
// func runtime·racewriterange(addr, size uintptr)
// Called from instrumented code.
-// Defined as ABIInternal so as to avoid introducing a wrapper,
-// which would render runtime.getcallerpc ineffective.
-TEXT runtime·racewriterange(SB), NOSPLIT, $0-16
+TEXT runtime·racewriterange(SB), NOSPLIT, $0-16
MOVQ addr+0(FP), RARG1
MOVQ size+8(FP), RARG2
MOVQ (SP), RARG3
diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
index 37cb8dad03..681cd20274 100644
--- a/src/runtime/sys_linux_amd64.s
+++ b/src/runtime/sys_linux_amd64.s
@@ -380,8 +380,7 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
POPQ BP
RET
-// Defined as ABIInternal since it does not use the stack-based Go ABI.
-TEXT runtime·sigtramp(SB),NOSPLIT,$72
+TEXT runtime·sigtramp(SB),NOSPLIT,$72
// Save callee-saved C registers, since the caller may be a C signal handler.
MOVQ BX, bx-8(SP)
MOVQ BP, bp-16(SP) // save in case GOEXPERIMENT=noframepointer is set
@@ -408,8 +407,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$72
// Used instead of sigtramp in programs that use cgo.
// Arguments from kernel are in DI, SI, DX.
-// Defined as ABIInternal since it does not use the stack-based Go ABI.
-TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
+TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
// If no traceback function, do usual sigtramp.
MOVQ runtime·cgoTraceback(SB), AX
TESTQ AX, AX
@@ -452,12 +450,12 @@ TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
// The first three arguments, and the fifth, are already in registers.
// Set the two remaining arguments now.
MOVQ runtime·cgoTraceback(SB), CX
- MOVQ $runtime·sigtramp(SB), R9
+ MOVQ $runtime·sigtramp(SB), R9
MOVQ _cgo_callers(SB), AX
JMP AX
sigtramp:
- JMP runtime·sigtramp(SB)
+ JMP runtime·sigtramp(SB)
sigtrampnog:
// Signal arrived on a non-Go thread. If this is SIGPROF, get a
@@ -488,8 +486,7 @@ sigtrampnog:
// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/x86_64/sigaction.c
// The code that cares about the precise instructions used is:
// https://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/i386/linux-unwind.h?revision=219188&view=markup
-// Defined as ABIInternal since it does not use the stack-based Go ABI.
-TEXT runtime·sigreturn(SB),NOSPLIT,$0
+TEXT runtime·sigreturn(SB),NOSPLIT,$0
MOVQ $SYS_rt_sigreturn, AX
SYSCALL
INT $3 // not reached
--
cgit v1.3
From a313eec3869c609c0da2402a4cac2d32113d599c Mon Sep 17 00:00:00 2001
From: Than McIntosh
Date: Wed, 14 Oct 2020 08:36:11 -0400
Subject: reflect,runtime: use internal ABI for selected ASM routines, attempt
2
[This is a roll-forward of CL 262319, with a fix for some Darwin test
failures].
Change the definitions of selected runtime assembly routines
from ABI0 (the default) to ABIInternal. The ABIInternal def is
intended to indicate that these functions don't follow the existing Go
runtime ABI. In addition, convert the assembly reference to
runtime.main (from runtime.mainPC) to ABIInternal. Finally, for
functions such as "runtime.duffzero" that are called directly from
generated code, make sure that the compiler looks up the correct
ABI version.
This is intended to support the register abi work, however these
changes should not have any issues even when GOEXPERIMENT=regabi is
not in effect.
Updates #27539, #40724.
Change-Id: Idf507f1c06176073563845239e1a54dad51a9ea9
Reviewed-on: https://go-review.googlesource.com/c/go/+/266638
Trust: Than McIntosh
Run-TryBot: Than McIntosh
Reviewed-by: Cherry Zhang
TryBot-Result: Go Bot
---
src/cmd/compile/internal/gc/ssa.go | 86 ++++++++++++++++----------------
src/cmd/internal/obj/wasm/wasmobj.go | 6 +--
src/cmd/internal/obj/x86/obj6.go | 4 +-
src/reflect/asm_amd64.s | 12 +++--
src/runtime/asm_amd64.s | 96 ++++++++++++++++++++++--------------
src/runtime/asm_wasm.s | 4 +-
src/runtime/duff_amd64.s | 4 +-
src/runtime/mkpreempt.go | 3 +-
src/runtime/preempt_386.s | 3 +-
src/runtime/preempt_amd64.s | 3 +-
src/runtime/preempt_arm.s | 3 +-
src/runtime/preempt_arm64.s | 3 +-
src/runtime/preempt_mips64x.s | 3 +-
src/runtime/preempt_mipsx.s | 3 +-
src/runtime/preempt_ppc64x.s | 3 +-
src/runtime/preempt_riscv64.s | 3 +-
src/runtime/preempt_s390x.s | 3 +-
src/runtime/preempt_wasm.s | 3 +-
src/runtime/race_amd64.s | 12 +++--
src/runtime/sys_linux_amd64.s | 13 +++--
20 files changed, 156 insertions(+), 114 deletions(-)
(limited to 'src/reflect')
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 45d628cc5e..7388e4e3e8 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -72,9 +72,9 @@ func initssaconfig() {
deferproc = sysfunc("deferproc")
deferprocStack = sysfunc("deferprocStack")
Deferreturn = sysfunc("deferreturn")
- Duffcopy = sysvar("duffcopy") // asm func with special ABI
- Duffzero = sysvar("duffzero") // asm func with special ABI
- gcWriteBarrier = sysvar("gcWriteBarrier") // asm func with special ABI
+ Duffcopy = sysfunc("duffcopy")
+ Duffzero = sysfunc("duffzero")
+ gcWriteBarrier = sysfunc("gcWriteBarrier")
goschedguarded = sysfunc("goschedguarded")
growslice = sysfunc("growslice")
msanread = sysfunc("msanread")
@@ -105,51 +105,51 @@ func initssaconfig() {
// asm funcs with special ABI
if thearch.LinkArch.Name == "amd64" {
GCWriteBarrierReg = map[int16]*obj.LSym{
- x86.REG_AX: sysvar("gcWriteBarrier"),
- x86.REG_CX: sysvar("gcWriteBarrierCX"),
- x86.REG_DX: sysvar("gcWriteBarrierDX"),
- x86.REG_BX: sysvar("gcWriteBarrierBX"),
- x86.REG_BP: sysvar("gcWriteBarrierBP"),
- x86.REG_SI: sysvar("gcWriteBarrierSI"),
- x86.REG_R8: sysvar("gcWriteBarrierR8"),
- x86.REG_R9: sysvar("gcWriteBarrierR9"),
+ x86.REG_AX: sysfunc("gcWriteBarrier"),
+ x86.REG_CX: sysfunc("gcWriteBarrierCX"),
+ x86.REG_DX: sysfunc("gcWriteBarrierDX"),
+ x86.REG_BX: sysfunc("gcWriteBarrierBX"),
+ x86.REG_BP: sysfunc("gcWriteBarrierBP"),
+ x86.REG_SI: sysfunc("gcWriteBarrierSI"),
+ x86.REG_R8: sysfunc("gcWriteBarrierR8"),
+ x86.REG_R9: sysfunc("gcWriteBarrierR9"),
}
}
if thearch.LinkArch.Family == sys.Wasm {
- BoundsCheckFunc[ssa.BoundsIndex] = sysvar("goPanicIndex")
- BoundsCheckFunc[ssa.BoundsIndexU] = sysvar("goPanicIndexU")
- BoundsCheckFunc[ssa.BoundsSliceAlen] = sysvar("goPanicSliceAlen")
- BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysvar("goPanicSliceAlenU")
- BoundsCheckFunc[ssa.BoundsSliceAcap] = sysvar("goPanicSliceAcap")
- BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysvar("goPanicSliceAcapU")
- BoundsCheckFunc[ssa.BoundsSliceB] = sysvar("goPanicSliceB")
- BoundsCheckFunc[ssa.BoundsSliceBU] = sysvar("goPanicSliceBU")
- BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysvar("goPanicSlice3Alen")
- BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysvar("goPanicSlice3AlenU")
- BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysvar("goPanicSlice3Acap")
- BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysvar("goPanicSlice3AcapU")
- BoundsCheckFunc[ssa.BoundsSlice3B] = sysvar("goPanicSlice3B")
- BoundsCheckFunc[ssa.BoundsSlice3BU] = sysvar("goPanicSlice3BU")
- BoundsCheckFunc[ssa.BoundsSlice3C] = sysvar("goPanicSlice3C")
- BoundsCheckFunc[ssa.BoundsSlice3CU] = sysvar("goPanicSlice3CU")
+ BoundsCheckFunc[ssa.BoundsIndex] = sysfunc("goPanicIndex")
+ BoundsCheckFunc[ssa.BoundsIndexU] = sysfunc("goPanicIndexU")
+ BoundsCheckFunc[ssa.BoundsSliceAlen] = sysfunc("goPanicSliceAlen")
+ BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysfunc("goPanicSliceAlenU")
+ BoundsCheckFunc[ssa.BoundsSliceAcap] = sysfunc("goPanicSliceAcap")
+ BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysfunc("goPanicSliceAcapU")
+ BoundsCheckFunc[ssa.BoundsSliceB] = sysfunc("goPanicSliceB")
+ BoundsCheckFunc[ssa.BoundsSliceBU] = sysfunc("goPanicSliceBU")
+ BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysfunc("goPanicSlice3Alen")
+ BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysfunc("goPanicSlice3AlenU")
+ BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysfunc("goPanicSlice3Acap")
+ BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysfunc("goPanicSlice3AcapU")
+ BoundsCheckFunc[ssa.BoundsSlice3B] = sysfunc("goPanicSlice3B")
+ BoundsCheckFunc[ssa.BoundsSlice3BU] = sysfunc("goPanicSlice3BU")
+ BoundsCheckFunc[ssa.BoundsSlice3C] = sysfunc("goPanicSlice3C")
+ BoundsCheckFunc[ssa.BoundsSlice3CU] = sysfunc("goPanicSlice3CU")
} else {
- BoundsCheckFunc[ssa.BoundsIndex] = sysvar("panicIndex")
- BoundsCheckFunc[ssa.BoundsIndexU] = sysvar("panicIndexU")
- BoundsCheckFunc[ssa.BoundsSliceAlen] = sysvar("panicSliceAlen")
- BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysvar("panicSliceAlenU")
- BoundsCheckFunc[ssa.BoundsSliceAcap] = sysvar("panicSliceAcap")
- BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysvar("panicSliceAcapU")
- BoundsCheckFunc[ssa.BoundsSliceB] = sysvar("panicSliceB")
- BoundsCheckFunc[ssa.BoundsSliceBU] = sysvar("panicSliceBU")
- BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysvar("panicSlice3Alen")
- BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysvar("panicSlice3AlenU")
- BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysvar("panicSlice3Acap")
- BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysvar("panicSlice3AcapU")
- BoundsCheckFunc[ssa.BoundsSlice3B] = sysvar("panicSlice3B")
- BoundsCheckFunc[ssa.BoundsSlice3BU] = sysvar("panicSlice3BU")
- BoundsCheckFunc[ssa.BoundsSlice3C] = sysvar("panicSlice3C")
- BoundsCheckFunc[ssa.BoundsSlice3CU] = sysvar("panicSlice3CU")
+ BoundsCheckFunc[ssa.BoundsIndex] = sysfunc("panicIndex")
+ BoundsCheckFunc[ssa.BoundsIndexU] = sysfunc("panicIndexU")
+ BoundsCheckFunc[ssa.BoundsSliceAlen] = sysfunc("panicSliceAlen")
+ BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysfunc("panicSliceAlenU")
+ BoundsCheckFunc[ssa.BoundsSliceAcap] = sysfunc("panicSliceAcap")
+ BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysfunc("panicSliceAcapU")
+ BoundsCheckFunc[ssa.BoundsSliceB] = sysfunc("panicSliceB")
+ BoundsCheckFunc[ssa.BoundsSliceBU] = sysfunc("panicSliceBU")
+ BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysfunc("panicSlice3Alen")
+ BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysfunc("panicSlice3AlenU")
+ BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysfunc("panicSlice3Acap")
+ BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysfunc("panicSlice3AcapU")
+ BoundsCheckFunc[ssa.BoundsSlice3B] = sysfunc("panicSlice3B")
+ BoundsCheckFunc[ssa.BoundsSlice3BU] = sysfunc("panicSlice3BU")
+ BoundsCheckFunc[ssa.BoundsSlice3C] = sysfunc("panicSlice3C")
+ BoundsCheckFunc[ssa.BoundsSlice3CU] = sysfunc("panicSlice3CU")
}
if thearch.LinkArch.PtrSize == 4 {
ExtendCheckFunc[ssa.BoundsIndex] = sysvar("panicExtendIndex")
diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go
index f7f66a1255..2e9890d86c 100644
--- a/src/cmd/internal/obj/wasm/wasmobj.go
+++ b/src/cmd/internal/obj/wasm/wasmobj.go
@@ -129,7 +129,6 @@ var (
morestackNoCtxt *obj.LSym
gcWriteBarrier *obj.LSym
sigpanic *obj.LSym
- sigpanic0 *obj.LSym
deferreturn *obj.LSym
jmpdefer *obj.LSym
)
@@ -142,9 +141,8 @@ const (
func instinit(ctxt *obj.Link) {
morestack = ctxt.Lookup("runtime.morestack")
morestackNoCtxt = ctxt.Lookup("runtime.morestack_noctxt")
- gcWriteBarrier = ctxt.Lookup("runtime.gcWriteBarrier")
+ gcWriteBarrier = ctxt.LookupABI("runtime.gcWriteBarrier", obj.ABIInternal)
sigpanic = ctxt.LookupABI("runtime.sigpanic", obj.ABIInternal)
- sigpanic0 = ctxt.LookupABI("runtime.sigpanic", 0) // sigpanic called from assembly, which has ABI0
deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal)
// jmpdefer is defined in assembly as ABI0, but what we're
// looking for is the *call* to jmpdefer from the Go function
@@ -493,7 +491,7 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
}
// return value of call is on the top of the stack, indicating whether to unwind the WebAssembly stack
- if call.As == ACALLNORESUME && call.To.Sym != sigpanic && call.To.Sym != sigpanic0 { // sigpanic unwinds the stack, but it never resumes
+ if call.As == ACALLNORESUME && call.To.Sym != sigpanic { // sigpanic unwinds the stack, but it never resumes
// trying to unwind WebAssembly stack but call has no resume point, terminate with error
p = appendp(p, AIf)
p = appendp(p, obj.AUNDEF)
diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go
index e11fa13f65..184fb4308b 100644
--- a/src/cmd/internal/obj/x86/obj6.go
+++ b/src/cmd/internal/obj/x86/obj6.go
@@ -324,9 +324,9 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
// flags and duffzero on 386 does not otherwise do so).
var sym *obj.LSym
if p.As == obj.ADUFFZERO {
- sym = ctxt.Lookup("runtime.duffzero")
+ sym = ctxt.LookupABI("runtime.duffzero", obj.ABIInternal)
} else {
- sym = ctxt.Lookup("runtime.duffcopy")
+ sym = ctxt.LookupABI("runtime.duffcopy", obj.ABIInternal)
}
offset := p.To.Offset
p.As = mov
diff --git a/src/reflect/asm_amd64.s b/src/reflect/asm_amd64.s
index fb28ab87f1..5c8e56558c 100644
--- a/src/reflect/asm_amd64.s
+++ b/src/reflect/asm_amd64.s
@@ -9,7 +9,9 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
+// makeFuncStub must be ABIInternal because it is placed directly
+// in function values.
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVQ DX, 0(SP)
LEAQ argframe+0(FP), CX
@@ -17,14 +19,16 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
MOVB $0, 24(SP)
LEAQ 24(SP), AX
MOVQ AX, 16(SP)
- CALL ·callReflect(SB)
+ CALL ·callReflect(SB)
RET
// methodValueCall is the code half of the function returned by makeMethodValue.
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
+// methodValueCall must be ABIInternal because it is placed directly
+// in function values.
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVQ DX, 0(SP)
LEAQ argframe+0(FP), CX
@@ -32,5 +36,5 @@ TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
MOVB $0, 24(SP)
LEAQ 24(SP), AX
MOVQ AX, 16(SP)
- CALL ·callMethod(SB)
+ CALL ·callMethod(SB)
RET
diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index 19a3bb2d7d..196252e1dd 100644
--- a/src/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -84,7 +84,9 @@ GLOBL _rt0_amd64_lib_argc<>(SB),NOPTR, $8
DATA _rt0_amd64_lib_argv<>(SB)/8, $0
GLOBL _rt0_amd64_lib_argv<>(SB),NOPTR, $8
-TEXT runtime·rt0_go(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stack-based Go ABI (and
+// in addition there are no calls to this entry point from Go code).
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
// copy arguments forward on an even stack
MOVQ DI, AX // argc
MOVQ SI, BX // argv
@@ -229,10 +231,13 @@ ok:
// Prevent dead-code elimination of debugCallV1, which is
// intended to be called by debuggers.
- MOVQ $runtime·debugCallV1(SB), AX
+ MOVQ $runtime·debugCallV1(SB), AX
RET
-DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
+// mainPC is a function value for runtime.main, to be passed to newproc.
+// The reference to runtime.main is made via ABIInternal, since the
+// actual function (not the ABI0 wrapper) is needed by newproc.
+DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
GLOBL runtime·mainPC(SB),RODATA,$8
TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
@@ -468,7 +473,7 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0
JMP AX
// Note: can't just "JMP NAME(SB)" - bad inlining results.
-TEXT ·reflectcall(SB), NOSPLIT, $0-32
+TEXT ·reflectcall(SB), NOSPLIT, $0-32
MOVLQZX argsize+24(FP), CX
DISPATCH(runtime·call16, 16)
DISPATCH(runtime·call32, 32)
@@ -1354,8 +1359,11 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
RET
// The top-most function running on a goroutine
-// returns to goexit+PCQuantum.
-TEXT runtime·goexit(SB),NOSPLIT,$0-0
+// returns to goexit+PCQuantum. Defined as ABIInternal
+// so as to make it identifiable to traceback (this
+// function it used as a sentinel; traceback wants to
+// see the func PC, not a wrapper PC).
+TEXT runtime·goexit(SB),NOSPLIT,$0-0
BYTE $0x90 // NOP
CALL runtime·goexit1(SB) // does not return
// traceback from goexit1 must hit code range of goexit
@@ -1377,7 +1385,8 @@ TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
// - AX is the value being written at DI
// It clobbers FLAGS. It does not clobber any general-purpose registers,
// but may clobber others (e.g., SSE registers).
-TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$120
+// Defined as ABIInternal since it does not use the stack-based Go ABI.
+TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$120
// Save the registers clobbered by the fast path. This is slightly
// faster than having the caller spill these.
MOVQ R14, 104(SP)
@@ -1461,51 +1470,58 @@ flush:
JMP ret
// gcWriteBarrierCX is gcWriteBarrier, but with args in DI and CX.
-TEXT runtime·gcWriteBarrierCX(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierCX(SB),NOSPLIT,$0
XCHGQ CX, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ CX, AX
RET
// gcWriteBarrierDX is gcWriteBarrier, but with args in DI and DX.
-TEXT runtime·gcWriteBarrierDX(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierDX(SB),NOSPLIT,$0
XCHGQ DX, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ DX, AX
RET
// gcWriteBarrierBX is gcWriteBarrier, but with args in DI and BX.
-TEXT runtime·gcWriteBarrierBX(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierBX(SB),NOSPLIT,$0
XCHGQ BX, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ BX, AX
RET
// gcWriteBarrierBP is gcWriteBarrier, but with args in DI and BP.
-TEXT runtime·gcWriteBarrierBP(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierBP(SB),NOSPLIT,$0
XCHGQ BP, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ BP, AX
RET
// gcWriteBarrierSI is gcWriteBarrier, but with args in DI and SI.
-TEXT runtime·gcWriteBarrierSI(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierSI(SB),NOSPLIT,$0
XCHGQ SI, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ SI, AX
RET
// gcWriteBarrierR8 is gcWriteBarrier, but with args in DI and R8.
-TEXT runtime·gcWriteBarrierR8(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierR8(SB),NOSPLIT,$0
XCHGQ R8, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ R8, AX
RET
// gcWriteBarrierR9 is gcWriteBarrier, but with args in DI and R9.
-TEXT runtime·gcWriteBarrierR9(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stable Go ABI.
+TEXT runtime·gcWriteBarrierR9(SB),NOSPLIT,$0
XCHGQ R9, AX
- CALL runtime·gcWriteBarrier(SB)
+ CALL runtime·gcWriteBarrier(SB)
XCHGQ R9, AX
RET
@@ -1544,7 +1560,10 @@ GLOBL debugCallFrameTooLarge<>(SB), RODATA, $20 // Size duplicated below
// obey escape analysis requirements. Specifically, it must not pass
// a stack pointer to an escaping argument. debugCallV1 cannot check
// this invariant.
-TEXT runtime·debugCallV1(SB),NOSPLIT,$152-0
+//
+// This is ABIInternal because Go code injects its PC directly into new
+// goroutine stacks.
+TEXT runtime·debugCallV1(SB),NOSPLIT,$152-0
// Save all registers that may contain pointers so they can be
// conservatively scanned.
//
@@ -1705,67 +1724,68 @@ TEXT runtime·debugCallPanicked(SB),NOSPLIT,$16-16
// in the caller's stack frame. These stubs write the args into that stack space and
// then tail call to the corresponding runtime handler.
// The tail call makes these stubs disappear in backtraces.
-TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
+// Defined as ABIInternal since they do not use the stack-based Go ABI.
+TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicIndex(SB)
-TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
+TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicIndexU(SB)
-TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAlen(SB)
-TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAlenU(SB)
-TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAcap(SB)
-TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSliceAcapU(SB)
-TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSliceB(SB)
-TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSliceBU(SB)
-TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3Alen(SB)
-TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3AlenU(SB)
-TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3Acap(SB)
-TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
MOVQ DX, x+0(FP)
MOVQ BX, y+8(FP)
JMP runtime·goPanicSlice3AcapU(SB)
-TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSlice3B(SB)
-TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
MOVQ CX, x+0(FP)
MOVQ DX, y+8(FP)
JMP runtime·goPanicSlice3BU(SB)
-TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSlice3C(SB)
-TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
+TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
MOVQ AX, x+0(FP)
MOVQ CX, y+8(FP)
JMP runtime·goPanicSlice3CU(SB)
diff --git a/src/runtime/asm_wasm.s b/src/runtime/asm_wasm.s
index 67e81adf0b..fcb780f1dc 100644
--- a/src/runtime/asm_wasm.s
+++ b/src/runtime/asm_wasm.s
@@ -196,7 +196,7 @@ TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16
Get CTXT
I64Eqz
If
- CALLNORESUME runtime·sigpanic(SB)
+ CALLNORESUME runtime·sigpanic(SB)
End
// caller sp after CALL
@@ -300,7 +300,7 @@ TEXT ·reflectcall(SB), NOSPLIT, $0-32
I64Load fn+8(FP)
I64Eqz
If
- CALLNORESUME runtime·sigpanic(SB)
+ CALLNORESUME runtime·sigpanic(SB)
End
MOVW argsize+24(FP), R0
diff --git a/src/runtime/duff_amd64.s b/src/runtime/duff_amd64.s
index 44dc75d297..2ff5bf6dbc 100644
--- a/src/runtime/duff_amd64.s
+++ b/src/runtime/duff_amd64.s
@@ -4,7 +4,7 @@
#include "textflag.h"
-TEXT runtime·duffzero(SB), NOSPLIT, $0-0
+TEXT runtime·duffzero(SB), NOSPLIT, $0-0
MOVUPS X0,(DI)
MOVUPS X0,16(DI)
MOVUPS X0,32(DI)
@@ -103,7 +103,7 @@ TEXT runtime·duffzero(SB), NOSPLIT, $0-0
RET
-TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
+TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
MOVUPS (SI), X0
ADDQ $16, SI
MOVUPS X0, (DI)
diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go
index 286f81489a..1d614dd003 100644
--- a/src/runtime/mkpreempt.go
+++ b/src/runtime/mkpreempt.go
@@ -126,7 +126,8 @@ func header(arch string) {
}
fmt.Fprintf(out, "#include \"go_asm.h\"\n")
fmt.Fprintf(out, "#include \"textflag.h\"\n\n")
- fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n")
+ fmt.Fprintf(out, "// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.\n")
+ fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n")
}
func p(f string, args ...interface{}) {
diff --git a/src/runtime/preempt_386.s b/src/runtime/preempt_386.s
index c3a5fa1f36..a803b24dc6 100644
--- a/src/runtime/preempt_386.s
+++ b/src/runtime/preempt_386.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
PUSHFL
ADJSP $156
NOP SP
diff --git a/src/runtime/preempt_amd64.s b/src/runtime/preempt_amd64.s
index 4765e9f448..92c664d79a 100644
--- a/src/runtime/preempt_amd64.s
+++ b/src/runtime/preempt_amd64.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
PUSHQ BP
MOVQ SP, BP
// Save flags before clobbering them
diff --git a/src/runtime/preempt_arm.s b/src/runtime/preempt_arm.s
index 8f243c0dcd..bbc9fbb1ea 100644
--- a/src/runtime/preempt_arm.s
+++ b/src/runtime/preempt_arm.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVW.W R14, -188(R13)
MOVW R0, 4(R13)
MOVW R1, 8(R13)
diff --git a/src/runtime/preempt_arm64.s b/src/runtime/preempt_arm64.s
index 36ee13282c..2b70a28479 100644
--- a/src/runtime/preempt_arm64.s
+++ b/src/runtime/preempt_arm64.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVD R30, -496(RSP)
SUB $496, RSP
#ifdef GOOS_linux
diff --git a/src/runtime/preempt_mips64x.s b/src/runtime/preempt_mips64x.s
index 1e123e8077..0d0c157c36 100644
--- a/src/runtime/preempt_mips64x.s
+++ b/src/runtime/preempt_mips64x.s
@@ -5,7 +5,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVV R31, -488(R29)
SUBV $488, R29
MOVV R1, 8(R29)
diff --git a/src/runtime/preempt_mipsx.s b/src/runtime/preempt_mipsx.s
index afac33e0a0..86d3a918d3 100644
--- a/src/runtime/preempt_mipsx.s
+++ b/src/runtime/preempt_mipsx.s
@@ -5,7 +5,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVW R31, -244(R29)
SUB $244, R29
MOVW R1, 4(R29)
diff --git a/src/runtime/preempt_ppc64x.s b/src/runtime/preempt_ppc64x.s
index b2d7e30ec7..90634386db 100644
--- a/src/runtime/preempt_ppc64x.s
+++ b/src/runtime/preempt_ppc64x.s
@@ -5,7 +5,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOVD R31, -488(R1)
MOVD LR, R31
MOVDU R31, -520(R1)
diff --git a/src/runtime/preempt_riscv64.s b/src/runtime/preempt_riscv64.s
index eb68dcba2b..d4f9cc277f 100644
--- a/src/runtime/preempt_riscv64.s
+++ b/src/runtime/preempt_riscv64.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
MOV X1, -472(X2)
ADD $-472, X2
MOV X3, 8(X2)
diff --git a/src/runtime/preempt_s390x.s b/src/runtime/preempt_s390x.s
index ca9e47cde1..c6f11571df 100644
--- a/src/runtime/preempt_s390x.s
+++ b/src/runtime/preempt_s390x.s
@@ -3,7 +3,8 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
IPM R10
MOVD R14, -248(R15)
ADD $-248, R15
diff --git a/src/runtime/preempt_wasm.s b/src/runtime/preempt_wasm.s
index 0cf57d3d22..da90e8aa6d 100644
--- a/src/runtime/preempt_wasm.s
+++ b/src/runtime/preempt_wasm.s
@@ -3,6 +3,7 @@
#include "go_asm.h"
#include "textflag.h"
-TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
+// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.
+TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0
// No async preemption on wasm
UNDEF
diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s
index 758d543203..4a86b3371a 100644
--- a/src/runtime/race_amd64.s
+++ b/src/runtime/race_amd64.s
@@ -41,7 +41,9 @@
// func runtime·raceread(addr uintptr)
// Called from instrumented code.
-TEXT runtime·raceread(SB), NOSPLIT, $0-8
+// Defined as ABIInternal so as to avoid introducing a wrapper,
+// which would render runtime.getcallerpc ineffective.
+TEXT runtime·raceread(SB), NOSPLIT, $0-8
MOVQ addr+0(FP), RARG1
MOVQ (SP), RARG2
// void __tsan_read(ThreadState *thr, void *addr, void *pc);
@@ -65,7 +67,9 @@ TEXT runtime·racereadpc(SB), NOSPLIT, $0-24
// func runtime·racewrite(addr uintptr)
// Called from instrumented code.
-TEXT runtime·racewrite(SB), NOSPLIT, $0-8
+// Defined as ABIInternal so as to avoid introducing a wrapper,
+// which would render runtime.getcallerpc ineffective.
+TEXT runtime·racewrite(SB), NOSPLIT, $0-8
MOVQ addr+0(FP), RARG1
MOVQ (SP), RARG2
// void __tsan_write(ThreadState *thr, void *addr, void *pc);
@@ -114,7 +118,9 @@ TEXT runtime·racereadrangepc1(SB), NOSPLIT, $0-24
// func runtime·racewriterange(addr, size uintptr)
// Called from instrumented code.
-TEXT runtime·racewriterange(SB), NOSPLIT, $0-16
+// Defined as ABIInternal so as to avoid introducing a wrapper,
+// which would render runtime.getcallerpc ineffective.
+TEXT runtime·racewriterange(SB), NOSPLIT, $0-16
MOVQ addr+0(FP), RARG1
MOVQ size+8(FP), RARG2
MOVQ (SP), RARG3
diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
index 681cd20274..37cb8dad03 100644
--- a/src/runtime/sys_linux_amd64.s
+++ b/src/runtime/sys_linux_amd64.s
@@ -380,7 +380,8 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
POPQ BP
RET
-TEXT runtime·sigtramp(SB),NOSPLIT,$72
+// Defined as ABIInternal since it does not use the stack-based Go ABI.
+TEXT runtime·sigtramp(SB),NOSPLIT,$72
// Save callee-saved C registers, since the caller may be a C signal handler.
MOVQ BX, bx-8(SP)
MOVQ BP, bp-16(SP) // save in case GOEXPERIMENT=noframepointer is set
@@ -407,7 +408,8 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$72
// Used instead of sigtramp in programs that use cgo.
// Arguments from kernel are in DI, SI, DX.
-TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stack-based Go ABI.
+TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
// If no traceback function, do usual sigtramp.
MOVQ runtime·cgoTraceback(SB), AX
TESTQ AX, AX
@@ -450,12 +452,12 @@ TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
// The first three arguments, and the fifth, are already in registers.
// Set the two remaining arguments now.
MOVQ runtime·cgoTraceback(SB), CX
- MOVQ $runtime·sigtramp(SB), R9
+ MOVQ $runtime·sigtramp(SB), R9
MOVQ _cgo_callers(SB), AX
JMP AX
sigtramp:
- JMP runtime·sigtramp(SB)
+ JMP runtime·sigtramp(SB)
sigtrampnog:
// Signal arrived on a non-Go thread. If this is SIGPROF, get a
@@ -486,7 +488,8 @@ sigtrampnog:
// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/x86_64/sigaction.c
// The code that cares about the precise instructions used is:
// https://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/i386/linux-unwind.h?revision=219188&view=markup
-TEXT runtime·sigreturn(SB),NOSPLIT,$0
+// Defined as ABIInternal since it does not use the stack-based Go ABI.
+TEXT runtime·sigreturn(SB),NOSPLIT,$0
MOVQ $SYS_rt_sigreturn, AX
SYSCALL
INT $3 // not reached
--
cgit v1.3
From ebc1b8ef2854e7006349275bc3b2306022200bbc Mon Sep 17 00:00:00 2001
From: Cuong Manh Le
Date: Thu, 22 Oct 2020 21:52:50 +0700
Subject: reflect: update NumMethod doc for interface type
Updates #42123
Change-Id: Ieb43b65c88d15b2475b6f3dd9672c44e7831cc34
Reviewed-on: https://go-review.googlesource.com/c/go/+/264357
Trust: Cuong Manh Le
Run-TryBot: Cuong Manh Le
TryBot-Result: Go Bot
Reviewed-by: Russ Cox
---
src/reflect/type.go | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
(limited to 'src/reflect')
diff --git a/src/reflect/type.go b/src/reflect/type.go
index a3a616701b..a2076bb3f1 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -50,13 +50,13 @@ type Type interface {
// It panics if i is not in the range [0, NumMethod()).
//
// For a non-interface type T or *T, the returned Method's Type and Func
- // fields describe a function whose first argument is the receiver.
+ // fields describe a function whose first argument is the receiver,
+ // and only exported methods are accessible.
//
// For an interface type, the returned Method's Type field gives the
// method signature, without a receiver, and the Func field is nil.
//
- // Only exported methods are accessible and they are sorted in
- // lexicographic order.
+ // Methods are sorted in lexicographic order.
Method(int) Method
// MethodByName returns the method with that name in the type's
@@ -69,7 +69,9 @@ type Type interface {
// method signature, without a receiver, and the Func field is nil.
MethodByName(string) (Method, bool)
- // NumMethod returns the number of exported methods in the type's method set.
+ // NumMethod returns the number of methods accessible using Method.
+ //
+ // Note that NumMethod counts unexported methods only for interface types.
NumMethod() int
// Name returns the type's name within its package for a defined type.
--
cgit v1.3
From f0ff6d4a67ec9a956aa655d487543da034cf576b Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Wed, 25 Nov 2020 13:47:42 -0800
Subject: reflect: fix Value.Convert for int-to-string conversions (regression)
The bug was introduced by https://golang.org/cl/220844.
Updates #42792.
Fixes #42835.
Change-Id: I03065c7526488aded35ef2f800b7162e1606877a
Reviewed-on: https://go-review.googlesource.com/c/go/+/273326
Trust: Robert Griesemer
Run-TryBot: Robert Griesemer
TryBot-Result: Go Bot
Reviewed-by: Ian Lance Taylor
---
src/reflect/all_test.go | 3 +++
src/reflect/value.go | 12 ++++++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
(limited to 'src/reflect')
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index a12712d254..b01158635f 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -4007,9 +4007,12 @@ var convertTests = []struct {
{V(int16(-3)), V(string("\uFFFD"))},
{V(int32(-4)), V(string("\uFFFD"))},
{V(int64(-5)), V(string("\uFFFD"))},
+ {V(int64(-1 << 32)), V(string("\uFFFD"))},
+ {V(int64(1 << 32)), V(string("\uFFFD"))},
{V(uint(0x110001)), V(string("\uFFFD"))},
{V(uint32(0x110002)), V(string("\uFFFD"))},
{V(uint64(0x110003)), V(string("\uFFFD"))},
+ {V(uint64(1 << 32)), V(string("\uFFFD"))},
{V(uintptr(0x110004)), V(string("\uFFFD"))},
// named string
diff --git a/src/reflect/value.go b/src/reflect/value.go
index bf926a7453..1f185b52e4 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -2681,12 +2681,20 @@ func cvtComplex(v Value, t Type) Value {
// convertOp: intXX -> string
func cvtIntString(v Value, t Type) Value {
- return makeString(v.flag.ro(), string(rune(v.Int())), t)
+ s := "\uFFFD"
+ if x := v.Int(); int64(rune(x)) == x {
+ s = string(rune(x))
+ }
+ return makeString(v.flag.ro(), s, t)
}
// convertOp: uintXX -> string
func cvtUintString(v Value, t Type) Value {
- return makeString(v.flag.ro(), string(rune(v.Uint())), t)
+ s := "\uFFFD"
+ if x := v.Uint(); uint64(rune(x)) == x {
+ s = string(rune(x))
+ }
+ return makeString(v.flag.ro(), s, t)
}
// convertOp: []byte -> string
--
cgit v1.3
From 9b8c27255893faf01e82227164a59baad1ff0011 Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Wed, 2 Dec 2020 18:25:19 -0800
Subject: reflect: document multiple keys in struct tags
For #40281
Fixes #42959
Change-Id: Ibc4769fda1592a1373ec720ea30baf319c0a0136
Reviewed-on: https://go-review.googlesource.com/c/go/+/274448
Trust: Ian Lance Taylor
Reviewed-by: Rob Pike
Reviewed-by: Dmitri Shuralyov
---
src/reflect/type.go | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
(limited to 'src/reflect')
diff --git a/src/reflect/type.go b/src/reflect/type.go
index a2076bb3f1..1f1e70d485 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -1104,12 +1104,16 @@ type StructField struct {
// A StructTag is the tag string in a struct field.
//
-// By convention, tag strings are a concatenation of
-// optionally space-separated key:"value" pairs.
-// Each key is a non-empty string consisting of non-control
-// characters other than space (U+0020 ' '), quote (U+0022 '"'),
-// and colon (U+003A ':'). Each value is quoted using U+0022 '"'
-// characters and Go string literal syntax.
+// By convention, tag strings are a mapping of keys to values.
+// The format is key:"value". Each key is a non-empty string consisting
+// of non-control characters other than space (U+0020 ' '),
+// quote (U+0022 '"'), and colon (U+003A ':'). Each value is quoted
+// using U+0022 '"' characters and Go string literal syntax.
+// Multiple key-value mappings are separated by zero or more spaces, as in
+// key1:"value1" key2:"value2"
+// Multiple keys may map to a single shared value by separating the keys
+// with spaces, as in
+// key1 key2:"value"
type StructTag string
// Get returns the value associated with key in the tag string.
--
cgit v1.3