Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/Neo.VM/JumpTable/JumpTable.Compound.cs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ public virtual void PickItem(ExecutionEngine engine, Instruction instruction)
var index = (int)key.GetInteger();
if (index < 0 || index >= buffer.Size)
throw new CatchableException($"The index of {nameof(Buffer)} is out of range, {index}/[0, {buffer.Size}).");
engine.Push((BigInteger)buffer.InnerBuffer.Span[index]);
engine.Push((BigInteger)buffer.GetSpan()[index]);
break;
}
default:
Expand Down Expand Up @@ -465,7 +465,7 @@ public virtual void SetItem(ExecutionEngine engine, Instruction instruction)
var b = (int)p.GetInteger();
if (b < sbyte.MinValue || b > byte.MaxValue)
throw new InvalidOperationException($"Overflow in {instruction.OpCode}, {b} is not a byte type.");
buffer.InnerBuffer.Span[index] = (byte)b;
buffer.Set(index, (byte)b);
break;
}
default:
Expand All @@ -490,7 +490,7 @@ public virtual void ReverseItems(ExecutionEngine engine, Instruction instruction
array.Reverse();
break;
case Buffer buffer:
buffer.InnerBuffer.Span.Reverse();
buffer.Reverse();
break;
default:
throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}");
Expand Down
12 changes: 6 additions & 6 deletions src/Neo.VM/JumpTable/JumpTable.Splice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public virtual void Memcpy(ExecutionEngine engine, Instruction instruction)
if (checked(di + count) > dst.Size)
throw new InvalidOperationException($"The destination index + count is out of range for {nameof(OpCode.MEMCPY)}, index: {di}, count: {count}, {di}/[0, {dst.Size}].");
// TODO: check if we can optimize the memcpy by using peek instead of dup then pop
src.Slice(si, count).CopyTo(dst.InnerBuffer.Span[di..]);
dst.CopyInto(src.Slice(si, count), di);
}

/// <summary>
Expand All @@ -76,8 +76,8 @@ public virtual void Cat(ExecutionEngine engine, Instruction instruction)
int length = x1.Length + x2.Length;
engine.Limits.AssertMaxItemSize(length);
Buffer result = new(length, false);
x1.CopyTo(result.InnerBuffer.Span);
x2.CopyTo(result.InnerBuffer.Span[x1.Length..]);
result.CopyInto(x1);
result.CopyInto(x2, x1.Length);
engine.Push(result);
}

Expand All @@ -101,7 +101,7 @@ public virtual void SubStr(ExecutionEngine engine, Instruction instruction)
if (checked(index + count) > x.Length)
throw new InvalidOperationException($"The index + count is out of range for {nameof(OpCode.SUBSTR)}, index: {index}, count: {count}, {index + count}/[0, {x.Length}].");
Buffer result = new(count, false);
x.Slice(index, count).CopyTo(result.InnerBuffer.Span);
result.CopyInto(x.Slice(index, count));
engine.Push(result);
}

Expand All @@ -122,7 +122,7 @@ public virtual void Left(ExecutionEngine engine, Instruction instruction)
if (count > x.Length)
throw new InvalidOperationException($"The count is out of range for {nameof(OpCode.LEFT)}, {count}/[0, {x.Length}].");
Buffer result = new(count, false);
x[..count].CopyTo(result.InnerBuffer.Span);
result.CopyInto(x[..count]);
engine.Push(result);
}

Expand All @@ -143,7 +143,7 @@ public virtual void Right(ExecutionEngine engine, Instruction instruction)
if (count > x.Length)
throw new InvalidOperationException($"The count is out of range for {nameof(OpCode.RIGHT)}, {count}/[0, {x.Length}].");
Buffer result = new(count, false);
x[^count..^0].CopyTo(result.InnerBuffer.Span);
result.CopyInto(x[^count..^0]);
engine.Push(result);
}
}
51 changes: 36 additions & 15 deletions src/Neo.VM/Types/Buffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ public class Buffer : StackItem
/// <summary>
/// The internal byte array used to store the actual data.
/// </summary>
public readonly Memory<byte> InnerBuffer;
private readonly Memory<byte> _innerBuffer;

