See issue 4949 for a full explanation.
Allocs go from 1 to zero in the non-addressable case.
Fixes#4949.
BenchmarkInterfaceBig 90 14 -84.01%
BenchmarkInterfaceSmall 14 14 +0.00%
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/12646043
It changes an exported API, and breaks the build.
««« original CL description
reflect: use unsafe.Pointer in StringHeader and SliceHeader
Relates to issue 5193.
R=r
CC=golang-dev
https://golang.org/cl/8363045
»»»
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/8357051
The new garbage collector (CL 6114046) may find the fake *[]byte value
and interpret its contents as bytes rather than as potential pointers.
This may lead the garbage collector to free memory blocks that
shouldn't be freed.
R=dvyukov, rsc, dave, minux.ma, remyoudompheng, iant
CC=golang-dev
https://golang.org/cl/7000059
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes#2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
This CL makes the runtime understand that the type of
the len or cap of a map, slice, or string is 'int', not 'int32',
and it is also careful to distinguish between function arguments
and results of type 'int' vs type 'int32'.
In the runtime, the new typedefs 'intgo' and 'uintgo' refer
to Go int and uint. The C types int and uint continue to be
unavailable (cause intentional compile errors).
This CL does not change the meaning of int, but it should make
the eventual change of the meaning of int on amd64 a bit
smoother.
Update #2188.
R=iant, r, dave, remyoudompheng
CC=golang-dev
https://golang.org/cl/6551067
unsafe: delete Typeof, Reflect, Unreflect, New, NewArray
Part of issue 2955 and issue 2968.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5650069
Making Value opaque means we can drop the interface kludges
in favor of a significantly simpler and faster representation.
v.Kind() will be a prime candidate for inlining too.
On a Thinkpad X201s using -benchtime 10:
benchmark old ns/op new ns/op delta
json.BenchmarkCodeEncoder 284391780 157415960 -44.65%
json.BenchmarkCodeMarshal 286979140 158992020 -44.60%
json.BenchmarkCodeDecoder 717175800 388288220 -45.86%
json.BenchmarkCodeUnmarshal 734470500 404548520 -44.92%
json.BenchmarkCodeUnmarshalReuse 707172280 385258720 -45.52%
json.BenchmarkSkipValue 24630036 18557062 -24.66%
benchmark old MB/s new MB/s speedup
json.BenchmarkCodeEncoder 6.82 12.33 1.81x
json.BenchmarkCodeMarshal 6.76 12.20 1.80x
json.BenchmarkCodeDecoder 2.71 5.00 1.85x
json.BenchmarkCodeUnmarshal 2.64 4.80 1.82x
json.BenchmarkCodeUnmarshalReuse 2.74 5.04 1.84x
json.BenchmarkSkipValue 77.92 103.42 1.33x
I cannot explain why BenchmarkSkipValue gets faster.
Maybe it is one of those code alignment things.
R=iant, r, gri, r
CC=golang-dev
https://golang.org/cl/5373101
Revert workaround in compiler and
revert test for compiler workaround.
Tested that the 386 build continues to fail if
the gc change is made without the reflect change.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5312041
Had been allowing it for use by fmt, but it is too hard to lock down.
Fix other packages not to depend on it.
R=r, r
CC=golang-dev
https://golang.org/cl/5266054
-s now means *disable* escape analysis.
Fix escape leaks for struct/slice/map literals.
Add ... tracking.
Rewrite new(T) and slice literal into stack allocation when safe.
Add annotations to reflect.
Reflect is too chummy with the compiler,
so changes like these affect it more than they should.
R=lvd, dave, gustavo
CC=golang-dev
https://golang.org/cl/4954043
This allows code that wants to handle
[]byte separately to get at the actual slice
instead of just at individual bytes.
It seems to come up often enough.
R=r
CC=golang-dev
https://golang.org/cl/4942051
This was initially pushed as part of CL 4876046, found
when logic in exp/template was using the method on
an Invalid value.
R=rsc
CC=golang-dev
https://golang.org/cl/4890043
It's probably just an oversight that it doesn't work,
perhaps caused by analogy with Cap.
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/4634125
This CL makes reflect require that values be assignable to the target type
in exactly the same places where that is the rule in Go. It also adds
the Implements and AssignableTo methods so that callers can check
the types themselves so as to avoid a panic.
Before this CL, reflect required strict type identity.
This CL expands Call to accept and correctly marshal arbitrary
argument lists for variadic functions; it introduces CallSlice for use
in the case where the slice for the variadic argument is already known.
Fixes#327.
Fixes#1212.
R=r, dsymonds
CC=golang-dev
https://golang.org/cl/4439058
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042