Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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 b)
{
_innerBuffer.Span[index] = b;
_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