Skip to content

Commit

Permalink
Avoid calling GetTypeAlignment for known types.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmds committed Nov 20, 2024
1 parent 6a641dd commit e82ebf4
Show file tree
Hide file tree
Showing 10 changed files with 37 additions and 72 deletions.
4 changes: 2 additions & 2 deletions src/Tmds.DBus.Protocol/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ private void ClearHeaders()
return null;
}

headerFieldLength = (uint)ProtocolConstants.Align((int)headerFieldLength, DBusType.Struct);
headerFieldLength = (uint)ProtocolConstants.Align((int)headerFieldLength, ProtocolConstants.StructAlignment);

long totalLength = seqReader.Consumed + headerFieldLength + bodyLength;

Expand Down Expand Up @@ -186,7 +186,7 @@ private void ParseHeader(UnixFdCollection? handles, bool isMonitor)
var reader = new Reader(IsBigEndian, _data.AsReadOnlySequence);
reader.Advance(HeaderFieldsLengthOffset);

ArrayEnd headersEnd = reader.ReadArrayStart(DBusType.Struct);
ArrayEnd headersEnd = reader.ReadArrayStart(ProtocolConstants.StructAlignment);
while (reader.HasNext(headersEnd))
{
MessageHeader hdrType = (MessageHeader)reader.ReadByte();
Expand Down
6 changes: 3 additions & 3 deletions src/Tmds.DBus.Protocol/MessageWriter.Basic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private void WriteStringCore(scoped ReadOnlySpan<byte> span)

private void WriteStringCore(string s)
{
WritePadding(DBusType.UInt32);
WritePadding(ProtocolConstants.UInt32Alignment);
Span<byte> lengthSpan = GetSpan(4);
Advance(4);
int bytesWritten = WriteRaw(s);
Expand All @@ -167,8 +167,8 @@ private void WriteStringCore(string s)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void WritePrimitiveCore<T>(T value, DBusType type)
{
WritePadding(type);
int length = ProtocolConstants.GetFixedTypeLength(type);
int length = Marshal.SizeOf<T>();
WritePadding(length);
var span = GetSpan(length);
Unsafe.WriteUnaligned<T>(ref MemoryMarshal.GetReference(span), value);
Advance(length);
Expand Down
2 changes: 1 addition & 1 deletion src/Tmds.DBus.Protocol/MessageWriter.Dictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Tmds.DBus.Protocol;
public ref partial struct MessageWriter
{
public ArrayStart WriteDictionaryStart()
=> WriteArrayStart(DBusType.Struct);
=> WriteArrayStart(ProtocolConstants.StructAlignment);

public void WriteDictionaryEnd(ArrayStart start)
=> WriteArrayEnd(start);
Expand Down
4 changes: 2 additions & 2 deletions src/Tmds.DBus.Protocol/MessageWriter.Header.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public void WriteSignalHeader(
private void WriteHeaderEnd(ArrayStart start)
{
WriteArrayEnd(start);
WritePadding(DBusType.Struct);
WritePadding(ProtocolConstants.StructAlignment);
}

private ArrayStart WriteHeaderStart(MessageType type, MessageFlags flags)
Expand All @@ -203,7 +203,7 @@ private ArrayStart WriteHeaderStart(MessageType type, MessageFlags flags)
Debug.Assert(_offset == SerialOffset + 4);

// headers
ArrayStart start = WriteArrayStart(DBusType.Struct);
ArrayStart start = WriteArrayStart(ProtocolConstants.StructAlignment);

// UnixFds
WriteStructureStart();
Expand Down
2 changes: 1 addition & 1 deletion src/Tmds.DBus.Protocol/MessageWriter.IntrospectionXml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ internal void WriteIntrospectionXml(
scoped ReadOnlySpan<string> childNames,
IEnumerable<string>? childNamesEnumerable)
{
WritePadding(DBusType.UInt32);
WritePadding(ProtocolConstants.UInt32Alignment);
Span<byte> lengthSpan = GetSpan(4);
Advance(4);

Expand Down
19 changes: 6 additions & 13 deletions src/Tmds.DBus.Protocol/MessageWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,16 @@ internal MessageWriter(MessageBufferPool messagePool, uint serial)
}

public ArrayStart WriteArrayStart(DBusType elementType)
=> WriteArrayStart(ProtocolConstants.GetTypeAlignment(elementType));

private ArrayStart WriteArrayStart(int alignment)
{
// Array length.
WritePadding(DBusType.UInt32);
WritePadding(ProtocolConstants.UInt32Alignment);
Span<byte> lengthSpan = GetSpan(4);
Advance(4);

WritePadding(elementType);
WritePadding(alignment);

return new ArrayStart(lengthSpan, _offset);
}
Expand All @@ -85,7 +88,7 @@ public void WriteArrayEnd(ArrayStart start)

public void WriteStructureStart()
{
WritePadding(DBusType.Struct);
WritePadding(ProtocolConstants.StructAlignment);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand All @@ -96,16 +99,6 @@ private void Advance(int count)
_span = _span.Slice(count);
}

private void WritePadding(DBusType type)
{
int pad = ProtocolConstants.GetPadding(_offset, type);
if (pad != 0)
{
GetSpan(pad).Slice(0, pad).Fill(0);
Advance(pad);
}
}

private void WritePadding(int alignment)
{
int pad = ProtocolConstants.GetPadding(_offset, alignment);
Expand Down
37 changes: 7 additions & 30 deletions src/Tmds.DBus.Protocol/ProtocolConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ static class ProtocolConstants
public static ReadOnlySpan<byte> SignatureSignature => new byte[] { (byte)'g' };
public static ReadOnlySpan<byte> VariantSignature => new byte[] { (byte)'v' };

public const int StructAlignment = 8;
public const int UInt32Alignment = 4;

private static ReadOnlySpan<byte> SingleTypes => new byte[] { (byte)'y', (byte)'b', (byte)'n', (byte)'q', (byte)'i', (byte)'u', (byte)'x', (byte)'t', (byte)'d', (byte)'h', (byte)'s', (byte)'o', (byte)'g', (byte)'v' };

public static bool IsSingleCompleteType(byte b)
Expand All @@ -38,15 +41,15 @@ public static int GetTypeAlignment(DBusType type)
case DBusType.Int16: return 2;
case DBusType.UInt16: return 2;
case DBusType.Int32: return 4;
case DBusType.UInt32: return 4;
case DBusType.UInt32: return UInt32Alignment;
case DBusType.Int64: return 8;
case DBusType.UInt64: return 8;
case DBusType.Double: return 8;
case DBusType.String: return 4;
case DBusType.ObjectPath: return 4;
case DBusType.Signature: return 4;
case DBusType.Array: return 4;
case DBusType.Struct: return 8;
case DBusType.Struct: return StructAlignment;
case DBusType.Variant: return 1;
case DBusType.DictEntry: return 8;
case DBusType.UnixFd: return 4;
Expand All @@ -55,35 +58,9 @@ public static int GetTypeAlignment(DBusType type)
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetFixedTypeLength(DBusType type)
{
switch (type)
{
case DBusType.Byte: return 1;
case DBusType.Bool: return 4;
case DBusType.Int16: return 2;
case DBusType.UInt16: return 2;
case DBusType.Int32: return 4;
case DBusType.UInt32: return 4;
case DBusType.Int64: return 8;
case DBusType.UInt64: return 8;
case DBusType.Double: return 8;
case DBusType.UnixFd: return 4;
default: return 0;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Align(int offset, DBusType type)
{
return offset + GetPadding(offset, type);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetPadding(int offset, DBusType type)
public static int Align(int offset, int alignment)
{
int alignment = GetTypeAlignment(type);
return GetPadding(offset ,alignment);
return offset + GetPadding(offset, alignment);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
6 changes: 3 additions & 3 deletions src/Tmds.DBus.Protocol/Reader.Basic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public ushort ReadUInt16()

public short ReadInt16()
{
AlignReader(DBusType.Int16);
AlignReader(alignment: 2);
bool dataRead = _isBigEndian ? _reader.TryReadBigEndian(out short rv) : _reader.TryReadLittleEndian(out rv);
if (!dataRead)
{
Expand All @@ -35,7 +35,7 @@ public uint ReadUInt32()

public int ReadInt32()
{
AlignReader(DBusType.Int32);
AlignReader(alignment: 4);
bool dataRead = _isBigEndian ? _reader.TryReadBigEndian(out int rv) : _reader.TryReadLittleEndian(out rv);
if (!dataRead)
{
Expand All @@ -49,7 +49,7 @@ public ulong ReadUInt64()

public long ReadInt64()
{
AlignReader(DBusType.Int64);
AlignReader(alignment: 8);
bool dataRead = _isBigEndian ? _reader.TryReadBigEndian(out long rv) : _reader.TryReadLittleEndian(out rv);
if (!dataRead)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Tmds.DBus.Protocol/Reader.Dictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Tmds.DBus.Protocol;
public ref partial struct Reader
{
public ArrayEnd ReadDictionaryStart()
=> ReadArrayStart(DBusType.Struct);
=> ReadArrayStart(ProtocolConstants.StructAlignment);

// Read method for the common 'a{sv}' type.
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026")] // It's safe to call ReadDictionary with these types.
Expand Down
27 changes: 11 additions & 16 deletions src/Tmds.DBus.Protocol/Reader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,8 @@ internal Reader(bool isBigEndian, ReadOnlySequence<byte> sequence, UnixFdCollect
_handleCount = handleCount;
}

public void AlignStruct() => AlignReader(DBusType.Struct);

private void AlignReader(DBusType type)
{
long pad = ProtocolConstants.GetPadding((int)_reader.Consumed, type);
if (pad != 0)
{
_reader.Advance(pad);
}
}
public void AlignStruct()
=> AlignReader(ProtocolConstants.StructAlignment);

private void AlignReader(int alignment)
{
Expand All @@ -45,17 +37,20 @@ private void AlignReader(int alignment)
}

public ArrayEnd ReadArrayStart(DBusType elementType)
=> ReadArrayStart(ProtocolConstants.GetTypeAlignment(elementType));

internal ArrayEnd ReadArrayStart(int alignment)
{
uint arrayLength = ReadUInt32();
AlignReader(elementType);
AlignReader(alignment);
int endOfArray = (int)(_reader.Consumed + arrayLength);
return new ArrayEnd(elementType, endOfArray);
return new ArrayEnd(alignment, endOfArray);
}

public bool HasNext(ArrayEnd iterator)
{
int consumed = (int)_reader.Consumed;
int nextElement = ProtocolConstants.Align(consumed, iterator.Type);
int nextElement = ProtocolConstants.Align(consumed, iterator.Alignment);
if (nextElement >= iterator.EndOfArray)
{
return false;
Expand All @@ -77,12 +72,12 @@ public void SkipTo(ArrayEnd end)

public ref struct ArrayEnd
{
internal readonly DBusType Type;
internal readonly int Alignment;
internal readonly int EndOfArray;

internal ArrayEnd(DBusType type, int endOfArray)
internal ArrayEnd(int alignment, int endOfArray)
{
Type = type;
Alignment = alignment;
EndOfArray = endOfArray;
}
}

0 comments on commit e82ebf4

Please sign in to comment.