mirror of
https://github.com/golang/go
synced 2024-11-18 14:54:40 -07:00
8bb20b8231
Support for: (*reflect.rtype).Field (*reflect.rtype).FieldByName reflect.MakeSlice runtime.SetFinalizer Details: - analysis locates ssa.Functions for (reflect.Value).Call and runtime.SetFinalizer during startup to that it can special-case them during genCall. ('Call' is forthcoming.) - The callsite.targets mechanism is only used for dynamic calls now. For static calls we call callEdge during constraint generation; this is a minor optimisation. - Static calls to SetFinalizer are inlined so that the call appears to go direct to the finalizer. (We'll use the same trick for (reflect.Value).Call.) - runtime.FuncForPC: treat as a no-op. - Fixed pointer_test to properly deal with expectations that are multi-sets. - Inlined rtypeMethodByNameConstraint.addMethod. - More tests. R=crawshaw CC=golang-dev https://golang.org/cl/14682045
99 lines
2.3 KiB
Go
99 lines
2.3 KiB
Go
// Copyright 2013 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package pointer
|
|
|
|
// This file defines our implementation of the call.Graph API.
|
|
|
|
import (
|
|
"fmt"
|
|
"go/token"
|
|
|
|
"code.google.com/p/go.tools/call"
|
|
"code.google.com/p/go.tools/ssa"
|
|
)
|
|
|
|
// cgraph implements call.Graph.
|
|
type cgraph struct {
|
|
root *cgnode
|
|
nodes []*cgnode
|
|
}
|
|
|
|
func (g *cgraph) Nodes() []call.GraphNode {
|
|
nodes := make([]call.GraphNode, len(g.nodes))
|
|
for i, node := range g.nodes {
|
|
nodes[i] = node
|
|
}
|
|
return nodes
|
|
}
|
|
|
|
func (g *cgraph) Root() call.GraphNode {
|
|
return g.root
|
|
}
|
|
|
|
// cgnode implements call.GraphNode.
|
|
type cgnode struct {
|
|
fn *ssa.Function
|
|
obj nodeid // start of this contour's object block
|
|
sites []*callsite // ordered list of callsites within this function
|
|
callersite *callsite // where called from, if known; nil for shared contours
|
|
}
|
|
|
|
func (n *cgnode) Func() *ssa.Function {
|
|
return n.fn
|
|
}
|
|
|
|
func (n *cgnode) Sites() []ssa.CallInstruction {
|
|
sites := make([]ssa.CallInstruction, len(n.sites))
|
|
for i, site := range n.sites {
|
|
sites[i] = site.instr
|
|
}
|
|
return sites
|
|
}
|
|
|
|
func (n *cgnode) Edges() []call.Edge {
|
|
var numEdges int
|
|
for _, site := range n.sites {
|
|
numEdges += len(site.callees)
|
|
}
|
|
edges := make([]call.Edge, 0, numEdges)
|
|
|
|
for _, site := range n.sites {
|
|
for _, callee := range site.callees {
|
|
edges = append(edges, call.Edge{Caller: n, Site: site.instr, Callee: callee})
|
|
}
|
|
}
|
|
return edges
|
|
}
|
|
|
|
func (n *cgnode) String() string {
|
|
return fmt.Sprintf("cg%d:%s", n.obj, n.fn)
|
|
}
|
|
|
|
// A callsite represents a single call site within a cgnode;
|
|
// it is implicitly context-sensitive.
|
|
// callsites never represent calls to built-ins;
|
|
// they are handled as intrinsics.
|
|
//
|
|
type callsite struct {
|
|
targets nodeid // pts(·) contains objects for dynamically called functions
|
|
instr ssa.CallInstruction // the call instruction; nil for synthetic/intrinsic
|
|
callees []*cgnode // unordered set of callees of this site
|
|
}
|
|
|
|
func (c *callsite) String() string {
|
|
if c.instr != nil {
|
|
return c.instr.Common().Description()
|
|
}
|
|
return "synthetic function call"
|
|
}
|
|
|
|
// pos returns the source position of this callsite, or token.NoPos if implicit.
|
|
func (c *callsite) pos() token.Pos {
|
|
if c.instr != nil {
|
|
return c.instr.Pos()
|
|
}
|
|
return token.NoPos
|
|
}
|