/// <summary>
/// The size of the buffer.
/// </summary>
public int Size => InnerBuffer.Length;
public int Size => _innerBuffer.Length;
public override StackItemType Type => StackItemType.Buffer;

private readonly byte[] _buffer;
Expand All @@ -45,8 +45,8 @@ public class Buffer : StackItem
public Buffer(int size, bool zeroInitialize = true)
{
_buffer = ArrayPool<byte>.Shared.Rent(size);
InnerBuffer = new Memory<byte>(_buffer, 0, size);
if (zeroInitialize) InnerBuffer.Span.Clear();
_innerBuffer = new Memory<byte>(_buffer, 0, size);
if (zeroInitialize) _innerBuffer.Span.Clear();
}

/// <summary>
Expand All @@ -55,7 +55,7 @@ public Buffer(int size, bool zeroInitialize = true)
/// <param name="data">The data to be contained in this buffer.</param>
public Buffer(ReadOnlySpan<byte> data) : this(data.Length, false)
{
data.CopyTo(InnerBuffer.Span);
data.CopyTo(_innerBuffer.Span);
}

internal override void Cleanup()
Expand All @@ -74,16 +74,16 @@ public override StackItem ConvertTo(StackItemType type)
switch (type)
{
case StackItemType.Integer:
if (InnerBuffer.Length > Integer.MaxSize)
if (_innerBuffer.Length > Integer.MaxSize)
throw new InvalidCastException();
return new BigInteger(InnerBuffer.Span);
return new BigInteger(_innerBuffer.Span);
case StackItemType.ByteString:
#if NET5_0_OR_GREATER
byte[] clone = GC.AllocateUninitializedArray<byte>(InnerBuffer.Length);
byte[] clone = GC.AllocateUninitializedArray<byte>(_innerBuffer.Length);
#else
byte[] clone = new byte[InnerBuffer.Length];
byte[] clone = new byte[_innerBuffer.Length];
#endif
InnerBuffer.CopyTo(clone);
_innerBuffer.CopyTo(clone);
return clone;
default:
return base.ConvertTo(type);
Expand All @@ -93,7 +93,7 @@ public override StackItem ConvertTo(StackItemType type)
internal override StackItem DeepCopy(Dictionary<StackItem, StackItem> refMap, bool asImmutable)
{
if (refMap.TryGetValue(this, out StackItem? mappedItem)) return mappedItem;
StackItem result = asImmutable ? new ByteString(InnerBuffer.ToArray()) : new Buffer(InnerBuffer.Span);
StackItem result = asImmutable ? new ByteString(_innerBuffer.ToArray()) : new Buffer(_innerBuffer.Span);
refMap.Add(this, result);
return result;
}
Expand All @@ -105,7 +105,7 @@ public override bool GetBoolean()

public override ReadOnlySpan<byte> GetSpan()
{
return InnerBuffer.Span;
return _innerBuffer.Span;
}

public override string ToString()
Expand All @@ -115,10 +115,31 @@ public override string ToString()
: $"(\"Base64: {Convert.ToBase64String(GetSpan())}\")";
}

public override int GetHashCode()
#region Write operations

public void Set(int index, byte value)
{
_innerBuffer.Span[index] = value;
_hashCode = 0;
}

public void Reverse()
{
_innerBuffer.Span.Reverse();
_hashCode = 0;
}

public void CopyInto(ReadOnlySpan<byte> span)
{
// Hash code can't be cached because the buffer is mutable
span.CopyTo(_innerBuffer.Span);
_hashCode = 0;
return base.GetHashCode();
}

public void CopyInto(ReadOnlySpan<byte> span, int index)
{
span.CopyTo(_innerBuffer.Span[index..]);
_hashCode = 0;
}

#endregion
}
2 changes: 1 addition & 1 deletion tests/Neo.VM.Tests/VMJsonTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ private static JObject ItemToJson(StackItem item)
case Boolean v: value = new JValue(v.GetBoolean()); break;
case Integer v: value = new JValue(v.GetInteger().ToString()); break;
case ByteString v: value = new JValue(v.GetSpan().ToArray()); break;
case Buffer v: value = new JValue(v.InnerBuffer.ToArray()); break;
case Buffer v: value = new JValue(v.GetSpan().ToArray()); break;
//case VM.Types.Struct v:
case Array v:
{
Expand Down