mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
cmd/compile: redo IsRuntimePkg/IsReflectPkg predicate
Currently, the types package has IsRuntimePkg and IsReflectPkg predicates for testing if a Pkg is the runtime or reflect packages. IsRuntimePkg returns "true" for any "CompilingRuntime" package, which includes all of the packages imported by the runtime. This isn't inherently wrong, except that all but one use of it is of the form "is this Sym a specific runtime.X symbol?" for which we clearly only want the package "runtime" itself. IsRuntimePkg was introduced (as isRuntime) in CL 37538 as part of separating the real runtime package from the compiler built-in fake runtime package. As of that CL, the "runtime" package couldn't import any other packages, so this was adequate at the time. We could fix this by just changing the implementation of IsRuntimePkg, but the meaning of this API is clearly somewhat ambiguous. Instead, we replace it with a new RuntimeSymName function that returns the name of a symbol if it's in package "runtime", or "" if not. This is what every call site (except one) actually wants, which lets us simplify the callers, and also more clearly addresses the ambiguity between package "runtime" and the general concept of a runtime package. IsReflectPkg doesn't have the same issue of ambiguity, but it parallels IsRuntimePkg and is used in the same way, so we replace it with a new ReflectSymName for consistency. Change-Id: If3a81d7d11732a9ab2cac9488d17508415cfb597 Reviewed-on: https://go-review.googlesource.com/c/go/+/521696 Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
9f9bb26880
commit
596120fdc6
@ -505,6 +505,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
|
|||||||
if n == nil {
|
if n == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
opSwitch:
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
// Call is okay if inlinable and we have the budget for the body.
|
// Call is okay if inlinable and we have the budget for the body.
|
||||||
case ir.OCALLFUNC:
|
case ir.OCALLFUNC:
|
||||||
@ -516,22 +517,19 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
|
|||||||
var cheap bool
|
var cheap bool
|
||||||
if n.X.Op() == ir.ONAME {
|
if n.X.Op() == ir.ONAME {
|
||||||
name := n.X.(*ir.Name)
|
name := n.X.(*ir.Name)
|
||||||
if name.Class == ir.PFUNC && types.IsRuntimePkg(name.Sym().Pkg) {
|
if name.Class == ir.PFUNC {
|
||||||
fn := name.Sym().Name
|
switch fn := types.RuntimeSymName(name.Sym()); fn {
|
||||||
if fn == "getcallerpc" || fn == "getcallersp" {
|
case "getcallerpc", "getcallersp":
|
||||||
v.reason = "call to " + fn
|
v.reason = "call to " + fn
|
||||||
return true
|
return true
|
||||||
}
|
case "throw":
|
||||||
if fn == "throw" {
|
|
||||||
v.budget -= inlineExtraThrowCost
|
v.budget -= inlineExtraThrowCost
|
||||||
break
|
break opSwitch
|
||||||
}
|
}
|
||||||
}
|
// Special case for reflect.noescape. It does just type
|
||||||
// Special case for reflect.noescpae. It does just type
|
// conversions to appease the escape analysis, and doesn't
|
||||||
// conversions to appease the escape analysis, and doesn't
|
// generate code.
|
||||||
// generate code.
|
if types.ReflectSymName(name.Sym()) == "noescape" {
|
||||||
if name.Class == ir.PFUNC && types.IsReflectPkg(name.Sym().Pkg) {
|
|
||||||
if name.Sym().Name == "noescape" {
|
|
||||||
cheap = true
|
cheap = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -553,7 +551,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
|
|||||||
if meth := ir.MethodExprName(n.X); meth != nil {
|
if meth := ir.MethodExprName(n.X); meth != nil {
|
||||||
if fn := meth.Func; fn != nil {
|
if fn := meth.Func; fn != nil {
|
||||||
s := fn.Sym()
|
s := fn.Sym()
|
||||||
if types.IsRuntimePkg(s.Pkg) && s.Name == "heapBits.nextArena" {
|
if types.RuntimeSymName(s) == "heapBits.nextArena" {
|
||||||
// Special case: explicitly allow mid-stack inlining of
|
// Special case: explicitly allow mid-stack inlining of
|
||||||
// runtime.heapBits.next even though it calls slow-path
|
// runtime.heapBits.next even though it calls slow-path
|
||||||
// runtime.heapBits.nextArena.
|
// runtime.heapBits.nextArena.
|
||||||
@ -906,8 +904,11 @@ func inlnode(callerfn *ir.Func, n ir.Node, bigCaller bool, inlCalls *[]*ir.Inlin
|
|||||||
// even when package reflect was compiled without it (#35073).
|
// even when package reflect was compiled without it (#35073).
|
||||||
if meth := ir.MethodExprName(n.X); meth != nil {
|
if meth := ir.MethodExprName(n.X); meth != nil {
|
||||||
s := meth.Sym()
|
s := meth.Sym()
|
||||||
if base.Debug.Checkptr != 0 && types.IsReflectPkg(s.Pkg) && (s.Name == "Value.UnsafeAddr" || s.Name == "Value.Pointer") {
|
if base.Debug.Checkptr != 0 {
|
||||||
return n
|
switch types.ReflectSymName(s) {
|
||||||
|
case "Value.UnsafeAddr", "Value.Pointer":
|
||||||
|
return n
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ func unified(m posMap, noders []*noder) {
|
|||||||
// For functions originally came from package runtime,
|
// For functions originally came from package runtime,
|
||||||
// mark as norace to prevent instrumenting, see issue #60439.
|
// mark as norace to prevent instrumenting, see issue #60439.
|
||||||
for _, fn := range target.Funcs {
|
for _, fn := range target.Funcs {
|
||||||
if !base.Flag.CompilingRuntime && types.IsRuntimePkg(fn.Sym().Pkg) {
|
if !base.Flag.CompilingRuntime && types.RuntimeSymName(fn.Sym()) != "" {
|
||||||
fn.Pragma |= ir.Norace
|
fn.Pragma |= ir.Norace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ func (c *nowritebarrierrecChecker) findExtraCalls(nn ir.Node) {
|
|||||||
if fn.Class != ir.PFUNC || fn.Defn == nil {
|
if fn.Class != ir.PFUNC || fn.Defn == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !types.IsRuntimePkg(fn.Sym().Pkg) || fn.Sym().Name != "systemstack" {
|
if types.RuntimeSymName(fn.Sym()) != "systemstack" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ func tcCall(n *ir.CallExpr, top int) ir.Node {
|
|||||||
n.SetType(l.Type().Result(0).Type)
|
n.SetType(l.Type().Result(0).Type)
|
||||||
|
|
||||||
if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.ONAME {
|
if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.ONAME {
|
||||||
if sym := n.X.(*ir.Name).Sym(); types.IsRuntimePkg(sym.Pkg) && sym.Name == "getg" {
|
if sym := n.X.(*ir.Name).Sym(); types.RuntimeSymName(sym) == "getg" {
|
||||||
// Emit code for runtime.getg() directly instead of calling function.
|
// Emit code for runtime.getg() directly instead of calling function.
|
||||||
// Most such rewrites (for example the similar one for math.Sqrt) should be done in walk,
|
// Most such rewrites (for example the similar one for math.Sqrt) should be done in walk,
|
||||||
// so that the ordering pass can make sure to preserve the semantics of the original code
|
// so that the ordering pass can make sure to preserve the semantics of the original code
|
||||||
|
@ -1841,17 +1841,22 @@ func IsMethodApplicable(t *Type, m *Field) bool {
|
|||||||
return t.IsPtr() || !m.Type.Recv().Type.IsPtr() || IsInterfaceMethod(m.Type) || m.Embedded == 2
|
return t.IsPtr() || !m.Type.Recv().Type.IsPtr() || IsInterfaceMethod(m.Type) || m.Embedded == 2
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRuntimePkg reports whether p is package runtime.
|
// RuntimeSymName returns the name of s if it's in package "runtime"; otherwise
|
||||||
func IsRuntimePkg(p *Pkg) bool {
|
// it returns "".
|
||||||
if base.Flag.CompilingRuntime && p == LocalPkg {
|
func RuntimeSymName(s *Sym) string {
|
||||||
return true
|
if s.Pkg.Path == "runtime" {
|
||||||
|
return s.Name
|
||||||
}
|
}
|
||||||
return p.Path == "runtime"
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsReflectPkg reports whether p is package reflect.
|
// ReflectSymName returns the name of s if it's in package "reflect"; otherwise
|
||||||
func IsReflectPkg(p *Pkg) bool {
|
// it returns "".
|
||||||
return p.Path == "reflect"
|
func ReflectSymName(s *Sym) string {
|
||||||
|
if s.Pkg.Path == "reflect" {
|
||||||
|
return s.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNoInstrumentPkg reports whether p is a package that
|
// IsNoInstrumentPkg reports whether p is a package that
|
||||||
|
@ -631,7 +631,7 @@ func walkPrint(nn *ir.CallExpr, init *ir.Nodes) ir.Node {
|
|||||||
on = typecheck.LookupRuntime("printslice")
|
on = typecheck.LookupRuntime("printslice")
|
||||||
on = typecheck.SubstArgTypes(on, n.Type()) // any-1
|
on = typecheck.SubstArgTypes(on, n.Type()) // any-1
|
||||||
case types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, types.TUINTPTR:
|
case types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, types.TUINTPTR:
|
||||||
if types.IsRuntimePkg(n.Type().Sym().Pkg) && n.Type().Sym().Name == "hex" {
|
if types.RuntimeSymName(n.Type().Sym()) == "hex" {
|
||||||
on = typecheck.LookupRuntime("printhex")
|
on = typecheck.LookupRuntime("printhex")
|
||||||
} else {
|
} else {
|
||||||
on = typecheck.LookupRuntime("printuint")
|
on = typecheck.LookupRuntime("printuint")
|
||||||
|
@ -993,7 +993,7 @@ func usemethod(n *ir.CallExpr) {
|
|||||||
|
|
||||||
// Check that first result type is "reflect.Method". Note that we have to check sym name and sym package
|
// Check that first result type is "reflect.Method". Note that we have to check sym name and sym package
|
||||||
// separately, as we can't check for exact string "reflect.Method" reliably (e.g., see #19028 and #38515).
|
// separately, as we can't check for exact string "reflect.Method" reliably (e.g., see #19028 and #38515).
|
||||||
if s := t.Result(0).Type.Sym(); s != nil && s.Name == "Method" && types.IsReflectPkg(s.Pkg) {
|
if s := t.Result(0).Type.Sym(); s != nil && types.ReflectSymName(s) == "Method" {
|
||||||
ir.CurFunc.SetReflectMethod(true)
|
ir.CurFunc.SetReflectMethod(true)
|
||||||
// The LSym is initialized at this point. We need to set the attribute on the LSym.
|
// The LSym is initialized at this point. We need to set the attribute on the LSym.
|
||||||
ir.CurFunc.LSym.Set(obj.AttrReflectMethod, true)
|
ir.CurFunc.LSym.Set(obj.AttrReflectMethod, true)
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
// errorcheck -+
|
// errorcheck -+ -p=runtime
|
||||||
|
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Test go:nowritebarrier and related directives.
|
// Test go:nowritebarrier and related directives.
|
||||||
|
// This must appear to be in package runtime so the compiler
|
||||||
|
// recognizes "systemstack".
|
||||||
|
|
||||||
package p
|
package runtime
|
||||||
|
|
||||||
type t struct {
|
type t struct {
|
||||||
f *t
|
f *t
|
||||||
|
Loading…
x
Reference in New Issue
Block a user