Commit f7b5a019 authored by Robert Hencke's avatar Robert Hencke Committed by Rob Pike

reflect: use visit structure for map key in DeepEqual

R=golang-dev, bradfitz, jonathan, r
CC=golang-dev
https://golang.org/cl/8730044
parent c6293d21
...@@ -9,18 +9,17 @@ package reflect ...@@ -9,18 +9,17 @@ package reflect
// During deepValueEqual, must keep track of checks that are // During deepValueEqual, must keep track of checks that are
// in progress. The comparison algorithm assumes that all // in progress. The comparison algorithm assumes that all
// checks in progress are true when it reencounters them. // checks in progress are true when it reencounters them.
// Visited are stored in a map indexed by 17 * a1 + a2; // Visited comparisons are stored in a map indexed by visit.
type visit struct { type visit struct {
a1 uintptr a1 uintptr
a2 uintptr a2 uintptr
typ Type typ Type
next *visit
} }
// Tests for deep equality using reflected types. The map argument tracks // Tests for deep equality using reflected types. The map argument tracks
// comparisons that have already been seen, which allows short circuiting on // comparisons that have already been seen, which allows short circuiting on
// recursive types. // recursive types.
func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool) { func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
if !v1.IsValid() || !v2.IsValid() { if !v1.IsValid() || !v2.IsValid() {
return v1.IsValid() == v2.IsValid() return v1.IsValid() == v2.IsValid()
} }
...@@ -44,17 +43,14 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool ...@@ -44,17 +43,14 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
} }
// ... or already seen // ... or already seen
h := 17*addr1 + addr2
seen := visited[h]
typ := v1.Type() typ := v1.Type()
for p := seen; p != nil; p = p.next { v := visit{addr1, addr2, typ}
if p.a1 == addr1 && p.a2 == addr2 && p.typ == typ { if visited[v] {
return true return true
} }
}
// Remember for later. // Remember for later.
visited[h] = &visit{addr1, addr2, typ, seen} visited[v] = true
} }
switch v1.Kind() { switch v1.Kind() {
...@@ -135,5 +131,5 @@ func DeepEqual(a1, a2 interface{}) bool { ...@@ -135,5 +131,5 @@ func DeepEqual(a1, a2 interface{}) bool {
if v1.Type() != v2.Type() { if v1.Type() != v2.Type() {
return false return false
} }
return deepValueEqual(v1, v2, make(map[uintptr]*visit), 0) return deepValueEqual(v1, v2, make(map[visit]bool), 0)
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment