Skip to content

Commit 7307841

Browse files
authored
Add support for 64-bit Memory (#169)
* Add support for enabling the Memory64 proposal, which was added to the Wasmtime C API with bytecodealliance/wasmtime#3182. Additionally, add tests to verify the new APIs added with #166 are able to access a memory beyond the 4 GiB area. * Follow-Up: Adjust the API to match the new C API introduced with bytecodealliance/wasmtime#3153, in order to support 64-bit memory. This also fixes the definition of native functions wasmtime_memory_size and wasmtime_memory_grow, which previously incorrectly used a UInt32 instead of UInt64, and config functions taking a bool parameter, which were previously missing the MarshalAsAttribute (to marshal a Boolean as 1 byte instead of 4 bytes). * Follow-Up: Validate the arguments. * Simplify. * Simplify.
1 parent 8660f62 commit 7307841

13 files changed

Lines changed: 289 additions & 87 deletions

src/Config.cs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,17 @@ public Config WithMultiMemory(bool enable)
185185
return this;
186186
}
187187

188+
/// <summary>
189+
/// Sets whether or not enable WebAssembly memory64 support.
190+
/// </summary>
191+
/// <param name="enable">True to enable WebAssembly memory64 support or false to disable.</param>
192+
/// <returns>Returns the current config.</returns>
193+
public Config WithMemory64(bool enable)
194+
{
195+
Native.wasmtime_config_wasm_memory64_set(handle, enable);
196+
return this;
197+
}
198+
188199
/// <summary>
189200
/// Sets the compiler strategy to use.
190201
/// </summary>
@@ -358,43 +369,46 @@ private static class Native
358369
public static extern void wasm_config_delete(IntPtr config);
359370

360371
[DllImport(Engine.LibraryName)]
361-
public static extern void wasmtime_config_debug_info_set(Handle config, bool enable);
372+
public static extern void wasmtime_config_debug_info_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
373+
374+
[DllImport(Engine.LibraryName)]
375+
public static extern void wasmtime_config_epoch_interruption_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
362376

363377
[DllImport(Engine.LibraryName)]
364-
public static extern void wasmtime_config_epoch_interruption_set(Handle config, bool enable);
378+
public static extern void wasmtime_config_consume_fuel_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
365379

366380
[DllImport(Engine.LibraryName)]
367-
public static extern void wasmtime_config_consume_fuel_set(Handle config, bool enable);
381+
public static extern void wasmtime_config_max_wasm_stack_set(Handle config, nuint size);
368382

369383
[DllImport(Engine.LibraryName)]
370-
public static extern void wasmtime_config_max_wasm_stack_set(Handle config, UIntPtr size);
384+
public static extern void wasmtime_config_wasm_threads_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
371385

372386
[DllImport(Engine.LibraryName)]
373-
public static extern void wasmtime_config_wasm_threads_set(Handle config, bool enable);
387+
public static extern void wasmtime_config_wasm_reference_types_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
374388

375389
[DllImport(Engine.LibraryName)]
376-
public static extern void wasmtime_config_wasm_reference_types_set(Handle config, bool enable);
390+
public static extern void wasmtime_config_wasm_simd_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
377391

378392
[DllImport(Engine.LibraryName)]
379-
public static extern void wasmtime_config_wasm_simd_set(Handle config, bool enable);
393+
public static extern void wasmtime_config_wasm_bulk_memory_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
380394

381395
[DllImport(Engine.LibraryName)]
382-
public static extern void wasmtime_config_wasm_bulk_memory_set(Handle config, bool enable);
396+
public static extern void wasmtime_config_wasm_multi_value_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
383397

384398
[DllImport(Engine.LibraryName)]
385-
public static extern void wasmtime_config_wasm_multi_value_set(Handle config, bool enable);
399+
public static extern void wasmtime_config_wasm_multi_memory_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
386400

387401
[DllImport(Engine.LibraryName)]
388-
public static extern void wasmtime_config_wasm_multi_memory_set(Handle config, bool enable);
402+
public static extern void wasmtime_config_wasm_memory64_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
389403

390404
[DllImport(Engine.LibraryName)]
391405
public static extern void wasmtime_config_strategy_set(Handle config, byte strategy);
392406

393407
[DllImport(Engine.LibraryName)]
394-
public static extern void wasmtime_config_cranelift_debug_verifier_set(Handle config, bool enable);
408+
public static extern void wasmtime_config_cranelift_debug_verifier_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
395409

