1
0
mirror of https://github.com/golang/go synced 2024-10-01 16:38:34 -06:00
Commit Graph

8 Commits

Author SHA1 Message Date
Alan Donovan
94c387c610 go.tools/pointer: implement (reflect.Value).Call.
The implementation follows the basic pattern of an indirect
function call (genDynamicCall).

We use the same trick as SetFinalizer so that direct calls to
(r.V).Call, which are overwhelmingly the norm, are inlined.

Bug fix (and simplification): calling untag() to unbox a
reflect.Value is wrong for reflect.Values containing interfaces
(rare).  Now, we call untag for concrete types and typeFilter
for interface types, and we can use this pattern in all cases.
It corresponds to the ssa.TypeAssert operator, so we call
it typeAssert.  Added tests to cover this.

We also specialize reflect.{In,Out} when the operand is an int
literal.

+ Tests.

Also:
- make taggedValue() panic, not return nil, eliminating many checks.
  We call isTaggedValue for the one place that cares.
- pointer_test: recover from panics in Analyze() and dump the log.

R=crawshaw
CC=golang-dev
https://golang.org/cl/14426050
2013-10-29 21:57:53 -04:00
Alan Donovan
8bb20b8231 go.tools/pointer: more reflection.
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
2013-10-17 09:26:44 -04:00
Alan Donovan
2299ac6bf3 go.tools/pointer: make sole callsite available to intrinsics in non-shared contours.
This information can be used to specialize such calls, e.g.
- report location of unsound calls (done for reflect.NewAt)
- exploit argument information (done for constant 'dir' parameter to reflect.ChanOf)

+ tests.

R=crawshaw
CC=golang-dev
https://golang.org/cl/14517046
2013-10-09 12:41:55 -04:00
Alan Donovan
3371b79a96 go.tools/pointer: reflect, part 2: channels.
(reflect.Value).Send
        (reflect.Value).TrySend
        (reflect.Value).Recv
        (reflect.Value).TryRecv
        (reflect.Type).ChanOf
        (reflect.Type).In
        (reflect.Type).Out
        reflect.Indirect
        reflect.MakeChan

Also:
- specialize genInvoke when the receiver is a reflect.Type under the
  assumption that there's only one possible concrete type.  This
  makes all reflect.Type operations context-sensitive since the calls
  are no longer dynamic.
- Rename all variables to match the actual parameter names used in
  the reflect API.
- Add pointer.Config.Reflection flag
  (exposed in oracle as --reflect, default false) to enable reflection.
  It currently adds about 20% running time.  I'll make it true after
  the presolver is implemented.
- Simplified worklist datatype and solver main loop slightly
  (~10% speed improvement).
- Use addLabel() utility to add a label to a PTS.

(Working on my 3 yr old 2x2GHz+4GB Mac vs 8x4GHz+24GB workstation,
one really notices the cost of pointer analysis.
Note to self: time to implement presolver.)

R=crawshaw
CC=golang-dev
https://golang.org/cl/13242062
2013-09-23 16:13:01 -04:00
Alan Donovan
3b5de067a1 go.tools/pointer: reflection, part 1: maps, and some core features.
Core:
        reflect.TypeOf
        reflect.ValueOf
        reflect.Zero
        reflect.Value.Interface
Maps:
        (reflect.Value).MapIndex
        (reflect.Value).MapKeys
        (reflect.Value).SetMapIndex
        (*reflect.rtype).Elem
        (*reflect.rtype).Key

+ tests:
  pointer/testdata/mapreflect.go.
  oracle/testdata/src/main/reflection.go.

Interface objects (T, V...) have been renamed "tagged objects".

Abstraction: we model reflect.Value similar to
interface{}---as a pointer that points only to tagged
objects---but a reflect.Value may also point to an "indirect
tagged object", one in which the payload V is of type *T not T.
These are required because reflect.Values can hold lvalues,
e.g. when derived via Field() or Elem(), though we won't use
them till we get to structs and pointers.

Solving: each reflection intrinsic defines a new constraint
and resolution rule.  Because of the nature of reflection,
generalizing across types, the resolution rules dynamically
create additional complex constraints during solving, where
previously only simple (copy) constraints were created.
This requires some solver changes:

  The work done before the main solver loop (to attach new
  constraints to the graph) is now done before each iteration,
  in processNewConstraints.

  Its loop over constraints is broken into two passes:
  the first handles base (addr-of) constraints,
  the second handles simple and complex constraints.

  constraint.init() has been inlined.  The only behaviour that
  varies across constraints is ptr()

Sadly this will pessimize presolver optimisations, when we get
there; such is the price of reflection.

Objects: reflection intrinsics create objects (i.e. cause
memory allocations) with no SSA operation.  We will represent
them as the cgnode of the instrinsic (e.g. reflect.New), so we
extend Labels and node.data to represent objects as a product
(not sum) of ssa.Value and cgnode and pull this out into its
own type, struct object.  This simplifies a number of
invariants and saves space.  The ntObject flag is now
represented by obj!=nil; the other flags are moved into
object.

cgnodes are now always recorded in objects/Labels for which it
is appropriate (all but those for globals, constants and the
shared contours for functions).

Also:
- Prepopulate the flattenMemo cache to consider reflect.Value
  a fake pointer, not a struct.
- Improve accessors and documentation on type Label.
- @conctypes assertions renamed @types (since dyn. types needn't be concrete).
- add oracle 'describe' test on an interface (missing, an oversight).

R=crawshaw
CC=golang-dev
https://golang.org/cl/13418048
2013-09-16 09:49:10 -04:00
Alan Donovan
0b534359c5 go.tools/pointer: summaries for more intrinsics.
All have been audited to ensure that they have NoEffect on
aliasing.  Also: clarify the requirements for NoEffect to
explicitly disclaim trivial loads/stores.

R=crawshaw
CC=golang-dev
https://golang.org/cl/13314045
2013-09-10 14:40:37 -04:00
Alan Donovan
713699d8ad go.tools: add copyright messages to source files.
R=r
CC=golang-dev
https://golang.org/cl/13305043
2013-08-27 18:49:13 -04:00
Alan Donovan
6643abb26c go.tools/pointer: inclusion-based pointer analysis for Go.
Suggested reading order:
- doc.go
- api.go, analysis.go, callgraph.go, labels.go
- print.go, util.go
- gen.go
- solve.go
- pointer_test.go, testdata/*
- intrinsics.go (none are implemented yet)

R=dannyb, gri, crawshaw, 0xjnml
CC=golang-dev
https://golang.org/cl/10618043
2013-08-22 12:27:55 -04:00