From 0b2c67ed3883bd04d0a03eb8c85ce218616099c2 Mon Sep 17 00:00:00 2001 From: Morgan Date: Fri, 25 Oct 2024 13:26:12 -0500 Subject: [PATCH] fix(gnolang): ensure complete Uverse initialization (#2997) Fixes #2067. UverseNode now distinguishes when it's uninitialized, initializing and initialized. In combination with calling Uverse() at init, we make sure that after package initialization we always have the same result from Uverse() and UverseNode() and we don't have issues like those pointed out in #2067. --- gnovm/pkg/gnolang/gno_test.go | 12 --------- gnovm/pkg/gnolang/preprocess.go | 6 +---- gnovm/pkg/gnolang/uverse.go | 47 ++++++++++++++++++++++++++------- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/gnovm/pkg/gnolang/gno_test.go b/gnovm/pkg/gnolang/gno_test.go index 1f83303023c..3b15c018505 100644 --- a/gnovm/pkg/gnolang/gno_test.go +++ b/gnovm/pkg/gnolang/gno_test.go @@ -404,18 +404,6 @@ func BenchmarkBenchdata(b *testing.B) { name += "_param:" + param } b.Run(name, func(b *testing.B) { - if strings.HasPrefix(name, "matrix.gno_param") { - // CGO_ENABLED=0 go test -bench . -benchmem ./... -short -run=^$ -cpu 1,2 -count=1 ./... - // That is not just exposing test and benchmark traces as output, but these benchmarks are failing - // making the output unparseable: - /* - BenchmarkBenchdata/matrix.gno_param:3 panic: runtime error: index out of range [31] with length 25 [recovered] - panic: runtime error: index out of range [31] with length 25: - ... - */ - b.Skip("it panics causing an error when parsing benchmark results") - } - // Gen template with N and param. var buf bytes.Buffer require.NoError(b, tpl.Execute(&buf, bdataParams{ diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 04cc83b54f0..2d65dfa5cb1 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -734,12 +734,8 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { // TRANS_BLOCK ----------------------- case *FuncDecl: // retrieve cached function type. + // the type and receiver are already set in predefineNow. ft := getType(&n.Type).(*FuncType) - if n.IsMethod { - // recv/type set @ predefineNow(). - } else { - // type set @ predefineNow(). - } // push func body block. pushInitBlock(n, &last, &stack) diff --git a/gnovm/pkg/gnolang/uverse.go b/gnovm/pkg/gnolang/uverse.go index d62d4228d68..ba66b27499f 100644 --- a/gnovm/pkg/gnolang/uverse.go +++ b/gnovm/pkg/gnolang/uverse.go @@ -61,26 +61,55 @@ var gStringerType = &DeclaredType{ var ( uverseNode *PackageNode uverseValue *PackageValue + uverseInit = uverseUninitialized ) +const ( + uverseUninitialized = iota + uverseInitializing + uverseInitialized +) + +func init() { + // Call Uverse() so we initialize the Uverse node ahead of any calls to the package. + Uverse() +} + const uversePkgPath = ".uverse" -// Always returns a new copy from the latest state of source. +// UverseNode returns the uverse PackageValue. +// If called while initializing the UverseNode itself, it will return an empty +// PackageValue. func Uverse() *PackageValue { - if uverseValue == nil { - pn := UverseNode() - uverseValue = pn.NewPackage() + switch uverseInit { + case uverseUninitialized: + uverseInit = uverseInitializing + makeUverseNode() + uverseInit = uverseInitialized + case uverseInitializing: + return &PackageValue{} } + return uverseValue } -// Always returns the same instance with possibly differing completeness. +// UverseNode returns the uverse PackageNode. +// If called while initializing the UverseNode itself, it will return an empty +// PackageNode. func UverseNode() *PackageNode { - // Global is singleton. - if uverseNode != nil { - return uverseNode + switch uverseInit { + case uverseUninitialized: + uverseInit = uverseInitializing + makeUverseNode() + uverseInit = uverseInitialized + case uverseInitializing: + return &PackageNode{} } + return uverseNode +} + +func makeUverseNode() { // NOTE: uverse node is hidden, thus the leading dot in pkgPath=".uverse". uverseNode = NewPackageNode("uverse", uversePkgPath, nil) @@ -1017,7 +1046,7 @@ func UverseNode() *PackageNode { m.Exceptions = nil }, ) - return uverseNode + uverseValue = uverseNode.NewPackage() } func copyDataToList(dst []TypedValue, data []byte, et Type) {