Skip to content

Commit

Permalink
sync
Browse files Browse the repository at this point in the history
  • Loading branch information
ltzmaxwell committed Feb 21, 2025
2 parents 2915fb4 + e067304 commit d8cd6e6
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 34 deletions.
9 changes: 0 additions & 9 deletions gnovm/pkg/gnolang/ownership.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,6 @@ type Object interface {
SetIsNewEscaped(bool)
GetIsNewDeleted() bool
SetIsNewDeleted(bool)
GetIsTransient() bool

// Saves to realm along the way if owned, and also (dirty
// or new).
// ValueImage(rlm *Realm, owned bool) *ValueImage
}

var (
Expand Down Expand Up @@ -381,10 +376,6 @@ func (oi *ObjectInfo) SetIsNewDeleted(x bool) {
oi.isNewDeleted = x
}

func (oi *ObjectInfo) GetIsTransient() bool {
return false
}

// get first accessible object, maybe containing(parent) object, maybe itself.
func (tv *TypedValue) GetFirstObject(store Store) Object {
switch cv := tv.V.(type) {
Expand Down
75 changes: 50 additions & 25 deletions gnovm/pkg/gnolang/realm.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ a realm to keep it alive.
//----------------------------------------
// PkgID & Realm

// PkgID is an identifier for a package, stored using a fixed length in bytes.
// It is a [Hashlet] (sha256 hash, cut at 20 bytes) of the package path.
type PkgID struct {
Hashlet
}
Expand Down Expand Up @@ -81,6 +83,7 @@ var (
pkgIDFromPkgPathCache = make(map[string]*PkgID, 100)
)

// PkgIDFromPkgPath creates a new [PkgID] from the given package path.
func PkgIDFromPkgPath(path string) PkgID {
pkgIDFromPkgPathCacheMu.Lock()
defer pkgIDFromPkgPathCacheMu.Unlock()
Expand All @@ -95,39 +98,51 @@ func PkgIDFromPkgPath(path string) PkgID {
return *pkgID
}

// Returns the ObjectID of the PackageValue associated with path.
// ObjectIDFromPkgPath the [ObjectID] of the [PackageValue] associated with path.
func ObjectIDFromPkgPath(path string) ObjectID {
pkgID := PkgIDFromPkgPath(path)
return ObjectIDFromPkgID(pkgID)
}

// Returns the ObjectID of the PackageValue associated with pkgID.
// ObjectIDFromPkgID the [ObjectID] of the [PackageValue] associated with pkgID.
func ObjectIDFromPkgID(pkgID PkgID) ObjectID {
return ObjectID{
PkgID: pkgID,
NewTime: 1, // by realm logic.
}
}

// NOTE: A nil realm is special and has limited functionality; enough to
// support methods that don't require persistence. This is the default realm
// when a machine starts with a non-realm package.
// Realm is a data structure to keep track of modifications done to a realm
// package's state. A Realm state is composed of various objects attached to a
// realm. Any of the objects of the realm may be created, escaped or deleted
// during a transaction, these actions are recorded through [Realm.DidUpdate].
// When a realm boundary is exited, then [Realm.FinalizeRealmTransaction] is
// called, which updates the store with the up-to-date objects.
//
// An object is considered "escaped" when it has a RefCount > 1.
type Realm struct {
ID PkgID
// ID is a constant-sized hash for the realm's package path.
ID PkgID
// The realm package path.
Path string
// The "Time" of a realm; a variable increased for each new object, in order
// to assign it a unique [ObjectID].
Time uint64

newCreated []Object
newEscaped []Object
newDeleted []Object
// Temporary creates/escapes/deletes that happen in [DidUpdate].
newCreated []Object // may become created unless ancestor is deleted
newEscaped []Object // may become escaped unless new-real and refcount 0 or 1.
newDeleted []Object // may become deleted unless attached to new-real owner
// Updated objects are marked directly in updated, there is no newUpdated.
// During finalization, all ancestors of updated are finalized too.

created []Object // about to become real.
updated []Object // real objects that were modified.
deleted []Object // real objects that became deleted.
escaped []Object // real objects with refcount > 1.
}

// Creates a blank new realm with counter 0.
// NewRealm a blank new [Realm] with counter 0.
func NewRealm(path string) *Realm {
id := PkgIDFromPkgPath(path)
return &Realm{
Expand All @@ -150,6 +165,12 @@ func (rlm *Realm) String() string {
//----------------------------------------
// ownership hooks

// DidUpdate attaches co (Created Object) to po (Parent Object), substituting xo
// (deleted (X) Object).
//
// po will be marked as dirty. If co is not nil, its ref-count will be increased.
// If xo is not nil, its ref-count will be decreased, and if 0 it will be
// considered as deleted.
func (rlm *Realm) DidUpdate(store Store, po, xo, co Object) {
if debug {
debug.Printf(
Expand Down Expand Up @@ -177,9 +198,6 @@ func (rlm *Realm) DidUpdate(store Store, po, xo, co Object) {
if co != nil && co.GetIsDeleted() {
panic("cannot attach a deleted object")
}
if po != nil && po.GetIsTransient() {
panic("cannot attach to a transient object")
}
if po != nil && po.GetIsDeleted() {
panic("cannot attach to a deleted object")
}
Expand Down Expand Up @@ -209,9 +227,8 @@ func (rlm *Realm) DidUpdate(store Store, po, xo, co Object) {
if co.GetIsReal() {
rlm.MarkDirty(co)
}
if co.GetIsEscaped() {
// already escaped
} else {
// If it's not escaped, mark as newly escaped item.
if !co.GetIsEscaped() {
checkCrossRealm(rlm, store, co, nil)
rlm.MarkNewEscaped(co)
}
Expand Down Expand Up @@ -348,6 +365,9 @@ func checkCrossRealmChildren(rlm *Realm, store Store, oo Object, seenObjs []Obje
//----------------------------------------
// mark*

// MarkNewReal marks the given [Object] as a new real object; that is, that
// it should be considered a newly created object to save during realm
// finalization.
func (rlm *Realm) MarkNewReal(oo Object) {
if debug {
if pv, ok := oo.(*PackageValue); ok {
Expand Down Expand Up @@ -379,7 +399,8 @@ func (rlm *Realm) MarkNewReal(oo Object) {
rlm.newCreated = append(rlm.newCreated, oo)
}

// mark dirty == updated
// MarkDirty sets the given [Object] as "dirty" (updated) at the given rlm.Time,
// and marks it to be updated during the next realm finalization.
func (rlm *Realm) MarkDirty(oo Object) {
if debug {
if !oo.GetIsReal() && !oo.GetIsNewReal() {
Expand All @@ -400,6 +421,8 @@ func (rlm *Realm) MarkDirty(oo Object) {
rlm.updated = append(rlm.updated, oo)
}

// MarkNewEscaped marks the given [Object] as to be deleted during the next
// realm finalization.
func (rlm *Realm) MarkNewDeleted(oo Object) {
if debug {
if !oo.GetIsNewReal() && !oo.GetIsReal() {
Expand All @@ -420,6 +443,8 @@ func (rlm *Realm) MarkNewDeleted(oo Object) {
rlm.newDeleted = append(rlm.newDeleted, oo)
}

// MarkNewEscaped marks the given [Object] to be escaped during the next realm
// finalization.
func (rlm *Realm) MarkNewEscaped(oo Object) {
if debug {
if !oo.GetIsNewReal() && !oo.GetIsReal() {
Expand All @@ -446,10 +471,14 @@ func (rlm *Realm) MarkNewEscaped(oo Object) {
//----------------------------------------
// transactions

// TODO: check cross realm, that might be objects not attached
// to a realm gets attached here, which should panic.
// OpReturn calls this when exiting a realm transaction.
// FinalizeRealmTransaction moves the changes recorded in the given [Realm] and
// writes them into the underlying [Store]. OpReturn calls this when exiting a
// realm transaction; additionally, this is called by the machine itself in
// [Machine.RunMemPackage].
func (rlm *Realm) FinalizeRealmTransaction(readonly bool, store Store) {
// TODO: check cross realm, that might be objects not attached
// to a realm gets attached here, which should panic.

if bm.OpsEnabled {
bm.PauseOpCode()
defer bm.ResumeOpCode()
Expand All @@ -468,10 +497,6 @@ func (rlm *Realm) FinalizeRealmTransaction(readonly bool, store Store) {
return
}
if debug {
// * newCreated - may become created unless ancestor is deleted
// * newDeleted - may become deleted unless attached to new-real owner
// * newEscaped - may become escaped unless new-real and refcount 0 or 1.
// * updated - includes all real updated objects, and will be appended with ancestors
ensureUniq(rlm.newCreated)
ensureUniq(rlm.newEscaped)
ensureUniq(rlm.newDeleted)
Expand Down Expand Up @@ -727,7 +752,7 @@ func (rlm *Realm) processNewEscapedMarks(store Store) {
if po == nil {
// e.g. !eo.GetIsNewReal(),
// should have no parent.
//eo.SetOwner(nil)
// eo.SetOwner(nil)
continue
} else {
if po.GetRefCount() == 0 {
Expand Down

0 comments on commit d8cd6e6

Please sign in to comment.