396410
[DllImport(Engine.LibraryName)]
397-
public static extern void wasmtime_config_cranelift_nan_canonicalization_set(Handle config, bool enable);
411+
public static extern void wasmtime_config_cranelift_nan_canonicalization_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool enable);
398412

399413
[DllImport(Engine.LibraryName)]
400414
public static extern void wasmtime_config_cranelift_opt_level_set(Handle config, byte level);

src/Export.cs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,21 +192,34 @@ internal MemoryExport(IntPtr exportType, IntPtr externType) : base(exportType)
192192

193193
unsafe
194194
{
195-
var limits = Memory.Native.wasm_memorytype_limits(type);
196-
Minimum = limits->min;
197-
Maximum = limits->max;
195+
Minimum = (long)Memory.Native.wasmtime_memorytype_minimum(type);
196+
197+
if (Memory.Native.wasmtime_memorytype_maximum(type, out ulong max))
198+
{
199+
Maximum = (long)max;
200+
}
201+
202+
Is64Bit = Memory.Native.wasmtime_memorytype_is64(type);
198203
}
199204
}
200205

201206
/// <summary>
202-
/// The minimum memory size (in WebAssembly page units).
207+
/// Gets the minimum memory size (in WebAssembly page units).
203208
/// </summary>
204-
public uint Minimum { get; private set; }
209+
/// <value>The minimum memory size (in WebAssembly page units).</value>
210+
public long Minimum { get; }
205211

206212
/// <summary>
207-
/// The maximum memory size (in WebAssembly page units).
213+
/// Gets the maximum memory size (in WebAssembly page units).
208214
/// </summary>
209-
public uint Maximum { get; private set; }
215+
/// <value>The maximum memory size (in WebAssembly page units), or <c>null</c> if no maximum is specified.</value>
216+
public long? Maximum { get; }
217+
218+
/// <summary>
219+
/// Gets a value that indicates whether this type of memory represents a 64-bit memory.
220+
/// </summary>
221+
/// <value><c>true</c> if this type of memory represents a 64-bit memory, <c>false</c> if it represents a 32-bit memory.</value>
222+
public bool Is64Bit { get; }
210223

211224
private static class Native
212225
{

src/Import.cs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,21 +205,34 @@ internal MemoryImport(IntPtr importType, IntPtr externType) : base(importType)
205205

206206
unsafe
207207
{
208-
var limits = Memory.Native.wasm_memorytype_limits(type);
209-
Minimum = limits->min;
210-
Maximum = limits->max;
208+
Minimum = (long)Memory.Native.wasmtime_memorytype_minimum(type);
209+
210+
if (Memory.Native.wasmtime_memorytype_maximum(type, out ulong max))
211+
{
212+
Maximum = (long)max;
213+
}
214+
215+
Is64Bit = Memory.Native.wasmtime_memorytype_is64(type);
211216
}
212217
}
213218

214219
/// <summary>
215-
/// The minimum memory size (in WebAssembly page units).
220+
/// Gets the minimum memory size (in WebAssembly page units).
216221
/// </summary>
217-
public uint Minimum { get; private set; }
222+
/// <value>The minimum memory size (in WebAssembly page units).</value>
223+
public long Minimum { get; }
218224

219225
/// <summary>
220-
/// The maximum memory size (in WebAssembly page units).
226+
/// Gets the maximum memory size (in WebAssembly page units).
221227
/// </summary>
222-
public uint Maximum { get; private set; }
228+
/// <value>The maximum memory size (in WebAssembly page units), or <c>null</c> if no maximum is specified.</value>
229+
public long? Maximum { get; }
230+
231+
/// <summary>
232+
/// Gets a value that indicates whether this type of memory represents a 64-bit memory.
233+
/// </summary>
234+
/// <value><c>true</c> if this type of memory represents a 64-bit memory, <c>false</c> if it represents a 32-bit memory.</value>
235+
public bool Is64Bit { get; }
223236

