diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index bec60c4348..d5ae88ee2e 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -288,7 +288,7 @@ public T Pop() where T : StackItem /// protected virtual void PostExecuteInstruction(Instruction instruction) { - if (ReferenceCounter.Count < Limits.MaxStackSize) return; + if (ReferenceCounter.Count <= Limits.MaxStackSize) return; if (ReferenceCounter.CheckZeroReferred() > Limits.MaxStackSize) throw new InvalidOperationException($"MaxStackSize exceed: {ReferenceCounter.Count}"); } diff --git a/src/Neo.VM/JumpTable/JumpTable.Compound.cs b/src/Neo.VM/JumpTable/JumpTable.Compound.cs index 817b460cf9..038bbf609c 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Compound.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Compound.cs @@ -119,6 +119,7 @@ public virtual void Unpack(ExecutionEngine engine, Instruction instruction) default: throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {compound.Type}"); } + engine.ReferenceCounter.TryCleanTrackedItem(compound); engine.Push(compound.Count); } diff --git a/src/Neo.VM/ReferenceCounter.cs b/src/Neo.VM/ReferenceCounter.cs index f9ea08a2e2..82bf565870 100644 --- a/src/Neo.VM/ReferenceCounter.cs +++ b/src/Neo.VM/ReferenceCounter.cs @@ -292,5 +292,16 @@ internal void RemoveStackReference(StackItem item) if (--item.StackReferences == 0) _zeroReferred.Add(item); } + + internal bool TryCleanTrackedItem(StackItem item) + { + if (item.StackReferences > 0 || item.ObjectReferences?.Values.Any(p => p.References > 0 && p.Item.OnStack) == true) + // Still referred by stack or some compound item + return false; + if (item is CompoundType compound) + _referencesCount -= compound.SubItemsCount; + item.Cleanup(); + return _trackedItems.Remove(item); + } } }