Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(599)

Issue 4435042: code review 4435042: reflect: more efficient; cannot Set result of NewValue ... (Closed)

Can't Edit
Can't Publish+Mail
Start Review
Created:
13 years, 7 months ago by rsc
Modified:
13 years, 7 months ago
Reviewers:
rog
CC:
r, golang-dev
Visibility:
Public.

Description

reflect: more efficient; cannot Set result of NewValue anymore * 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 http://codereview.appspot.com/4423043/.

Patch Set 1 #

Patch Set 2 : diff -r 0cab3021a860 https://go.googlecode.com/hg/ #

Total comments: 1

Patch Set 3 : diff -r 0cab3021a860 https://go.googlecode.com/hg/ #

Patch Set 4 : diff -r ad82ac65f73c https://go.googlecode.com/hg/ #

Patch Set 5 : diff -r ad82ac65f73c https://go.googlecode.com/hg/ #

Total comments: 41

Patch Set 6 : diff -r ad82ac65f73c https://go.googlecode.com/hg/ #

Total comments: 1

Patch Set 7 : diff -r fb36bd46b1fb https://go.googlecode.com/hg #

Patch Set 8 : diff -r df02112a28f1 https://go.googlecode.com/hg #

Unified diffs Side-by-side diffs Delta from patch set Stats (+1320 lines, -1147 lines) Patch
M src/pkg/reflect/all_test.go View 1 20 chunks +101 lines, -81 lines 0 comments Download
M src/pkg/reflect/deepequal.go View 1 2 3 3 chunks +23 lines, -22 lines 0 comments Download
M src/pkg/reflect/type.go View 1 2 3 4 5 6 chunks +38 lines, -13 lines 0 comments Download
M src/pkg/reflect/value.go View 1 2 3 4 5 6 24 chunks +894 lines, -900 lines 0 comments Download
M src/pkg/runtime/Makefile View 1 1 chunk +0 lines, -1 line 0 comments Download
M src/pkg/runtime/chan.c View 1 2 3 4 5 4 chunks +96 lines, -7 lines 0 comments Download
M src/pkg/runtime/hashmap.c View 1 6 chunks +116 lines, -5 lines 0 comments Download
M src/pkg/runtime/iface.c View 1 2 3 4 5 16 chunks +52 lines, -2 lines 0 comments Download
R src/pkg/runtime/reflect.goc View 1 1 chunk +0 lines, -114 lines 0 comments Download
M src/pkg/runtime/runtime.h View 1 2 3 2 chunks +0 lines, -2 lines 0 comments Download

Messages

Total messages: 15
rsc
Hello r (cc: golang-dev@googlegroups.com), I'd like you to review this change to https://go.googlecode.com/hg/
13 years, 7 months ago (2011-04-18 16:21:15 UTC) #1
rsc
CL description expanded using the text of the mail I sent to golang-dev last week.
13 years, 7 months ago (2011-04-18 16:40:47 UTC) #2
r
http://codereview.appspot.com/4435042/diff/11001/src/pkg/reflect/type.go File src/pkg/reflect/type.go (right): http://codereview.appspot.com/4435042/diff/11001/src/pkg/reflect/type.go#newcode788 src/pkg/reflect/type.go:788: if uintptr(x)&3 != 0 { here's that 3 again. ...
13 years, 7 months ago (2011-04-18 16:57:56 UTC) #3
rsc
Hello r (cc: golang-dev@googlegroups.com), Please take another look.
13 years, 7 months ago (2011-04-18 17:19:10 UTC) #4
rsc
http://codereview.appspot.com/4435042/diff/2001/src/pkg/runtime/iface.c File src/pkg/runtime/iface.c (right): http://codereview.appspot.com/4435042/diff/2001/src/pkg/runtime/iface.c#newcode649 src/pkg/runtime/iface.c:649: ret = *(Eface*)((uintptr)e.type&~(uintptr)7); xxx should return nil http://codereview.appspot.com/4435042/diff/11001/src/pkg/reflect/type.go File ...
13 years, 7 months ago (2011-04-18 17:19:19 UTC) #5
rsc
> http://codereview.appspot.com/4435042/diff/2001/src/pkg/runtime/iface.c#newcode649 > src/pkg/runtime/iface.c:649: ret = > *(Eface*)((uintptr)e.type&~(uintptr)7); > xxx should return nil Ignore this ...
13 years, 7 months ago (2011-04-18 17:21:50 UTC) #6
r
LGTM http://codereview.appspot.com/4435042/diff/3013/src/pkg/reflect/value.go File src/pkg/reflect/value.go (right): http://codereview.appspot.com/4435042/diff/3013/src/pkg/reflect/value.go#newcode1451 src/pkg/reflect/value.go:1451: // If sk is an in line array, ...
13 years, 7 months ago (2011-04-18 17:31:10 UTC) #7
rsc
*** Submitted as http://code.google.com/p/go/source/detail?r=47bd15b15056 *** reflect: more efficient; cannot Set result of NewValue anymore * ...
13 years, 7 months ago (2011-04-18 18:35:40 UTC) #8
rog
On 18 April 2011 19:35, <rsc@golang.org> wrote: > (1) If you have a reflect.Value v, ...
13 years, 7 months ago (2011-04-18 21:53:13 UTC) #9
rsc
> obviously i can use your suggested workaround, but > it would be nice if ...
13 years, 7 months ago (2011-04-18 22:49:27 UTC) #10
rog
On 18 April 2011 23:49, Russ Cox <rsc@golang.org> wrote: >> obviously i can use your ...
13 years, 7 months ago (2011-04-19 06:37:07 UTC) #11
rsc
> i think there needs to be some way of doing both > > f(a, ...
13 years, 7 months ago (2011-04-19 16:11:02 UTC) #12
r
sounds good, although I'm less sure about making them ... functions. the chances of having ...
13 years, 7 months ago (2011-04-19 16:28:02 UTC) #13
rsc
On Tue, Apr 19, 2011 at 12:27, Rob 'Commander' Pike <r@golang.org> wrote: > sounds good, ...
13 years, 7 months ago (2011-04-20 10:17:57 UTC) #14
r
13 years, 7 months ago (2011-04-20 15:06:20 UTC) #15
ok
Sign in to reply to this message.

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b