-
Notifications
You must be signed in to change notification settings - Fork 405
feat(gnovm): interrealm spec; cross/crossing; readonly; defer/recover/panic fixes; blank identifier fixes.... #4060
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🛠 PR Checks Summary🔴 Changes to 'docs' folder must be reviewed/authored by at least one devrel and one tech-staff Manual Checks (for Reviewers):
Read More🤖 This bot helps streamline PR reviews by verifying automated checks and providing guidance for contributors and reviewers. ✅ Automated Checks (for Contributors):🔴 Changes to 'docs' folder must be reviewed/authored by at least one devrel and one tech-staff ☑️ Contributor Actions:
☑️ Reviewer Actions:
📚 Resources:Debug
|
gnovm/pkg/gnolang/machine.go
Outdated
updates := m.runFileDecls(IsStdlib(pv.PkgPath), fns...) | ||
if rlm != nil { | ||
pb := pv.GetBlock(m.Store) | ||
for _, update := range updates { | ||
rlm.DidUpdate(pb, nil, update.GetFirstObject(m.Store)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update
can be a heap item, since all global variables are stored as heap item values. Therefore, a check is needed to determine whether update
is a heap item. If it is, do not call GetFirstObject, as this would trigger a panic. thanks @leohhhn for discovering the initial bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, maybe it should just work for heap items too now.
Is there a bug report or way to reproduce, or associated test that fails?
7777.
I just merged the master branch into this PR. I'm 90% confident that I resolved the conflicts correctly. |
Codecov ReportAttention: Patch coverage is 📢 Thoughts on this report? Let us know! |
btw, please check this commit: |
@@ -74,7 +74,7 @@ func (grc *token) SafeTransferFrom(from, to std.Address, tid grc721.TokenID) { | |||
} | |||
|
|||
func (grc *token) TransferFrom(from, to std.Address, tid grc721.TokenID) { | |||
caller := std.CallerAt(2) | |||
caller := std.CallerAt(2) // XXX use CurrentRealm or PreviousRealm(). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this needs change.
``` | ||
|
||
#### 2. EOA calling a sequence of realms | ||
|
||
Assuming that you use interrealm switching, when an EOA calls a sequence of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interrealm cross & crossing
} | ||
|
||
func Exec(fn func()) { | ||
// no realm switching. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no realm crossing
seems like it needs fixing, I'll take a look. The // 2 1 --> // 1 2 seems correct but the // undefined isn't consistent with go... |
} | ||
|
||
// Output: | ||
// (struct{(11 int),(&(struct{(22 int),(&(ref@0 main.A) *main.A)} main.B) *main.B)} main.A) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was incorrect.
Defers re-use the same frame but this causes all kinds of issues w/ panic scoping, return statements, and even frame stack inspection e.g. with `defer panic(...)`. This PR will: * make PanicStmt just a regular panic uverse call. * revert Frames to non-pointers. * make defer calls push a new call frame. * fix all known defer/panic/recover issues.
This uses heapitemvalues more such that a closure or pointer doesn't need to refer to a block.
It resolves #3693.
Excerpt from the new document 'Gno Memory Model' in this PR:
The above code when executed will first produce the following block:
In the above example the third slot for
x
is not initialized to the zerovalue of a typed value slot, but rather it is prefilled with a heap item.
Variables declared in a closure or passed by reference are first discovered and
marked as such from the preprocessor, and NewBlock() will prepopulate these
slots with
*HeapItemValues
. When a*HeapItemValue
is present in a blockslot it is not written over but instead the value is written into the heap
item's slot.
When the example code executes
return &x
instead of returning aPointerValue
with.Base
set to theBlockValue
and.Index
of 2, it sets.Base
to the*HeapItemValue
with.Index
of 0 since a heap item onlycontains one slot. The pointer's
.TV
is set to the single slot of of the heapitem. This way the when the pointer is used later in another transaction there
is no need to load the whole original block value, but rather a single heap
item object. If
Example()
returned onlyx
rather than a pointer&x
itwould not be initialized with a heap item for the slot.
The above example illustrates another use for heap items. Here we don't
reference
x
, but it is captured by the anonymous function literal (closure).At runtime the closure
*FuncValue
captures the heap item object such that theclosure does not depend on the block at all.
Variables declared at the package (global) level may also be referred to by
pointer in anonymous functions. In the future we will allow limited upgrading
features for mutable realm packages (e.g. the ability to add new functions or
replace or "swizzle" existing ones), so all package level declared variables
are wrapped in heap item objects.
Since all global package values referenced closures can be captured as heap
objects, the execution and persistence of a closure function value does not
depend on any parent blocks. (Omitted here is how references to package
level declared functions and methods are replaced by a selector expression
on the package itself; otherwise closures would still in general depend
on their parent blocks).
Loopvars
Go1.22 introduced loopvars to reduce programmer errors. Gno uses
heap items to implement loopvars.
The Gno VM does something special for loopvars. Instead of assigning the new
value
v
to the same slot, or even the same heap item object's slot, itreplaces the existing heap item object with a new one. This allows the closure
to capture a new heap item object with every iteration. This is called
a heap definition.
The behavior is applied for implicit loops with
goto
statements. Thepreprocessor first identifies all such variable definitions whether explicit in
range statements or implicit via
goto
statements that are captured byclosures or passed by pointer reference, and directs the VM to execute the
define statement by replacing the existing heap item object with a new one.