diff --git a/examples/gno.land/r/demo/bugs/slice_pop_push/slice_pop_push.gno b/examples/gno.land/r/demo/bugs/slice_pop_push/slice_pop_push.gno index 849748b6424..38bbad987b3 100644 --- a/examples/gno.land/r/demo/bugs/slice_pop_push/slice_pop_push.gno +++ b/examples/gno.land/r/demo/bugs/slice_pop_push/slice_pop_push.gno @@ -1,19 +1,21 @@ package slice_pop_push +import ( + "strings" +) + var slice = []string{"undead-element"} -func Pop() { +func Pop() []string { slice = slice[:len(slice)-1] + return slice } -func Push() { +func Push() []string { slice = append(slice, "new-element") + return slice } func Render(path string) string { - os := []string{"undead-element-2"} - os = os[:len(os)-1] - os = append(os, "new-element-2") - - return os[0] + slice[0] + return strings.Join(slice, ",") } diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 40f770c7720..70e67cb9ec9 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -130,6 +130,15 @@ func (rlm *Realm) DidUpdate(po, xo, co Object) { if rlm == nil { return } + + shouldDebug := false + if (po != nil && strings.Contains(po.String(), "-element")) || + (xo != nil && strings.Contains(xo.String(), "-element")) || + (co != nil && strings.Contains(co.String(), "-element")) { + fmt.Println("intersting DidUpdate", xo, co) + shouldDebug = true + } + if debug { if co != nil && co.GetIsDeleted() { panic("cannot attach a deleted object") @@ -142,6 +151,9 @@ func (rlm *Realm) DidUpdate(po, xo, co Object) { } } if po == nil || !po.GetIsReal() { + if shouldDebug { + fmt.Println("DidUpdate - Do nothing 1") + } return // do nothing. } if po.GetObjectID().PkgID != rlm.ID { @@ -151,17 +163,32 @@ func (rlm *Realm) DidUpdate(po, xo, co Object) { // Updates to .newCreated/.newEscaped /.newDeleted made here. (first gen) // More appends happen during FinalizeRealmTransactions(). (second+ gen) rlm.MarkDirty(po) + if shouldDebug { + fmt.Println("MarkDirty po", po) + } if co != nil { co.IncRefCount() if co.GetRefCount() > 1 { + if shouldDebug { + fmt.Println("DidUpdate - ref count case") + } if co.GetIsEscaped() { + fmt.Println("DidUpdate - already escaped") // already escaped } else { + fmt.Println("DidUpdate - mark escaped") rlm.MarkNewEscaped(co) } - } else if co.GetIsReal() { + } + if co.GetIsReal() { + if shouldDebug { + fmt.Println("MarkDirty co", co) + } rlm.MarkDirty(co) } else { + if shouldDebug { + fmt.Println("DidUpdate - else case") + } co.SetOwner(po) rlm.MarkNewReal(co) } @@ -211,6 +238,9 @@ func (rlm *Realm) MarkNewReal(oo Object) { } func (rlm *Realm) MarkDirty(oo Object) { + if strings.Contains(oo.(Value).String(), "-element") { + fmt.Println("MarkDirty implem", oo) + } if debug { if !oo.GetIsReal() && !oo.GetIsNewReal() { panic("should not happen") @@ -638,6 +668,9 @@ func (rlm *Realm) markDirtyAncestors(store Store) { // Saves .created and .updated objects. func (rlm *Realm) saveUnsavedObjects(store Store) { for _, co := range rlm.created { + if strings.Contains(co.String(), "-element") { + fmt.Println("saveUnsavedObjects: created:", co.String()) + } // for i := len(rlm.created) - 1; i >= 0; i-- { // co := rlm.created[i] if !co.GetIsNewReal() { @@ -649,6 +682,9 @@ func (rlm *Realm) saveUnsavedObjects(store Store) { } } for _, uo := range rlm.updated { + if strings.Contains(uo.String(), "-element") { + fmt.Println("saveUnsavedObjects: updated:", uo.String()) + } // for i := len(rlm.updated) - 1; i >= 0; i-- { // uo := rlm.updated[i] if !uo.GetIsDirty() { @@ -1057,6 +1093,9 @@ func copyValueWithRefs(parent Object, val Value) Value { case nil: return nil case StringValue: + if cv == "undead-element" || cv == "new-element" { + fmt.Println("copyValueWithRefs", cv) + } return cv case BigintValue: return cv @@ -1088,6 +1127,9 @@ func copyValueWithRefs(parent Object, val Value) Value { } } case *ArrayValue: + if strings.Contains(cv.String(), "-element") { + fmt.Println("copyValueWithRefs slice", cv) + } if cv.Data == nil { list := make([]TypedValue, len(cv.List)) for i, etv := range cv.List { @@ -1104,6 +1146,11 @@ func copyValueWithRefs(parent Object, val Value) Value { } } case *SliceValue: + if strings.Contains(cv.String(), "-element") { + fmt.Println("copyValueWithRefs slice", cv) + fmt.Println("copyValue base", cv.Base.(*ArrayValue)) + + } return &SliceValue{ Base: toRefValue(parent, cv.Base), Offset: cv.Offset, diff --git a/gnovm/pkg/gnolang/store.go b/gnovm/pkg/gnolang/store.go index d3628edf216..3e0d3433c81 100644 --- a/gnovm/pkg/gnolang/store.go +++ b/gnovm/pkg/gnolang/store.go @@ -296,6 +296,9 @@ func (ds *defaultStore) loadObjectSafe(oid ObjectID) Object { // package values. func (ds *defaultStore) SetObject(oo Object) { oid := oo.GetObjectID() + if array, ok := oo.(Value).(*ArrayValue); ok && strings.Contains(array.String(), "-element") { + fmt.Println("SetObject intersting array", array) + } // replace children/fields with Ref. o2 := copyValueWithRefs(nil, oo) // marshal to binary. diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 3de74ac0130..a12937b92d8 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -204,6 +204,12 @@ func (pv *PointerValue) GetBase(store Store) Object { // TODO: document as something that enables into-native assignment. // TODO: maybe consider this as entrypoint for DataByteValue too? func (pv PointerValue) Assign2(alloc *Allocator, store Store, rlm *Realm, tv2 TypedValue, cu bool) { + shouldDebug := false + if strings.Contains(tv2.String(), "-element") { + fmt.Println("Assign2", tv2) + // rlm.MarkDirty(tv2.V.(*SliceValue).GetBase(store)) + shouldDebug = true + } // Special cases. if pv.Index == PointerIndexNative { // Special case if extended object && native. @@ -276,10 +282,44 @@ func (pv PointerValue) Assign2(alloc *Allocator, store Store, rlm *Realm, tv2 Ty } // General case if rlm != nil && pv.Base != nil { + if shouldDebug { + fmt.Println("Assign2 - DidUpdate", pv.TV, tv2) + } + oo1 := pv.TV.GetFirstObject(store) + + markDirty := false + if pv.TV != nil && pv.TV.T != nil && pv.TV.V != nil && pv.TV.T.Kind() == SliceKind && tv2.T != nil && tv2.V != nil && tv2.T.Kind() == SliceKind && pv.TV.V.(*SliceValue).Length != tv2.V.(*SliceValue).Length { + //fmt.Println("MarkDirty weird", pv.TV, tv2) + markDirty = true + } + pv.TV.Assign(alloc, tv2, cu) - oo2 := pv.TV.GetFirstObject(store) + oo2 := tv2.GetFirstObject(store) + if shouldDebug { + fmt.Printf("Assign2 - DidUpdate after %p %p\n", oo1, oo2) + } rlm.DidUpdate(pv.Base.(Object), oo1, oo2) + if markDirty { + //rlm.MarkDirty(oo1) + } + + /* + if shouldDebug { + if pv.TV != nil && tv2.V != nil && oo1 != nil && oo2 != nil { + switch pv.TV.V.(type) { + case *SliceValue: + switch tv2.V.(type) { + case *SliceValue: + base := pv.TV.V.(*SliceValue).GetBase(store) + if base == tv2.V.(*SliceValue).GetBase(store) && base != nil { + rlm.MarkDirty(base) + } + } + } + } + } + */ } else { pv.TV.Assign(alloc, tv2, cu) } diff --git a/go.mod b/go.mod index e61748552f0..1e09637a395 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 github.com/golang/protobuf v1.5.3 github.com/google/gofuzz v1.2.0 + github.com/gookit/goutil v0.6.10 github.com/gorilla/mux v1.8.0 github.com/gorilla/websocket v1.5.0 github.com/gotuna/gotuna v0.6.0 @@ -34,7 +35,7 @@ require ( golang.org/x/crypto v0.9.0 golang.org/x/mod v0.9.0 golang.org/x/net v0.10.0 - golang.org/x/term v0.8.0 + golang.org/x/term v0.9.0 golang.org/x/tools v0.6.0 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v3 v3.0.1 @@ -54,6 +55,7 @@ require ( github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect github.com/golang/snappy v0.0.3 // indirect github.com/google/flatbuffers v1.12.1 // indirect + github.com/gookit/color v1.5.3 // indirect github.com/gorilla/securecookie v1.1.1 // indirect github.com/gorilla/sessions v1.2.1 // indirect github.com/klauspost/compress v1.12.3 // indirect @@ -62,9 +64,10 @@ require ( github.com/lucasb-eyer/go-colorful v1.0.3 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.opencensus.io v0.22.5 // indirect go.uber.org/atomic v1.7.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/sys v0.9.0 // indirect + golang.org/x/text v0.10.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) diff --git a/go.sum b/go.sum index 750461de671..f10728e6130 100644 --- a/go.sum +++ b/go.sum @@ -100,6 +100,10 @@ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gookit/color v1.5.3 h1:twfIhZs4QLCtimkP7MOxlF3A0U/5cDPseRT9M/+2SCE= +github.com/gookit/color v1.5.3/go.mod h1:NUzwzeehUfl7GIb36pqId+UGmRfQcU/WiiyTTeNjHtE= +github.com/gookit/goutil v0.6.10 h1:iq7CXOf+fYLvrVAh3+ZoLgufGfK65TwbzE8NpnPGtyk= +github.com/gookit/goutil v0.6.10/go.mod h1:qqrPoX+Pm6YmxqqccgkNLPirTFX7UYMES1SK+fokqQU= github.com/gorilla/csrf v1.7.0/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= @@ -196,6 +200,8 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -216,6 +222,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -259,15 +266,15 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=