Skip to content

Commit

Permalink
Move ReferenceCounter to an interface (#3524)
Browse files Browse the repository at this point in the history
* Reference counter V2

* Remove warning

* Interface

* Change to interface

* Update

* Remove V2
  • Loading branch information
shargon authored Oct 11, 2024
1 parent 20c8661 commit 018e17b
Show file tree
Hide file tree
Showing 49 changed files with 170 additions and 125 deletions.
2 changes: 1 addition & 1 deletion benchmarks/Neo.VM.Benchmarks/TestArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public TestArray(IEnumerable<StackItem>? items = null)
/// </summary>
/// <param name="referenceCounter">The <see cref="ReferenceCounter"/> to be used by this array.</param>
/// <param name="items">The items to be included in the array.</param>
public TestArray(ReferenceCounter? referenceCounter, IEnumerable<StackItem>? items = null)
public TestArray(IReferenceCounter? referenceCounter, IEnumerable<StackItem>? items = null)
: base(referenceCounter)
{
_array = items switch
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/Neo.VM.Benchmarks/TestStruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public TestStruct(IEnumerable<StackItem>? fields = null)
/// </summary>
/// <param name="referenceCounter">The <see cref="ReferenceCounter"/> to be used by this structure.</param>
/// <param name="fields">The fields to be included in the structure.</param>
public TestStruct(ReferenceCounter? referenceCounter, IEnumerable<StackItem>? fields = null)
public TestStruct(IReferenceCounter? referenceCounter, IEnumerable<StackItem>? fields = null)
: base(referenceCounter, fields)
{
}
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/Neo.VM.Benchmarks/VMTypes/Benchmarks_DeepCopy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public void BenchNestedTestArrayDeepCopyWithReferenceCounter()
_ = root.DeepCopy();
}

private static void CreateNestedArray(Array? rootArray, int depth, int elementsPerLevel = 1, ReferenceCounter? referenceCounter = null)
private static void CreateNestedArray(Array? rootArray, int depth, int elementsPerLevel = 1, IReferenceCounter? referenceCounter = null)
{
if (depth < 0)
{
Expand All @@ -95,7 +95,7 @@ private static void CreateNestedArray(Array? rootArray, int depth, int elementsP
}
}

private static void CreateNestedTestArray(TestArray rootArray, int depth, int elementsPerLevel = 1, ReferenceCounter referenceCounter = null)
private static void CreateNestedTestArray(TestArray rootArray, int depth, int elementsPerLevel = 1, IReferenceCounter referenceCounter = null)

Check warning on line 98 in benchmarks/Neo.VM.Benchmarks/VMTypes/Benchmarks_DeepCopy.cs

View workflow job for this annotation

GitHub Actions / Test-Everything

Cannot convert null literal to non-nullable reference type.

Check warning on line 98 in benchmarks/Neo.VM.Benchmarks/VMTypes/Benchmarks_DeepCopy.cs

View workflow job for this annotation

GitHub Actions / Test-Everything

Cannot convert null literal to non-nullable reference type.

Check warning on line 98 in benchmarks/Neo.VM.Benchmarks/VMTypes/Benchmarks_DeepCopy.cs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

Cannot convert null literal to non-nullable reference type.

Check warning on line 98 in benchmarks/Neo.VM.Benchmarks/VMTypes/Benchmarks_DeepCopy.cs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

Cannot convert null literal to non-nullable reference type.

Check warning on line 98 in benchmarks/Neo.VM.Benchmarks/VMTypes/Benchmarks_DeepCopy.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

Cannot convert null literal to non-nullable reference type.

Check warning on line 98 in benchmarks/Neo.VM.Benchmarks/VMTypes/Benchmarks_DeepCopy.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

Cannot convert null literal to non-nullable reference type.
{
if (depth < 0)
{
Expand Down
8 changes: 4 additions & 4 deletions src/Neo.VM/EvaluationStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ namespace Neo.VM
/// </summary>
public sealed class EvaluationStack : IReadOnlyList<StackItem>
{
private readonly List<StackItem> innerList = new();
private readonly ReferenceCounter referenceCounter;
private readonly List<StackItem> innerList = [];
private readonly IReferenceCounter referenceCounter;

internal ReferenceCounter ReferenceCounter => referenceCounter;
internal IReferenceCounter ReferenceCounter => referenceCounter;

internal EvaluationStack(ReferenceCounter referenceCounter)
internal EvaluationStack(IReferenceCounter referenceCounter)
{
this.referenceCounter = referenceCounter;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Neo.VM/ExecutionContext.SharedStates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private class SharedStates
public Slot? StaticFields;
public readonly Dictionary<Type, object> States;

public SharedStates(Script script, ReferenceCounter referenceCounter)
public SharedStates(Script script, IReferenceCounter referenceCounter)
{
Script = script;
EvaluationStack = new EvaluationStack(referenceCounter);
Expand Down
2 changes: 1 addition & 1 deletion src/Neo.VM/ExecutionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public Instruction? NextInstruction
}
}

internal ExecutionContext(Script script, int rvcount, ReferenceCounter referenceCounter)
internal ExecutionContext(Script script, int rvcount, IReferenceCounter referenceCounter)
: this(new SharedStates(script, referenceCounter), rvcount, 0)
{
}
Expand Down
2 changes: 1 addition & 1 deletion src/Neo.VM/ExecutionEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class ExecutionEngine : IDisposable
/// <summary>
/// Used for reference counting of objects in the VM.
/// </summary>
public ReferenceCounter ReferenceCounter { get; }
public IReferenceCounter ReferenceCounter { get; }

/// <summary>
/// The invocation stack of the VM.
Expand Down
91 changes: 91 additions & 0 deletions src/Neo.VM/IReferenceCounter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright (C) 2015-2024 The Neo Project.
//
// IReferenceCounter.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using Neo.VM.Types;

namespace Neo.VM
{
/// <summary>
/// Used for reference counting of objects in the VM.
/// </summary>
public interface IReferenceCounter
{
/// <summary>
/// Gets the count of references.
/// </summary>
int Count { get; }

/// <summary>
/// Adds an item to the zero-referred list.
///
/// This method is used when an item has no remaining references.
/// It adds the item to the zero-referred list to be checked for cleanup later.
///
/// Use this method when you detect that an item has zero references and may need to be cleaned up.
/// </summary>
/// <param name="item">The item to add.</param>
void AddZeroReferred(StackItem item);

/// <summary>
/// Adds a reference to a specified item with a parent compound type.
///
/// This method is used when an item gains a new reference through a parent compound type.
/// It increments the reference count and updates the tracking structures if necessary.
///
/// Use this method when you need to add a reference from a compound type to a stack item.
/// </summary>
/// <param name="item">The item to add a reference to.</param>
/// <param name="parent">The parent compound type.</param>
void AddReference(StackItem item, CompoundType parent);

/// <summary>
/// Adds a stack reference to a specified item with a count.
///
/// This method is used when an item gains a new stack reference, usually due to being pushed onto the evaluation stack.
/// It increments the reference count and updates the tracking structures if necessary.
///
/// Use this method when you need to add one or more stack references to a stack item.
/// </summary>
/// <param name="item">The item to add a stack reference to.</param>
/// <param name="count">The number of references to add.</param>
void AddStackReference(StackItem item, int count = 1);

/// <summary>
/// Removes a reference from a specified item with a parent compound type.
///
/// This method is used when an item loses a reference from a parent compound type.
/// It decrements the reference count and updates the tracking structures if necessary.
///
/// Use this method when you need to remove a reference from a compound type to a stack item.
/// </summary>
/// <param name="item">The item to remove a reference from.</param>
/// <param name="parent">The parent compound type.</param>
void RemoveReference(StackItem item, CompoundType parent);

/// <summary>
/// Removes a stack reference from a specified item.
///
/// This method is used when an item loses a stack reference, usually due to being popped off the evaluation stack.
/// It decrements the reference count and updates the tracking structures if necessary.
///
/// Use this method when you need to remove one or more stack references from a stack item.
/// </summary>
/// <param name="item">The item to remove a stack reference from.</param>
void RemoveStackReference(StackItem item);

/// <summary>
/// Checks and processes items that have zero references.
/// This method is used to check items in the zero-referred list and clean up those that are no longer needed.
/// </summary>
/// <returns>The current reference count.</returns>
int CheckZeroReferred();
}
}
72 changes: 13 additions & 59 deletions src/Neo.VM/ReferenceCounter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Neo.VM
/// <summary>
/// Used for reference counting of objects in the VM.
/// </summary>
public sealed class ReferenceCounter
public sealed class ReferenceCounter : IReferenceCounter
{
// If set to true, all items will be tracked regardless of their type.
private const bool TrackAllItems = false;
Expand All @@ -38,9 +38,7 @@ public sealed class ReferenceCounter
// Keeps the total count of references.
private int _referencesCount = 0;

/// <summary>
/// Gets the count of references.
/// </summary>
/// <inheritdoc/>
public int Count => _referencesCount;

/// <summary>
Expand All @@ -61,17 +59,8 @@ private static bool NeedTrack(StackItem item)
return false;
}

/// <summary>
/// Adds a reference to a specified item with a parent compound type.
///
/// This method is used when an item gains a new reference through a parent compound type.
/// It increments the reference count and updates the tracking structures if necessary.
///
/// Use this method when you need to add a reference from a compound type to a stack item.
/// </summary>
/// <param name="item">The item to add a reference to.</param>
/// <param name="parent">The parent compound type.</param>
internal void AddReference(StackItem item, CompoundType parent)
/// <inheritdoc/>
public void AddReference(StackItem item, CompoundType parent)
{
// Increment the reference count.
_referencesCount++;
Expand All @@ -98,17 +87,8 @@ internal void AddReference(StackItem item, CompoundType parent)
pEntry.References++;
}

/// <summary>
/// Adds a stack reference to a specified item with a count.
///
/// This method is used when an item gains a new stack reference, usually due to being pushed onto the evaluation stack.
/// It increments the reference count and updates the tracking structures if necessary.
///
/// Use this method when you need to add one or more stack references to a stack item.
/// </summary>
/// <param name="item">The item to add a stack reference to.</param>
/// <param name="count">The number of references to add.</param>
internal void AddStackReference(StackItem item, int count = 1)
/// <inheritdoc/>
public void AddStackReference(StackItem item, int count = 1)
{
// Increment the reference count by the specified count.
_referencesCount += count;
Expand All @@ -127,16 +107,8 @@ internal void AddStackReference(StackItem item, int count = 1)
_zeroReferred.Remove(item);
}

/// <summary>
/// Adds an item to the zero-referred list.
///
/// This method is used when an item has no remaining references.
/// It adds the item to the zero-referred list to be checked for cleanup later.
///
/// Use this method when you detect that an item has zero references and may need to be cleaned up.
/// </summary>
/// <param name="item">The item to add.</param>
internal void AddZeroReferred(StackItem item)
/// <inheritdoc/>
public void AddZeroReferred(StackItem item)
{
// Add the item to the _zeroReferred set.
_zeroReferred.Add(item);
Expand All @@ -158,7 +130,7 @@ internal void AddZeroReferred(StackItem item)
/// Use this method periodically to clean up items with zero references and free up memory.
/// </summary>
/// <returns>The current reference count.</returns>
internal int CheckZeroReferred()
public int CheckZeroReferred()
{
// If there are items with zero references, process them.
if (_zeroReferred.Count > 0)
Expand Down Expand Up @@ -241,18 +213,8 @@ internal int CheckZeroReferred()
return _referencesCount;
}


/// <summary>
/// Removes a reference from a specified item with a parent compound type.
///
/// This method is used when an item loses a reference from a parent compound type.
/// It decrements the reference count and updates the tracking structures if necessary.
///
/// Use this method when you need to remove a reference from a compound type to a stack item.
/// </summary>
/// <param name="item">The item to remove a reference from.</param>
/// <param name="parent">The parent compound type.</param>
internal void RemoveReference(StackItem item, CompoundType parent)
/// <inheritdoc/>
public void RemoveReference(StackItem item, CompoundType parent)
{
// Decrement the reference count.
_referencesCount--;
Expand All @@ -271,16 +233,8 @@ internal void RemoveReference(StackItem item, CompoundType parent)
_zeroReferred.Add(item);
}

/// <summary>
/// Removes a stack reference from a specified item.
///
/// This method is used when an item loses a stack reference, usually due to being popped off the evaluation stack.
/// It decrements the reference count and updates the tracking structures if necessary.
///
/// Use this method when you need to remove one or more stack references from a stack item.
/// </summary>
/// <param name="item">The item to remove a stack reference from.</param>
internal void RemoveStackReference(StackItem item)
/// <inheritdoc/>
public void RemoveStackReference(StackItem item)
{
// Decrement the reference count.
_referencesCount--;
Expand Down
6 changes: 3 additions & 3 deletions src/Neo.VM/Slot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Neo.VM
/// </summary>
public class Slot : IReadOnlyList<StackItem>
{
private readonly ReferenceCounter referenceCounter;
private readonly IReferenceCounter referenceCounter;
private readonly StackItem[] items;

/// <summary>
Expand Down Expand Up @@ -53,7 +53,7 @@ internal set
/// </summary>
/// <param name="items">The items to be contained.</param>
/// <param name="referenceCounter">The reference counter to be used.</param>
public Slot(StackItem[] items, ReferenceCounter referenceCounter)
public Slot(StackItem[] items, IReferenceCounter referenceCounter)
{
this.referenceCounter = referenceCounter;
this.items = items;
Expand All @@ -66,7 +66,7 @@ public Slot(StackItem[] items, ReferenceCounter referenceCounter)
/// </summary>
/// <param name="count">Indicates the number of items contained in the slot.</param>
/// <param name="referenceCounter">The reference counter to be used.</param>
public Slot(int count, ReferenceCounter referenceCounter)
public Slot(int count, IReferenceCounter referenceCounter)
{
this.referenceCounter = referenceCounter;
items = new StackItem[count];
Expand Down
2 changes: 1 addition & 1 deletion src/Neo.VM/Types/Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public Array(IEnumerable<StackItem>? items = null)
/// </summary>
/// <param name="referenceCounter">The <see cref="ReferenceCounter"/> to be used by this array.</param>
/// <param name="items">The items to be included in the array.</param>
public Array(ReferenceCounter? referenceCounter, IEnumerable<StackItem>? items = null)
public Array(IReferenceCounter? referenceCounter, IEnumerable<StackItem>? items = null)
: base(referenceCounter)
{
_array = items switch
Expand Down
4 changes: 2 additions & 2 deletions src/Neo.VM/Types/CompoundType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ public abstract class CompoundType : StackItem
/// <summary>
/// The reference counter used to count the items in the VM object.
/// </summary>
protected internal readonly ReferenceCounter? ReferenceCounter;
protected internal readonly IReferenceCounter? ReferenceCounter;

/// <summary>
/// Create a new <see cref="CompoundType"/> with the specified reference counter.
/// </summary>
/// <param name="referenceCounter">The reference counter to be used.</param>
protected CompoundType(ReferenceCounter? referenceCounter)
protected CompoundType(IReferenceCounter? referenceCounter)
{
ReferenceCounter = referenceCounter;
referenceCounter?.AddZeroReferred(this);
Expand Down
2 changes: 1 addition & 1 deletion src/Neo.VM/Types/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public StackItem this[PrimitiveType key]
/// Create a new map with the specified reference counter.
/// </summary>
/// <param name="referenceCounter">The reference counter to be used.</param>
public Map(ReferenceCounter? referenceCounter = null)
public Map(IReferenceCounter? referenceCounter = null)
: base(referenceCounter)
{
}
Expand Down
2 changes: 1 addition & 1 deletion src/Neo.VM/Types/Struct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public Struct(IEnumerable<StackItem>? fields = null)
/// </summary>
/// <param name="referenceCounter">The <see cref="ReferenceCounter"/> to be used by this structure.</param>
/// <param name="fields">The fields to be included in the structure.</param>
public Struct(ReferenceCounter? referenceCounter, IEnumerable<StackItem>? fields = null)
public Struct(IReferenceCounter? referenceCounter, IEnumerable<StackItem>? fields = null)
: base(referenceCounter, fields)
{
}
Expand Down
2 changes: 1 addition & 1 deletion src/Neo/Network/P2P/Payloads/Conditions/AndCondition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public override JObject ToJson()
return json;
}

public override StackItem ToStackItem(ReferenceCounter referenceCounter)
public override StackItem ToStackItem(IReferenceCounter referenceCounter)
{
var result = (VM.Types.Array)base.ToStackItem(referenceCounter);
result.Add(new VM.Types.Array(referenceCounter, Expressions.Select(p => p.ToStackItem(referenceCounter))));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public override JObject ToJson()
return json;
}

public override StackItem ToStackItem(ReferenceCounter referenceCounter)
public override StackItem ToStackItem(IReferenceCounter referenceCounter)
{
var result = (VM.Types.Array)base.ToStackItem(referenceCounter);
result.Add(Expression);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public override JObject ToJson()
return json;
}

public override StackItem ToStackItem(ReferenceCounter referenceCounter)
public override StackItem ToStackItem(IReferenceCounter referenceCounter)
{
var result = (VM.Types.Array)base.ToStackItem(referenceCounter);
result.Add(Hash.ToArray());
Expand Down
Loading

0 comments on commit 018e17b

Please sign in to comment.