224237
private static class Native
225238
{

src/Memory.cs

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,25 @@ public class Memory : IExternal
1616
/// </summary>
1717
/// <param name="store">The store to create the memory in.</param>
1818
/// <param name="minimum">The minimum number of WebAssembly pages.</param>
19-
/// <param name="maximum">The maximum number of WebAssembly pages.</param>
20-
public Memory(IStore store, uint minimum = 0, uint maximum = uint.MaxValue)
19+
/// <param name="maximum">The maximum number of WebAssembly pages, or <c>null</c> to not specify a maximum.</param>
20+
/// <param name="is64Bit"><c>true</c> when memory type represents a 64-bit memory, <c>false</c> when it represents a 32-bit memory.</param>
21+
public Memory(IStore store, long minimum = 0, long? maximum = null, bool is64Bit = false)
2122
{
2223
if (store is null)
2324
{
2425
throw new ArgumentNullException(nameof(store));
2526
}
2627

28+
if (minimum < 0)
29+
{
30+
throw new ArgumentOutOfRangeException(nameof(minimum));
31+
}
32+
33+
if (maximum < 0)
34+
{
35+
throw new ArgumentOutOfRangeException(nameof(maximum));
36+
}
37+
2738
if (maximum < minimum)
2839
{
2940
throw new ArgumentException("The maximum cannot be less than the minimum.", nameof(maximum));
@@ -32,14 +43,12 @@ public Memory(IStore store, uint minimum = 0, uint maximum = uint.MaxValue)
3243
this.store = store;
3344
Minimum = minimum;
3445
Maximum = maximum;
46+
Is64Bit = is64Bit;
3547

3648
unsafe
3749
{
38-
var limits = new Native.Limits();
39-
limits.min = minimum;
40-
limits.max = maximum;
50+
using var type = new TypeHandle(Native.wasmtime_memorytype_new((ulong)minimum, maximum is not null, (ulong)(maximum ?? 0), is64Bit));
4151

42-
using var type = new TypeHandle(Native.wasm_memorytype_new(limits));
4352
var error = Native.wasmtime_memory_new(store.Context.handle, type, out this.memory);
4453
if (error != IntPtr.Zero)
4554
{
@@ -54,22 +63,30 @@ public Memory(IStore store, uint minimum = 0, uint maximum = uint.MaxValue)
5463
public const int PageSize = 65536;
5564

5665
/// <summary>
57-
/// The minimum memory size (in WebAssembly page units).
66+
/// Gets the minimum memory size (in WebAssembly page units).
5867
/// </summary>
59-
public uint Minimum { get; private set; }
68+
/// <value>The minimum memory size (in WebAssembly page units).</value>
69+
public long Minimum { get; }
6070

6171
/// <summary>
62-
/// The maximum memory size (in WebAssembly page units).
72+
/// Gets the maximum memory size (in WebAssembly page units).
6373
/// </summary>
64-
public uint Maximum { get; private set; }
74+
/// <value>The maximum memory size (in WebAssembly page units), or <c>null</c> if no maximum is specified.</value>
75+
public long? Maximum { get; }
76+
77+
/// <summary>
78+
/// Gets a value that indicates whether this type of memory represents a 64-bit memory.
79+
/// </summary>
80+
/// <value><c>true</c> if this type of memory represents a 64-bit memory, <c>false</c> otherwise.</value>
81+
public bool Is64Bit { get; }
6582

6683
/// <summary>
6784
/// Gets the current size of the memory, in WebAssembly page units.
6885
/// </summary>
6986
/// <returns>Returns the current size of the memory, in WebAssembly page units.</returns>
70-
public uint GetSize()
87+
public long GetSize()
7188
{
72-
return Native.wasmtime_memory_size(store.Context.handle, this.memory);
89+
return (long)Native.wasmtime_memory_size(store.Context.handle, this.memory);
7390
}
7491

7592
/// <summary>
@@ -78,7 +95,7 @@ public uint GetSize()
7895
/// <returns>Returns the current length of the memory, in bytes.</returns>
7996
public long GetLength()
8097
{
81-
return checked((long)(nuint)Native.wasmtime_memory_data_size(store.Context.handle, this.memory));
98+
return checked((long)Native.wasmtime_memory_data_size(store.Context.handle, this.memory));
8299
}
83100

84101
/// <summary>
@@ -485,20 +502,25 @@ public void WriteDouble(long address, double value)
485502
/// <param name="delta">The number of WebAssembly pages to grow the memory by.</param>
486503
/// <returns>Returns the previous size of the Webassembly memory, in pages.</returns>
487504
/// <remarks>This method will invalidate previously returned values from `GetSpan`.</remarks>
488-
public uint Grow(uint delta)
505+
public long Grow(long delta)
489506
{
490507
if (store is null)
491508
{
492509
throw new ArgumentNullException(nameof(store));
493510
}
494511

495-
var error = Native.wasmtime_memory_grow(store.Context.handle, this.memory, delta, out var prev);
512+
if (delta < 0)
513+
{
514+
throw new ArgumentOutOfRangeException(nameof(delta));
515+
}
516+
517+
var error = Native.wasmtime_memory_grow(store.Context.handle, this.memory, (ulong)delta, out var prev);
496518
if (error != IntPtr.Zero)
497519
{
498520
throw WasmtimeException.FromOwnedError(error);
499521
}
500522

501-
return prev;
523+
return (long)prev;
502524
}
503525

504526
Extern IExternal.AsExtern()
@@ -518,9 +540,14 @@ internal Memory(IStore store, ExternMemory memory)
518540

519541
unsafe
520542
{
521-
var limits = Native.wasm_memorytype_limits(type.DangerousGetHandle());
522-
Minimum = limits->min;
523-
Maximum = limits->max;
543+
Minimum = (long)Native.wasmtime_memorytype_minimum(type.DangerousGetHandle());
544+
545+
if (Native.wasmtime_memorytype_maximum(type.DangerousGetHandle(), out ulong max))
546+
{
547+
Maximum = (long)max;
548+
}
549+
550+
Is64Bit = Native.wasmtime_memorytype_is64(type.DangerousGetHandle());
524551
}
525552
}
526553

@@ -541,37 +568,37 @@ protected override bool ReleaseHandle()
541568

542569
internal static class Native
543570
{
544-
[StructLayout(LayoutKind.Sequential)]
545-
internal struct Limits
546-
{
547-
public uint min;
548-
549-
public uint max;
550-
}
551-
552571
[DllImport(Engine.LibraryName)]
553572
public static extern IntPtr wasmtime_memory_new(IntPtr context, TypeHandle type, out ExternMemory memory);
554573

555574
[DllImport(Engine.LibraryName)]
556575
public static unsafe extern byte* wasmtime_memory_data(IntPtr context, in ExternMemory memory);
557576

558577
[DllImport(Engine.LibraryName)]
559-
public static extern UIntPtr wasmtime_memory_data_size(IntPtr context, in ExternMemory memory);
578+
public static extern nuint wasmtime_memory_data_size(IntPtr context, in ExternMemory memory);
560579

561580
[DllImport(Engine.LibraryName)]
562-
public static extern uint wasmtime_memory_size(IntPtr context, in ExternMemory memory);
581+
public static extern ulong wasmtime_memory_size(IntPtr context, in ExternMemory memory);
563582

564583
[DllImport(Engine.LibraryName)]
565-
public static extern IntPtr wasmtime_memory_grow(IntPtr context, in ExternMemory memory, uint delta, out uint prev);
584+
public static extern IntPtr wasmtime_memory_grow(IntPtr context, in ExternMemory memory, ulong delta, out ulong prev);
566585

567586
[DllImport(Engine.LibraryName)]
568587
public static extern IntPtr wasmtime_memory_type(IntPtr context, in ExternMemory memory);
569588

570589
[DllImport(Engine.LibraryName)]
571-
public static extern IntPtr wasm_memorytype_new(in Limits limits);
590+
public static extern IntPtr wasmtime_memorytype_new(ulong min, [MarshalAs(UnmanagedType.I1)] bool max_present, ulong max, [MarshalAs(UnmanagedType.I1)] bool is_64);
591+
592+
[DllImport(Engine.LibraryName)]
593+
public static unsafe extern ulong wasmtime_memorytype_minimum(IntPtr type);
594+
595+
[DllImport(Engine.LibraryName)]
596+
[return: MarshalAs(UnmanagedType.I1)]
597+
public static unsafe extern bool wasmtime_memorytype_maximum(IntPtr type, out ulong max);
572598

573599
[DllImport(Engine.LibraryName)]
574-
public static unsafe extern Limits* wasm_memorytype_limits(IntPtr type);
600+
[return: MarshalAs(UnmanagedType.I1)]
601+
public static unsafe extern bool wasmtime_memorytype_is64(IntPtr type);
575602

576603
[DllImport(Engine.LibraryName)]
577604
public static extern void wasm_memorytype_delete(IntPtr handle);

0 commit comments

Comments
 (0)