Skip to content
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

fix: (gnovm) star expr assign for #1919 #2255

Merged
merged 39 commits into from
Jun 20, 2024
Merged

Conversation

jaekwon
Copy link
Contributor

@jaekwon jaekwon commented Jun 1, 2024

This is a complete solution, alternative to #1919, and (I think) closes #1326.
It creates a new container for "baseless" (floating) values constructed via new(xxx) or &struct{}, which currently do not have a base containing object for that value, and are currently represented as PointerValues with .Base set to nil.

The containing object is like a Block but minimal -- it only contains one Value, and has no Source or Parent. The modifications to realm.go allow for proper ref-counting so that even when there are multiple references to the baseless value, and even when the value is primitive, gc and ref-counting works (since the containing HeapItemValue is ref-counted). PointerValue.Base should now never be nil.

See also #1919 (comment) for why the previous solution doesn't work.

A better optimization than the one mentioned in the comment above, is to always store the HeapItemValue along with the Value, since the Value's refcount should always be 1. This is left for the future, after first checking that this invariant is true.

@jaekwon jaekwon requested review from moul, piux2, deelawn, zivkovicmilos and a team as code owners June 1, 2024 05:55
@github-actions github-actions bot added 📦 🤖 gnovm Issues or PRs gnovm related 📦 ⛰️ gno.land Issues or PRs gno.land package related labels Jun 1, 2024
@deelawn deelawn changed the title jae/fix/star expr assign for #1919 fix: (gnovm) star expr assign for #1919 Jun 3, 2024
@deelawn deelawn requested review from a team as code owners June 3, 2024 21:57
@github-actions github-actions bot added the 🧾 package/realm Tag used for new Realms or Packages. label Jun 3, 2024
@petar-dambovaliev petar-dambovaliev self-requested a review June 4, 2024 09:34
Copy link
Contributor

@petar-dambovaliev petar-dambovaliev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

// would be any faster. But this is something we could
// explore after launch.
hiv := &HeapItemValue{
ObjectInfo: cv.ObjectInfo.Copy(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, just because we copy the object info everywhere else in this function.

@@ -171,6 +173,9 @@ func (dbv DataByteValue) SetByte(b byte) {
// or binary operations. When a pointer is to be
// allocated, *Allocator.AllocatePointer() is called separately,
// as in OpRef.
//
// Since PointerValue is used internally for assignment etc,
// it MUST stay minimal for computational efficiency.
type PointerValue struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the original comment on this should be updated as well.
''...A pointer constructed via a &x{} composite lit expression or constructed via new() or make() are independent objects, and have nil Base...."

@jaekwon jaekwon merged commit eef0039 into master Jun 20, 2024
76 of 77 checks passed
@jaekwon jaekwon deleted the jae/fix/star-expr-assign branch June 20, 2024 00:39
deelawn added a commit that referenced this pull request Jul 2, 2024
Closes #2449.

I believe the bug was introduced by #2255. Previously, if the type of
`tv.V` in `GetFirstObject` was a `PointerValue`, it the `Base` would
have been nil in the scenario producing this bug. Now that `Base` can
never be nil for a `PointerValue`, the nil base check has been removed.
We do however need to account for a new scenario where the `Base` is a
`RefValue`, a type that does implement the `Object` interface. In the
case where the base is a `RefValue`, first resolve it by calling
`store.GetObject`.

<!-- please provide a detailed description of the changes made in this
pull request. -->

<details><summary>Contributors' checklist...</summary>

- [x] Added new tests, or not needed, or not feasible
- [x] Provided an example (e.g. screenshot) to aid review or the PR is
self-explanatory
- [x] Updated the official documentation or not needed
- [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message
was included in the description
- [x] Added references to related issues and PRs
- [x] Provided any useful hints for running manual tests
- [x] Added new benchmarks to [generated
graphs](https://gnoland.github.io/benchmarks), if any. More info
[here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
</details>
gfanton pushed a commit to gfanton/gno that referenced this pull request Jul 23, 2024
This is a complete solution, alternative to gnolang#1919, and (I think) closes
gnolang#1326.
It creates a new container for "baseless" (floating) values constructed
via `new(xxx)` or `&struct{}`, which currently do not have a base
containing object for that value, and are currently represented as
PointerValues with .Base set to nil.

The containing object is like a Block but minimal -- it only contains
one Value, and has no Source or Parent. The modifications to realm.go
allow for proper ref-counting so that even when there are multiple
references to the baseless value, and even when the value is primitive,
gc and ref-counting works (since the containing HeapItemValue is
ref-counted). PointerValue.Base should now never be nil.

See also
gnolang#1919 (comment) for why
the previous solution doesn't work.

A better optimization than the one mentioned in the comment above, is to
always store the HeapItemValue along with the Value, since the Value's
refcount should always be 1. This is left for the future, after first
checking that this invariant is true.

---------

Co-authored-by: deelawn <dboltz03@gmail.com>
gfanton pushed a commit to gfanton/gno that referenced this pull request Jul 23, 2024
Closes gnolang#2449.

I believe the bug was introduced by gnolang#2255. Previously, if the type of
`tv.V` in `GetFirstObject` was a `PointerValue`, it the `Base` would
have been nil in the scenario producing this bug. Now that `Base` can
never be nil for a `PointerValue`, the nil base check has been removed.
We do however need to account for a new scenario where the `Base` is a
`RefValue`, a type that does implement the `Object` interface. In the
case where the base is a `RefValue`, first resolve it by calling
`store.GetObject`.

<!-- please provide a detailed description of the changes made in this
pull request. -->

<details><summary>Contributors' checklist...</summary>

- [x] Added new tests, or not needed, or not feasible
- [x] Provided an example (e.g. screenshot) to aid review or the PR is
self-explanatory
- [x] Updated the official documentation or not needed
- [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message
was included in the description
- [x] Added references to related issues and PRs
- [x] Provided any useful hints for running manual tests
- [x] Added new benchmarks to [generated
graphs](https://gnoland.github.io/benchmarks), if any. More info
[here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
</details>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📦 ⛰️ gno.land Issues or PRs gno.land package related 📦 🤖 gnovm Issues or PRs gnovm related 🧾 package/realm Tag used for new Realms or Packages.
Projects
Status: Done
Status: Done
Development

Successfully merging this pull request may close these issues.

unexpected unreal object when assigning a local variable to a global variable (pointer)
6 participants