mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: improve undo of poset
prove uses the poset datastructure in a DFS walk, and always undoes it back to its pristine status. Before this CL, poset's undo of a new node creation didn't fully deallocate the node, which means that at the end of prove there was still some allocated memory pending. This was not a problem until now because the posets used by prove were discarded after each function, but it would prevent recycling them between functions (as a followup CL does). Change-Id: I1c1c99c03fe19ad765395a43958cb256f686765a Reviewed-on: https://go-review.googlesource.com/112976 Run-TryBot: Giovanni Bajo <rasky@develer.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
7bac2a95f6
commit
67656ba71b
3 changed files with 20 additions and 10 deletions
|
|
@ -608,6 +608,8 @@ var knownFormats = map[string]string{
|
||||||
"[]byte %x": "",
|
"[]byte %x": "",
|
||||||
"[]cmd/compile/internal/ssa.Edge %v": "",
|
"[]cmd/compile/internal/ssa.Edge %v": "",
|
||||||
"[]cmd/compile/internal/ssa.ID %v": "",
|
"[]cmd/compile/internal/ssa.ID %v": "",
|
||||||
|
"[]cmd/compile/internal/ssa.posetNode %v": "",
|
||||||
|
"[]cmd/compile/internal/ssa.posetUndo %v": "",
|
||||||
"[]cmd/compile/internal/syntax.token %s": "",
|
"[]cmd/compile/internal/syntax.token %s": "",
|
||||||
"[]string %v": "",
|
"[]string %v": "",
|
||||||
"[]uint32 %v": "",
|
"[]uint32 %v": "",
|
||||||
|
|
@ -718,6 +720,7 @@ var knownFormats = map[string]string{
|
||||||
"uint16 %v": "",
|
"uint16 %v": "",
|
||||||
"uint16 %x": "",
|
"uint16 %x": "",
|
||||||
"uint32 %d": "",
|
"uint32 %d": "",
|
||||||
|
"uint32 %v": "",
|
||||||
"uint32 %x": "",
|
"uint32 %x": "",
|
||||||
"uint64 %08x": "",
|
"uint64 %08x": "",
|
||||||
"uint64 %d": "",
|
"uint64 %d": "",
|
||||||
|
|
|
||||||
|
|
@ -679,13 +679,24 @@ func (po *poset) CheckIntegrity() (err error) {
|
||||||
// It can be used for debugging purposes, as a poset is supposed to
|
// It can be used for debugging purposes, as a poset is supposed to
|
||||||
// be empty after it's fully rolled back through Undo.
|
// be empty after it's fully rolled back through Undo.
|
||||||
func (po *poset) CheckEmpty() error {
|
func (po *poset) CheckEmpty() error {
|
||||||
// Check that the poset is completely empty
|
if len(po.nodes) != 1 {
|
||||||
|
return fmt.Errorf("non-empty nodes list: %v", po.nodes)
|
||||||
|
}
|
||||||
if len(po.values) != 0 {
|
if len(po.values) != 0 {
|
||||||
return fmt.Errorf("non-empty value map: %v", po.values)
|
return fmt.Errorf("non-empty value map: %v", po.values)
|
||||||
}
|
}
|
||||||
if len(po.roots) != 0 {
|
if len(po.roots) != 0 {
|
||||||
return fmt.Errorf("non-empty root list: %v", po.roots)
|
return fmt.Errorf("non-empty root list: %v", po.roots)
|
||||||
}
|
}
|
||||||
|
if len(po.constants) != 0 {
|
||||||
|
return fmt.Errorf("non-empty constants: %v", po.constants)
|
||||||
|
}
|
||||||
|
if len(po.undo) != 0 {
|
||||||
|
return fmt.Errorf("non-empty undo list: %v", po.undo)
|
||||||
|
}
|
||||||
|
if po.lastidx != 0 {
|
||||||
|
return fmt.Errorf("lastidx index is not zero: %v", po.lastidx)
|
||||||
|
}
|
||||||
for _, bs := range po.noneq {
|
for _, bs := range po.noneq {
|
||||||
for _, x := range bs {
|
for _, x := range bs {
|
||||||
if x != 0 {
|
if x != 0 {
|
||||||
|
|
@ -693,14 +704,6 @@ func (po *poset) CheckEmpty() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for idx, n := range po.nodes {
|
|
||||||
if n.l|n.r != 0 {
|
|
||||||
return fmt.Errorf("non-empty node %v->[%d,%d]", idx, n.l.Target(), n.r.Target())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(po.constants) != 0 {
|
|
||||||
return fmt.Errorf("non-empty constant")
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1123,6 +1126,9 @@ func (po *poset) Undo() {
|
||||||
po.noneq[pass.ID].Clear(pass.idx)
|
po.noneq[pass.ID].Clear(pass.idx)
|
||||||
|
|
||||||
case undoNewNode:
|
case undoNewNode:
|
||||||
|
if pass.idx != po.lastidx {
|
||||||
|
panic("invalid newnode index")
|
||||||
|
}
|
||||||
if pass.ID != 0 {
|
if pass.ID != 0 {
|
||||||
if po.values[pass.ID] != pass.idx {
|
if po.values[pass.ID] != pass.idx {
|
||||||
panic("invalid newnode undo pass")
|
panic("invalid newnode undo pass")
|
||||||
|
|
@ -1131,6 +1137,8 @@ func (po *poset) Undo() {
|
||||||
}
|
}
|
||||||
po.setchl(pass.idx, 0)
|
po.setchl(pass.idx, 0)
|
||||||
po.setchr(pass.idx, 0)
|
po.setchr(pass.idx, 0)
|
||||||
|
po.nodes = po.nodes[:pass.idx]
|
||||||
|
po.lastidx--
|
||||||
|
|
||||||
// If it was the last inserted constant, remove it
|
// If it was the last inserted constant, remove it
|
||||||
nc := len(po.constants)
|
nc := len(po.constants)
|
||||||
|
|
|
||||||
|
|
@ -626,7 +626,6 @@ func TestPosetConst(t *testing.T) {
|
||||||
|
|
||||||
func TestPosetNonEqual(t *testing.T) {
|
func TestPosetNonEqual(t *testing.T) {
|
||||||
testPosetOps(t, false, []posetTestOp{
|
testPosetOps(t, false, []posetTestOp{
|
||||||
{Checkpoint, 0, 0},
|
|
||||||
{Equal_Fail, 10, 20},
|
{Equal_Fail, 10, 20},
|
||||||
{NonEqual_Fail, 10, 20},
|
{NonEqual_Fail, 10, 20},
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue