aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCuong Manh Le <cuong.manhle.vn@gmail.com>2021-02-17 15:14:21 +0700
committerCuong Manh Le <cuong.manhle.vn@gmail.com>2021-02-23 06:01:29 +0000
commite52149822b54811cedaaa87013de3fa4bc634e95 (patch)
tree34bdc306bf2c00c662add4a459ea5dcff0e4d670
parent86deb459de6a309503aa445a7d686bd139354e5e (diff)
downloadgo-e52149822b54811cedaaa87013de3fa4bc634e95.tar.gz
go-e52149822b54811cedaaa87013de3fa4bc634e95.zip
cmd/compile: simplify assert{E,I}2I{,2} calling conventions
This CL rebases CL 273694 on top of master with @mdempsky's permission. For assertE2I and assertI2I, there's no need to pass through the interface's data pointer: it's always going to come back unmodified. For assertE2I2 and assertI2I2, there's no need for an extra bool result parameter: it's redundant with testing the returned interface value for nil. Change-Id: Ic92d4409ad381952f875d3d74b8cf11c32702fa6 Reviewed-on: https://go-review.googlesource.com/c/go/+/292892 Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com> Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
-rw-r--r--src/cmd/compile/internal/ssagen/ssa.go23
-rw-r--r--src/cmd/compile/internal/typecheck/builtin.go10
-rw-r--r--src/cmd/compile/internal/typecheck/builtin/runtime.go8
-rw-r--r--src/runtime/iface.go28
-rw-r--r--src/runtime/mfinal.go4
5 files changed, 34 insertions, 39 deletions
diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go
index 6b1ddebd32..e13ca90d33 100644
--- a/src/cmd/compile/internal/ssagen/ssa.go
+++ b/src/cmd/compile/internal/ssagen/ssa.go
@@ -6075,18 +6075,23 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val
if base.Debug.TypeAssert > 0 {
base.WarnfAt(n.Pos(), "type assertion not inlined")
}
- if n.X.Type().IsEmptyInterface() {
- if commaok {
- call := s.rtcall(ir.Syms.AssertE2I2, true, []*types.Type{n.Type(), types.Types[types.TBOOL]}, target, iface)
- return call[0], call[1]
+ if !commaok {
+ fn := ir.Syms.AssertI2I
+ if n.X.Type().IsEmptyInterface() {
+ fn = ir.Syms.AssertE2I
}
- return s.rtcall(ir.Syms.AssertE2I, true, []*types.Type{n.Type()}, target, iface)[0], nil
+ data := s.newValue1(ssa.OpIData, types.Types[types.TUNSAFEPTR], iface)
+ tab := s.newValue1(ssa.OpITab, byteptr, iface)
+ tab = s.rtcall(fn, true, []*types.Type{byteptr}, target, tab)[0]
+ return s.newValue2(ssa.OpIMake, n.Type(), tab, data), nil
}
- if commaok {
- call := s.rtcall(ir.Syms.AssertI2I2, true, []*types.Type{n.Type(), types.Types[types.TBOOL]}, target, iface)
- return call[0], call[1]
+ fn := ir.Syms.AssertI2I2
+ if n.X.Type().IsEmptyInterface() {
+ fn = ir.Syms.AssertE2I2
}
- return s.rtcall(ir.Syms.AssertI2I, true, []*types.Type{n.Type()}, target, iface)[0], nil
+ res = s.rtcall(fn, true, []*types.Type{n.Type()}, target, iface)[0]
+ resok = s.newValue2(ssa.OpNeqInter, types.Types[types.TBOOL], res, s.constInterface(n.Type()))
+ return
}
if base.Debug.TypeAssert > 0 {
diff --git a/src/cmd/compile/internal/typecheck/builtin.go b/src/cmd/compile/internal/typecheck/builtin.go
index b095a014f0..3c7776d9ae 100644
--- a/src/cmd/compile/internal/typecheck/builtin.go
+++ b/src/cmd/compile/internal/typecheck/builtin.go
@@ -80,10 +80,10 @@ var runtimeDecls = [...]struct {
{"convT2Enoptr", funcTag, 59},
{"convT2I", funcTag, 59},
{"convT2Inoptr", funcTag, 59},
- {"assertE2I", funcTag, 57},
- {"assertE2I2", funcTag, 60},
- {"assertI2I", funcTag, 57},
- {"assertI2I2", funcTag, 60},
+ {"assertE2I", funcTag, 60},
+ {"assertE2I2", funcTag, 57},
+ {"assertI2I", funcTag, 60},
+ {"assertI2I2", funcTag, 57},
{"panicdottypeE", funcTag, 61},
{"panicdottypeI", funcTag, 61},
{"panicnildottype", funcTag, 62},
@@ -280,7 +280,7 @@ func runtimeTypes() []*types.Type {
typs[57] = newSig(params(typs[1], typs[2]), params(typs[2]))
typs[58] = newSig(params(typs[2]), params(typs[7]))
typs[59] = newSig(params(typs[1], typs[3]), params(typs[2]))
- typs[60] = newSig(params(typs[1], typs[2]), params(typs[2], typs[6]))
+ typs[60] = newSig(params(typs[1], typs[1]), params(typs[1]))
typs[61] = newSig(params(typs[1], typs[1], typs[1]), nil)
typs[62] = newSig(params(typs[1]), nil)
typs[63] = types.NewPtr(typs[5])
diff --git a/src/cmd/compile/internal/typecheck/builtin/runtime.go b/src/cmd/compile/internal/typecheck/builtin/runtime.go
index ad82a9b349..d5e00afcf8 100644
--- a/src/cmd/compile/internal/typecheck/builtin/runtime.go
+++ b/src/cmd/compile/internal/typecheck/builtin/runtime.go
@@ -101,10 +101,10 @@ func convT2I(tab *byte, elem *any) (ret any)
func convT2Inoptr(tab *byte, elem *any) (ret any)
// interface type assertions x.(T)
-func assertE2I(typ *byte, iface any) (ret any)
-func assertE2I2(typ *byte, iface any) (ret any, b bool)
-func assertI2I(typ *byte, iface any) (ret any)
-func assertI2I2(typ *byte, iface any) (ret any, b bool)
+func assertE2I(inter *byte, typ *byte) *byte
+func assertE2I2(inter *byte, eface any) (ret any)
+func assertI2I(inter *byte, tab *byte) *byte
+func assertI2I2(inter *byte, iface any) (ret any)
func panicdottypeE(have, want, iface *byte)
func panicdottypeI(have, want, iface *byte)
func panicnildottype(want *byte)
diff --git a/src/runtime/iface.go b/src/runtime/iface.go
index 0504b89363..02b18dabff 100644
--- a/src/runtime/iface.go
+++ b/src/runtime/iface.go
@@ -447,23 +447,18 @@ func convI2I(inter *interfacetype, i iface) (r iface) {
return
}
-func assertI2I(inter *interfacetype, i iface) (r iface) {
- tab := i.tab
+func assertI2I(inter *interfacetype, tab *itab) *itab {
if tab == nil {
// explicit conversions require non-nil interface value.
panic(&TypeAssertionError{nil, nil, &inter.typ, ""})
}
if tab.inter == inter {
- r.tab = tab
- r.data = i.data
- return
+ return tab
}
- r.tab = getitab(inter, tab._type, false)
- r.data = i.data
- return
+ return getitab(inter, tab._type, false)
}
-func assertI2I2(inter *interfacetype, i iface) (r iface, b bool) {
+func assertI2I2(inter *interfacetype, i iface) (r iface) {
tab := i.tab
if tab == nil {
return
@@ -476,22 +471,18 @@ func assertI2I2(inter *interfacetype, i iface) (r iface, b bool) {
}
r.tab = tab
r.data = i.data
- b = true
return
}
-func assertE2I(inter *interfacetype, e eface) (r iface) {
- t := e._type
+func assertE2I(inter *interfacetype, t *_type) *itab {
if t == nil {
// explicit conversions require non-nil interface value.
panic(&TypeAssertionError{nil, nil, &inter.typ, ""})
}
- r.tab = getitab(inter, t, false)
- r.data = e.data
- return
+ return getitab(inter, t, false)
}
-func assertE2I2(inter *interfacetype, e eface) (r iface, b bool) {
+func assertE2I2(inter *interfacetype, e eface) (r iface) {
t := e._type
if t == nil {
return
@@ -502,18 +493,17 @@ func assertE2I2(inter *interfacetype, e eface) (r iface, b bool) {
}
r.tab = tab
r.data = e.data
- b = true
return
}
//go:linkname reflect_ifaceE2I reflect.ifaceE2I
func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
- *dst = assertE2I(inter, e)
+ *dst = iface{assertE2I(inter, e._type), e.data}
}
//go:linkname reflectlite_ifaceE2I internal/reflectlite.ifaceE2I
func reflectlite_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
- *dst = assertE2I(inter, e)
+ *dst = iface{assertE2I(inter, e._type), e.data}
}
func iterate_itabs(fn func(*itab)) {
diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go
index 7d0313be12..e92ec80e3c 100644
--- a/src/runtime/mfinal.go
+++ b/src/runtime/mfinal.go
@@ -214,7 +214,7 @@ func runfinq() {
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))
+ (*iface)(frame).tab = assertE2I(ityp, (*eface)(frame)._type)
}
default:
throw("bad kind in runfinq")
@@ -403,7 +403,7 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
// ok - satisfies empty interface
goto okarg
}
- if _, ok := assertE2I2(ityp, *efaceOf(&obj)); ok {
+ if iface := assertE2I2(ityp, *efaceOf(&obj)); iface.tab != nil {
goto okarg
}
}