Skip to content

Commit 12d1378

Browse files
committed
assume aligned reads
1 parent 0d158f5 commit 12d1378

File tree

5 files changed

+47
-15
lines changed

5 files changed

+47
-15
lines changed

src/runtime/Util.cs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
using System;
1+
using System;
22
using System.Runtime.InteropServices;
33

44
namespace Python.Runtime
55
{
66
internal class Util
77
{
8+
// On Windows, a C long is always 32 bits.
9+
static readonly bool clong32bit = Runtime.IsWindows || Runtime.Is32Bit;
10+
811
internal static Int64 ReadCLong(IntPtr tp, int offset)
912
{
10-
// On Windows, a C long is always 32 bits.
11-
if (Runtime.IsWindows || Runtime.Is32Bit)
13+
if (clong32bit)
1214
{
1315
return Marshal.ReadInt32(tp, offset);
1416
}
@@ -20,7 +22,7 @@ internal static Int64 ReadCLong(IntPtr tp, int offset)
2022

2123
internal static void WriteCLong(IntPtr type, int offset, Int64 flags)
2224
{
23-
if (Runtime.IsWindows || Runtime.Is32Bit)
25+
if (clong32bit)
2426
{
2527
Marshal.WriteInt32(type, offset, (Int32)(flags & 0xffffffffL));
2628
}
@@ -29,5 +31,34 @@ internal static void WriteCLong(IntPtr type, int offset, Int64 flags)
2931
Marshal.WriteInt64(type, offset, flags);
3032
}
3133
}
34+
35+
internal static unsafe Int32 ReadInt32Aligned(IntPtr ptr, int byteOffset)
36+
{
37+
byte* address = (byte*)ptr + byteOffset;
38+
return *((int*)address);
39+
}
40+
41+
internal static unsafe Int64 ReadInt64Aligned(IntPtr ptr, int byteOffset)
42+
{
43+
byte* address = (byte*)ptr + byteOffset;
44+
return *((long*)address);
45+
}
46+
47+
internal static unsafe Int64 ReadCLongAligned(IntPtr ptr, int byteOffset)
48+
{
49+
return clong32bit ? ReadInt32Aligned(ptr, byteOffset) : ReadInt64Aligned(ptr, byteOffset);
50+
}
51+
52+
internal static unsafe IntPtr ReadIntPtrAligned(IntPtr ptr, int byteOffset)
53+
{
54+
byte* address = (byte*)ptr + byteOffset;
55+
return *((IntPtr*)address);
56+
}
57+
58+
internal static unsafe void WriteIntPtrAligned(IntPtr ptr, int byteOffset, IntPtr value)
59+
{
60+
byte* address = (byte*)ptr + byteOffset;
61+
*((IntPtr*)address) = value;
62+
}
3263
}
33-
}
64+
}

src/runtime/clrobject.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,20 @@ internal CLRObject(object ob, IntPtr tp)
1111
{
1212
IntPtr py = Runtime.PyType_GenericAlloc(tp, 0);
1313

14-
long flags = Util.ReadCLong(tp, TypeOffset.tp_flags);
14+
long flags = Util.ReadCLongAligned(tp, TypeOffset.tp_flags);
1515
if ((flags & TypeFlags.Subclass) != 0)
1616
{
17-
IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.TypeDictOffset(tp));
17+
int dictOffset = ObjectOffset.TypeDictOffset(tp);
18+
IntPtr dict = Util.ReadIntPtrAligned(py, dictOffset);
1819
if (dict == IntPtr.Zero)
1920
{
2021
dict = Runtime.PyDict_New();
21-
Marshal.WriteIntPtr(py, ObjectOffset.TypeDictOffset(tp), dict);
22+
Util.WriteIntPtrAligned(py, dictOffset, dict);
2223
}
2324
}
2425

2526
GCHandle gc = GCHandle.Alloc(this);
26-
Marshal.WriteIntPtr(py, ObjectOffset.magic(tp), (IntPtr)gc);
27+
Util.WriteIntPtrAligned(py, ObjectOffset.magic(tp), (IntPtr)gc);
2728
tpHandle = tp;
2829
pyHandle = py;
2930
gcHandle = gc;

src/runtime/interop.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ static ManagedDataOffsets()
8787
static int BaseOffset(IntPtr type)
8888
{
8989
Debug.Assert(type != IntPtr.Zero);
90-
int typeSize = Marshal.ReadInt32(type, TypeOffset.tp_basicsize);
90+
int typeSize = (int)Util.ReadIntPtrAligned(type, TypeOffset.tp_basicsize);
9191
Debug.Assert(typeSize > 0 && typeSize <= ExceptionOffset.Size());
9292
return typeSize;
9393
}

src/runtime/managedtype.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ internal static ManagedType GetManagedObject(IntPtr ob)
2828
tp = ob;
2929
}
3030

31-
var flags = Util.ReadCLong(tp, TypeOffset.tp_flags);
31+
var flags = Util.ReadCLongAligned(tp, TypeOffset.tp_flags);
3232
if ((flags & TypeFlags.Managed) != 0)
3333
{
3434
IntPtr op = tp == ob
35-
? Marshal.ReadIntPtr(tp, TypeOffset.magic())
36-
: Marshal.ReadIntPtr(ob, ObjectOffset.magic(tp));
35+
? Util.ReadIntPtrAligned(tp, TypeOffset.magic())
36+
: Util.ReadIntPtrAligned(ob, ObjectOffset.magic(tp));
3737
if (op == IntPtr.Zero)
3838
{
3939
return null;

src/runtime/runtime.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,10 @@ public class Runtime
191191
internal static object IsFinalizingLock = new object();
192192
internal static bool IsFinalizing;
193193

194-
internal static bool Is32Bit = IntPtr.Size == 4;
194+
internal static readonly bool Is32Bit = IntPtr.Size == 4;
195195

196196
// .NET core: System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
197-
internal static bool IsWindows = Environment.OSVersion.Platform == PlatformID.Win32NT;
197+
internal static readonly bool IsWindows = Environment.OSVersion.Platform == PlatformID.Win32NT;
198198

199199
internal static bool IsPython2 = pyversionnumber < 30;
200200
internal static bool IsPython3 = pyversionnumber >= 30;

0 commit comments

Comments
 (0)