diff --git a/runtime/interpreter/interpreter.go b/runtime/interpreter/interpreter.go index 614d91f35f..d9579211e4 100644 --- a/runtime/interpreter/interpreter.go +++ b/runtime/interpreter/interpreter.go @@ -239,7 +239,7 @@ type Storage interface { CheckHealth() error } -type ReferencedResourceKindedValues map[atree.SlabID]map[ReferenceTrackedResourceKindedValue]struct{} +type ReferencedResourceKindedValues map[atree.ValueID]map[ReferenceTrackedResourceKindedValue]struct{} type Interpreter struct { Location common.Location @@ -5100,12 +5100,12 @@ func (interpreter *Interpreter) ValidateAtreeValue(value atree.Value) { func (interpreter *Interpreter) maybeTrackReferencedResourceKindedValue(value Value) { if value, ok := value.(ReferenceTrackedResourceKindedValue); ok { - interpreter.trackReferencedResourceKindedValue(value.SlabID(), value) + interpreter.trackReferencedResourceKindedValue(value.ValueID(), value) } } func (interpreter *Interpreter) trackReferencedResourceKindedValue( - id atree.SlabID, + id atree.ValueID, value ReferenceTrackedResourceKindedValue, ) { values := interpreter.SharedState.referencedResourceKindedValues[id] @@ -5117,8 +5117,8 @@ func (interpreter *Interpreter) trackReferencedResourceKindedValue( } func (interpreter *Interpreter) updateReferencedResource( - currentID atree.SlabID, - newID atree.SlabID, + currentID atree.ValueID, + newID atree.ValueID, updateFunc func(value ReferenceTrackedResourceKindedValue), ) { values := interpreter.SharedState.referencedResourceKindedValues[currentID] @@ -5377,8 +5377,8 @@ func (interpreter *Interpreter) idCapabilityCheckFunction( ) } -func (interpreter *Interpreter) validateMutation(slabID atree.SlabID, locationRange LocationRange) { - _, present := interpreter.SharedState.containerValueIteration[slabID] +func (interpreter *Interpreter) validateMutation(valueID atree.ValueID, locationRange LocationRange) { + _, present := interpreter.SharedState.containerValueIteration[valueID] if !present { return } @@ -5387,32 +5387,32 @@ func (interpreter *Interpreter) validateMutation(slabID atree.SlabID, locationRa }) } -func (interpreter *Interpreter) withMutationPrevention(slabID atree.SlabID, f func()) { - oldIteration, present := interpreter.SharedState.containerValueIteration[slabID] - interpreter.SharedState.containerValueIteration[slabID] = struct{}{} +func (interpreter *Interpreter) withMutationPrevention(valueID atree.ValueID, f func()) { + oldIteration, present := interpreter.SharedState.containerValueIteration[valueID] + interpreter.SharedState.containerValueIteration[valueID] = struct{}{} f() if !present { - delete(interpreter.SharedState.containerValueIteration, slabID) + delete(interpreter.SharedState.containerValueIteration, valueID) } else { - interpreter.SharedState.containerValueIteration[slabID] = oldIteration + interpreter.SharedState.containerValueIteration[valueID] = oldIteration } } func (interpreter *Interpreter) withResourceDestruction( - slabID atree.SlabID, + valueID atree.ValueID, locationRange LocationRange, f func(), ) { - _, exists := interpreter.SharedState.destroyedResources[slabID] + _, exists := interpreter.SharedState.destroyedResources[valueID] if exists { panic(DestroyedResourceError{ LocationRange: locationRange, }) } - interpreter.SharedState.destroyedResources[slabID] = struct{}{} + interpreter.SharedState.destroyedResources[valueID] = struct{}{} f() } diff --git a/runtime/interpreter/interpreter_expression.go b/runtime/interpreter/interpreter_expression.go index 27f48e4e09..371c4c3943 100644 --- a/runtime/interpreter/interpreter_expression.go +++ b/runtime/interpreter/interpreter_expression.go @@ -937,8 +937,8 @@ func (interpreter *Interpreter) visitInvocationExpressionWithImplicitArgument(in if boundFunction, ok := function.(BoundFunctionValue); ok && boundFunction.Self != nil { self := *boundFunction.Self if resource, ok := self.(ReferenceTrackedResourceKindedValue); ok { - slabID := resource.SlabID() - interpreter.trackReferencedResourceKindedValue(slabID, resource) + valueID := resource.ValueID() + interpreter.trackReferencedResourceKindedValue(valueID, resource) } } @@ -1290,7 +1290,7 @@ func (interpreter *Interpreter) VisitAttachExpression(attachExpression *ast.Atta base, interpreter.MustSemaTypeOfValue(base).(*sema.CompositeType), ) - interpreter.trackReferencedResourceKindedValue(base.SlabID(), base) + interpreter.trackReferencedResourceKindedValue(base.ValueID(), base) attachment, ok := interpreter.visitInvocationExpressionWithImplicitArgument( attachExpression.Attachment, @@ -1302,7 +1302,7 @@ func (interpreter *Interpreter) VisitAttachExpression(attachExpression *ast.Atta } // Because `self` in attachments is a reference, we need to track the attachment if it's a resource - interpreter.trackReferencedResourceKindedValue(attachment.SlabID(), attachment) + interpreter.trackReferencedResourceKindedValue(attachment.ValueID(), attachment) base = base.Transfer( interpreter, diff --git a/runtime/interpreter/sharedstate.go b/runtime/interpreter/sharedstate.go index 682bd68bf2..6824d9ac6f 100644 --- a/runtime/interpreter/sharedstate.go +++ b/runtime/interpreter/sharedstate.go @@ -43,8 +43,8 @@ type SharedState struct { storageMutatedDuringIteration bool CapabilityControllerIterations map[AddressPath]int MutationDuringCapabilityControllerIteration bool - containerValueIteration map[atree.SlabID]struct{} - destroyedResources map[atree.SlabID]struct{} + containerValueIteration map[atree.ValueID]struct{} + destroyedResources map[atree.ValueID]struct{} } func NewSharedState(config *Config) *SharedState { @@ -59,11 +59,11 @@ func NewSharedState(config *Config) *SharedState { }, inStorageIteration: false, storageMutatedDuringIteration: false, - referencedResourceKindedValues: map[atree.SlabID]map[ReferenceTrackedResourceKindedValue]struct{}{}, + referencedResourceKindedValues: map[atree.ValueID]map[ReferenceTrackedResourceKindedValue]struct{}{}, resourceVariables: map[ResourceKindedValue]*Variable{}, CapabilityControllerIterations: map[AddressPath]int{}, - containerValueIteration: map[atree.SlabID]struct{}{}, - destroyedResources: map[atree.SlabID]struct{}{}, + containerValueIteration: map[atree.ValueID]struct{}{}, + destroyedResources: map[atree.ValueID]struct{}{}, } } diff --git a/runtime/interpreter/value.go b/runtime/interpreter/value.go index 984b6d9e58..7920e69181 100644 --- a/runtime/interpreter/value.go +++ b/runtime/interpreter/value.go @@ -217,7 +217,7 @@ func maybeDestroy(interpreter *Interpreter, locationRange LocationRange, value V type ReferenceTrackedResourceKindedValue interface { ResourceKindedValue IsReferenceTrackedResourceKindedValue() - SlabID() atree.SlabID + ValueID() atree.ValueID } // ContractValue is the value of a contract. @@ -1717,7 +1717,7 @@ func (v *ArrayValue) Iterate(interpreter *Interpreter, f func(element Value) (re } if v.IsResourceKinded(interpreter) { - interpreter.withMutationPrevention(v.SlabID(), iterate) + interpreter.withMutationPrevention(v.ValueID(), iterate) } else { iterate() } @@ -1784,10 +1784,10 @@ func (v *ArrayValue) Destroy(interpreter *Interpreter, locationRange LocationRan }() } - slabID := v.SlabID() + valueID := v.ValueID() interpreter.withResourceDestruction( - slabID, + valueID, locationRange, func() { v.Walk(interpreter, func(element Value) { @@ -1803,8 +1803,8 @@ func (v *ArrayValue) Destroy(interpreter *Interpreter, locationRange LocationRan } interpreter.updateReferencedResource( - slabID, - slabID, + valueID, + valueID, func(value ReferenceTrackedResourceKindedValue) { arrayValue, ok := value.(*ArrayValue) if !ok { @@ -1948,7 +1948,7 @@ func (v *ArrayValue) SetKey(interpreter *Interpreter, locationRange LocationRang func (v *ArrayValue) Set(interpreter *Interpreter, locationRange LocationRange, index int, element Value) { - interpreter.validateMutation(v.SlabID(), locationRange) + interpreter.validateMutation(v.ValueID(), locationRange) // We only need to check the lower bound before converting from `int` (signed) to `uint64` (unsigned). // atree's Array.Set function will check the upper bound and report an atree.IndexOutOfBoundsError @@ -2022,7 +2022,7 @@ func (v *ArrayValue) MeteredString(memoryGauge common.MemoryGauge, seenReference func (v *ArrayValue) Append(interpreter *Interpreter, locationRange LocationRange, element Value) { - interpreter.validateMutation(v.SlabID(), locationRange) + interpreter.validateMutation(v.ValueID(), locationRange) // length increases by 1 dataSlabs, metaDataSlabs := common.AdditionalAtreeMemoryUsage( @@ -2070,7 +2070,7 @@ func (v *ArrayValue) InsertKey(interpreter *Interpreter, locationRange LocationR func (v *ArrayValue) Insert(interpreter *Interpreter, locationRange LocationRange, index int, element Value) { - interpreter.validateMutation(v.SlabID(), locationRange) + interpreter.validateMutation(v.ValueID(), locationRange) // We only need to check the lower bound before converting from `int` (signed) to `uint64` (unsigned). // atree's Array.Insert function will check the upper bound and report an atree.IndexOutOfBoundsError @@ -2125,7 +2125,7 @@ func (v *ArrayValue) RemoveKey(interpreter *Interpreter, locationRange LocationR func (v *ArrayValue) Remove(interpreter *Interpreter, locationRange LocationRange, index int) Value { - interpreter.validateMutation(v.SlabID(), locationRange) + interpreter.validateMutation(v.ValueID(), locationRange) // We only need to check the lower bound before converting from `int` (signed) to `uint64` (unsigned). // atree's Array.Remove function will check the upper bound and report an atree.IndexOutOfBoundsError @@ -2586,7 +2586,7 @@ func (v *ArrayValue) Transfer( }() } - currentSlabID := v.SlabID() + currentValueID := v.ValueID() array := v.array @@ -2655,11 +2655,11 @@ func (v *ArrayValue) Transfer( res = v } - newSlabID := array.SlabID() + newValueID := array.ValueID() interpreter.updateReferencedResource( - currentSlabID, - newSlabID, + currentValueID, + newValueID, func(value ReferenceTrackedResourceKindedValue) { arrayValue, ok := value.(*ArrayValue) if !ok { @@ -2767,6 +2767,10 @@ func (v *ArrayValue) StorageAddress() atree.Address { return v.array.Address() } +func (v *ArrayValue) ValueID() atree.ValueID { + return v.array.ValueID() +} + func (v *ArrayValue) GetOwner() common.Address { return common.Address(v.StorageAddress()) } @@ -15364,10 +15368,10 @@ func (v *CompositeValue) Destroy(interpreter *Interpreter, locationRange Locatio }() } - slabID := v.SlabID() + valueID := v.ValueID() interpreter.withResourceDestruction( - slabID, + valueID, locationRange, func() { // if this type has attachments, destroy all of them before invoking the destructor @@ -15419,8 +15423,8 @@ func (v *CompositeValue) Destroy(interpreter *Interpreter, locationRange Locatio } interpreter.updateReferencedResource( - slabID, - slabID, + valueID, + valueID, func(value ReferenceTrackedResourceKindedValue) { compositeValue, ok := value.(*CompositeValue) if !ok { @@ -16077,7 +16081,7 @@ func (v *CompositeValue) Transfer( }() } - currentSlabID := v.SlabID() + currentValueID := v.ValueID() currentAddress := v.StorageAddress() dictionary := v.dictionary @@ -16170,11 +16174,11 @@ func (v *CompositeValue) Transfer( res = v } - newSlabID := dictionary.SlabID() + newValueID := dictionary.ValueID() interpreter.updateReferencedResource( - currentSlabID, - newSlabID, + currentValueID, + newValueID, func(value ReferenceTrackedResourceKindedValue) { compositeValue, ok := value.(*CompositeValue) if !ok { @@ -16359,6 +16363,10 @@ func (v *CompositeValue) StorageAddress() atree.Address { return v.dictionary.Address() } +func (v *CompositeValue) ValueID() atree.ValueID { + return v.dictionary.ValueID() +} + func (v *CompositeValue) RemoveField( interpreter *Interpreter, _ LocationRange, @@ -16446,7 +16454,7 @@ func (v *CompositeValue) setBaseValue(interpreter *Interpreter, base *CompositeV // the base reference can only be borrowed with the declared type of the attachment's base v.base = NewEphemeralReferenceValue(interpreter, false, base, baseType) - interpreter.trackReferencedResourceKindedValue(base.SlabID(), base) + interpreter.trackReferencedResourceKindedValue(base.ValueID(), base) } func attachmentMemberName(ty sema.Type) string { @@ -16476,7 +16484,7 @@ func attachmentBaseAndSelfValues( base = v.getBaseValue(interpreter, locationRange) // in attachment functions, self is a reference value self = NewEphemeralReferenceValue(interpreter, false, v, interpreter.MustSemaTypeOfValue(v)) - interpreter.trackReferencedResourceKindedValue(v.SlabID(), v) + interpreter.trackReferencedResourceKindedValue(v.ValueID(), v) return } @@ -16527,7 +16535,7 @@ func (v *CompositeValue) GetTypeKey( attachment.setBaseValue(interpreter, v) attachmentRef := NewEphemeralReferenceValue(interpreter, false, attachment, ty) - interpreter.trackReferencedResourceKindedValue(attachment.SlabID(), attachment) + interpreter.trackReferencedResourceKindedValue(attachment.ValueID(), attachment) return NewSomeValueNonCopying(interpreter, attachmentRef) } @@ -16736,7 +16744,7 @@ func (v *DictionaryValue) Iterate(interpreter *Interpreter, f func(key, value Va } } if v.IsResourceKinded(interpreter) { - interpreter.withMutationPrevention(v.SlabID(), iterate) + interpreter.withMutationPrevention(v.ValueID(), iterate) } else { iterate() } @@ -16834,10 +16842,10 @@ func (v *DictionaryValue) Destroy(interpreter *Interpreter, locationRange Locati }() } - slabID := v.SlabID() + valueID := v.ValueID() interpreter.withResourceDestruction( - slabID, + valueID, locationRange, func() { v.Iterate(interpreter, func(key, value Value) (resume bool) { @@ -16857,8 +16865,8 @@ func (v *DictionaryValue) Destroy(interpreter *Interpreter, locationRange Locati } interpreter.updateReferencedResource( - slabID, - slabID, + valueID, + valueID, func(value ReferenceTrackedResourceKindedValue) { dictionaryValue, ok := value.(*DictionaryValue) if !ok { @@ -16913,7 +16921,7 @@ func (v *DictionaryValue) ForEachKey( } if v.IsResourceKinded(interpreter) { - interpreter.withMutationPrevention(v.SlabID(), iterate) + interpreter.withMutationPrevention(v.ValueID(), iterate) } else { iterate() } @@ -16985,7 +16993,7 @@ func (v *DictionaryValue) SetKey( keyValue Value, value Value, ) { - interpreter.validateMutation(v.SlabID(), locationRange) + interpreter.validateMutation(v.ValueID(), locationRange) config := interpreter.SharedState.Config @@ -17269,7 +17277,7 @@ func (v *DictionaryValue) Remove( keyValue Value, ) OptionalValue { - interpreter.validateMutation(v.SlabID(), locationRange) + interpreter.validateMutation(v.ValueID(), locationRange) valueComparator := newValueComparator(interpreter, locationRange) hashInputProvider := newHashInputProvider(interpreter, locationRange) @@ -17326,7 +17334,7 @@ func (v *DictionaryValue) Insert( keyValue, value Value, ) OptionalValue { - interpreter.validateMutation(v.SlabID(), locationRange) + interpreter.validateMutation(v.ValueID(), locationRange) // length increases by 1 dataSlabs, metaDataSlabs := common.AdditionalAtreeMemoryUsage(v.dictionary.Count(), v.elementSize, false) @@ -17579,7 +17587,7 @@ func (v *DictionaryValue) Transfer( }() } - currentSlabID := v.SlabID() + currentValueID := v.ValueID() dictionary := v.dictionary @@ -17663,11 +17671,11 @@ func (v *DictionaryValue) Transfer( res = v } - newSlabID := dictionary.SlabID() + newValueID := dictionary.ValueID() interpreter.updateReferencedResource( - currentSlabID, - newSlabID, + currentValueID, + newValueID, func(value ReferenceTrackedResourceKindedValue) { dictionaryValue, ok := value.(*DictionaryValue) if !ok { @@ -17794,6 +17802,10 @@ func (v *DictionaryValue) StorageAddress() atree.Address { return v.dictionary.Address() } +func (v *DictionaryValue) ValueID() atree.ValueID { + return v.dictionary.ValueID() +} + func (v *DictionaryValue) SemaType(interpreter *Interpreter) *sema.DictionaryType { if v.semaType == nil { // this function will panic already if this conversion fails