diff --git a/Directory.Build.props b/Directory.Build.props index 65eb7e5b..9e9f3635 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ true - 35.0.0 + 44.0.0 $(WasmtimeVersion)$(WasmtimeDotnetVersion)-dev $(WasmtimeVersion)$(WasmtimeDotnetVersion) diff --git a/src/Function.cs b/src/Function.cs index 947bd986..6b71f70e 100644 --- a/src/Function.cs +++ b/src/Function.cs @@ -305,7 +305,7 @@ private unsafe void InvokeWithoutReturn(Span arguments, StoreContext s // `wasmtime_externref_new` failed). for (int releaseIndex = 0; releaseIndex < i; releaseIndex++) { - args[releaseIndex].Release(store); + args[releaseIndex].Dispose(); } throw; @@ -347,7 +347,7 @@ private unsafe void InvokeWithoutReturn(Span arguments, StoreContext s { for (int i = 0; i < Results.Count; ++i) { - resultsSpan[i].Release(store); + resultsSpan[i].Dispose(); } } } @@ -355,7 +355,7 @@ private unsafe void InvokeWithoutReturn(Span arguments, StoreContext s { for (int i = 0; i < arguments.Length; ++i) { - args[i].Release(store); + args[i].Dispose(); } } } @@ -672,7 +672,7 @@ internal static unsafe IntPtr InvokeUntypedCallback(UntypedCallbackDelegate call // of already allocated result values. for (int releaseIndex = 0; releaseIndex < i; releaseIndex++) { - results[releaseIndex].Release(caller.Store); + results[releaseIndex].Dispose(); } throw; diff --git a/src/Global.cs b/src/Global.cs index 2eb37407..96e3da1a 100644 --- a/src/Global.cs +++ b/src/Global.cs @@ -131,7 +131,7 @@ public Global(Store store, ValueKind kind, object? initialValue, Mutability muta } finally { - value.Release(store); + value.Dispose(); } } @@ -152,7 +152,7 @@ public Global(Store store, ValueKind kind, object? initialValue, Mutability muta } finally { - v.Release(store); + v.Dispose(); } } @@ -176,7 +176,7 @@ public void SetValue(object? value) } finally { - v.Release(store); + v.Dispose(); } } @@ -325,7 +325,7 @@ public T GetValue() } finally { - v.Release(_store); + v.Dispose(); } } @@ -350,7 +350,7 @@ public void SetValue(T value) } finally { - v.Release(_store); + v.Dispose(); } } diff --git a/src/Memory.cs b/src/Memory.cs index 45189440..a3d1a7ea 100644 --- a/src/Memory.cs +++ b/src/Memory.cs @@ -45,11 +45,17 @@ public Memory(Store store, long minimum = 0, long? maximum = null, bool is64Bit Is64Bit = is64Bit; IsShared = false; - var typeHandle = Native.wasmtime_memorytype_new((ulong)minimum, maximum is not null, (ulong)(maximum ?? 0), is64Bit, IsShared); + IntPtr typeHandle; + var error = Native.wasmtime_memorytype_new((ulong)minimum, maximum is not null, (ulong)(maximum ?? 0), is64Bit, IsShared, PageSizeLog2, out typeHandle); + + if (error != IntPtr.Zero){ + throw WasmtimeException.FromOwnedError(error); + } + try { - var error = Native.wasmtime_memory_new(store.Context.handle, typeHandle, out this.memory); + error = Native.wasmtime_memory_new(store.Context.handle, typeHandle, out this.memory); GC.KeepAlive(store); if (error != IntPtr.Zero) @@ -62,6 +68,8 @@ public Memory(Store store, long minimum = 0, long? maximum = null, bool is64Bit Native.wasm_memorytype_delete(typeHandle); } } + + private const int PageSizeLog2 = 16; /// /// The size, in bytes, of a WebAssembly memory page. @@ -602,7 +610,7 @@ internal static class Native public static extern IntPtr wasmtime_memory_type(IntPtr context, in ExternMemory memory); [DllImport(Engine.LibraryName)] - public static extern IntPtr wasmtime_memorytype_new(ulong min, [MarshalAs(UnmanagedType.I1)] bool max_present, ulong max, [MarshalAs(UnmanagedType.I1)] bool is_64, [MarshalAs(UnmanagedType.I1)] bool shared); + public static extern IntPtr wasmtime_memorytype_new(ulong min, [MarshalAs(UnmanagedType.I1)] bool max_present, ulong max, [MarshalAs(UnmanagedType.I1)] bool is_64, [MarshalAs(UnmanagedType.I1)] bool shared, byte page_size_log2, out IntPtr ret); [DllImport(Engine.LibraryName)] public static extern ulong wasmtime_memorytype_minimum(IntPtr type); diff --git a/src/Store.cs b/src/Store.cs index d53295ab..405fe5f8 100644 --- a/src/Store.cs +++ b/src/Store.cs @@ -17,7 +17,11 @@ internal StoreContext(IntPtr handle) internal void GC() { - Native.wasmtime_context_gc(handle); + var error = Native.wasmtime_context_gc(handle); + if (error != IntPtr.Zero) + { + throw WasmtimeException.FromOwnedError(error); + } } internal ulong GetFuel() @@ -84,7 +88,7 @@ public void SetEpochDeadline(ulong deadline) private static class Native { [DllImport(Engine.LibraryName)] - public static extern void wasmtime_context_gc(IntPtr handle); + public static extern IntPtr wasmtime_context_gc(IntPtr handle); [DllImport(Engine.LibraryName)] public static extern IntPtr wasmtime_context_set_fuel(IntPtr handle, ulong fuel); diff --git a/src/Table.cs b/src/Table.cs index 34fb1139..24716219 100644 --- a/src/Table.cs +++ b/src/Table.cs @@ -92,7 +92,7 @@ public Table(Store store, TableKind kind, object? initialValue, uint initial, ui } finally { - value.Release(store); + value.Dispose(); } } @@ -134,7 +134,7 @@ public Table(Store store, TableKind kind, object? initialValue, uint initial, ui } finally { - v.Release(store); + v.Dispose(); } } @@ -159,7 +159,7 @@ public void SetElement(uint index, object? value) } finally { - v.Release(store); + v.Dispose(); } } @@ -198,7 +198,7 @@ public ulong Grow(uint delta, object? initialValue) } finally { - v.Release(store); + v.Dispose(); } } diff --git a/src/TrapException.cs b/src/TrapException.cs index a158dd0d..09ac7775 100644 --- a/src/TrapException.cs +++ b/src/TrapException.cs @@ -37,41 +37,32 @@ public enum TrapCode Unreachable = 9, /// The trap was the result of interrupting execution. Interrupt = 10, - /// - /// The trap was the result of executing a function that was `canon lift`'d, then `canonlower`'d, then called. - /// - /// - /// When the component model feature is enabled this trap represents a function that was `canon lift`'d, - /// then `canonlower`'d, then called. This combination of creation of a function in the component model - /// generates a function that always traps and, when called, produces this flavor of trap. - /// - AlwaysTrapAdapter = 11, /// The trap was the result of running out of the configured fuel amount. - OutOfFuel = 12, + OutOfFuel = 11, /// /// The trap was the result of atomic wait operations on non-shared memory. /// - AtomicWaitNonSharedMemory = 13, + AtomicWaitNonSharedMemory = 12, /// /// The trap was the result of a call to a null reference. /// - NullReference = 14, + NullReference = 13, /// /// The trap was the result of an attempt to access beyond the bounds of an array. /// - ArrayOutOfBounds = 15, + ArrayOutOfBounds = 14, /// /// The trap was the result of an allocation that was too large to succeed. /// - AllocationTooLarge = 16, + AllocationTooLarge = 15, /// /// The trap was the result of an attempt to cast a reference to a type that it is not an instance of. /// - CastFailure = 17, + CastFailure = 16, /// /// The trap was the result of a component calling another component that would have violated the reentrance rules. /// - CannotEnterComponent = 18, + CannotEnterComponent = 17, /// /// The trap was the result of an async-lifted export failing to return a valid async result. /// @@ -79,11 +70,129 @@ public enum TrapCode /// An async-lifted export failed to produce a result by calling `task.return` before returning `STATUS_DONE` /// and/or after all host tasks completed. /// - NoAsyncResult = 19, + NoAsyncResult = 18, + /// + /// The trap was the result of suspending to a tag for which there is no active handler. + /// + UnhandledTag = 19, + /// + /// The trap was the result of an attempt to resume a continuation twice. + /// + ContinuationAlreadyConsumed = 20, /// /// The trap was the result of a Pulley opcode executed at runtime when the opcode was disabled at compile time. /// - DisabledOpCode = 20 + DisabledOpCode = 21, + /// + /// The trap was the result of an async event loop deadlocking; i.e. it cannot make further + /// progress given that all host tasks have completed and any/all host-owned stream/future + /// handles have been dropped. + /// + AsyncDeadlock = 22, + /// + /// When the `component-model` feature is enabled this trap was the result of a scenario + /// where a component instance tried to call an import or intrinsic when it wasn't allowed + /// to, e.g. from a post-return function. + /// + CannotLeaveComponent = 23, + /// + /// The trap was the result of a synchronous task attempted to make a potentially blocking + /// call prior to returning. + /// + CannotBlockSyncTask = 24, + /// + /// The trap was the result of a component trying to lift a `char` with an invalid bit pattern. + /// + InvalidChar = 25, + /// + /// The trap was the result of a debug assertion generated for a fused adapter regarding the + /// expected completion of a string encoding operation. + /// + DebugAssertStringEncodingFinished = 26, + /// + /// The trap was the result of a debug assertion generated for a fused adapter regarding a + /// string encoding operation. + /// + DebugAssertEqualCodeUnits = 27, + /// + /// The trap was the result of a debug assertion generated for a fused adapter regarding the + /// alignment of a pointer. + /// + DebugAssertPointerAligned = 28, + /// + /// The trap was the result of a debug assertion generated for a fused adapter regarding the + /// upper bits of a 64-bit value. + /// + DebugAssertUpperBitsUnset = 29, + /// + /// The trap was the result of a component trying to lift or lower a string past the end of its memory. + /// + StringOutOfBounds = 30, + /// + /// The trap was the result of a component tryping to lift or lower a list past the end of its memory. + /// + ListOutOfBounds = 31, + /// + /// The trap was the result of a component using an invalid discriminant when lowering a variant value. + /// + InvalidDiscriminant = 32, + /// + /// The trap was the result of a component passing an unaligned pointer when lifting or + /// lowering a value. + /// + UnalignedPointer = 33, + /// + /// The trap was the result of task.cancel being invoked in an invalid way. + /// + TaskCancelNotCancelled = 34, + /// + /// The trap was the result of task.cancel or task.return being called too many times + /// + TaskCancelOrReturnTwice = 35, + /// + /// The trap was the result of subtask.cancel being invoked after it already finished. + /// + SubtaskCancelAfterTerminal = 36, + /// + /// The trap was the result of task.return being invoked with an invalid type. + /// + TaskReturnInvalid = 37, + /// + /// The trap was the result of waitable-set.drop being invoked on a waitable set with waiters. + /// + WaitableSetDropHasWaiters = 38, + /// + /// The trap was the result of subtask.drop being invoked on a subtask that hasn't resolved yet. + /// + SubtaskDropNotResolved = 39, + /// + /// The trap was the result of thread.new-indirect being invoked with a function that + /// has an invalid type. + /// + ThreadNewIndirectInvalidType = 40, + /// + /// The trap was the result of thread.new-indirect being invoked with an + /// uninitialized function reference. + /// + ThreadNewIndirectUninitialized = 41, + /// + /// The trap was the result of backpressure-related intrinsics overflowing the built-in counter. + /// + BackpressureOverflow = 42, + /// + /// The trap was the result of an invalid code being returned from the callback of an + /// async-lifted function. + /// + UnsupportedCallbackCode = 43, + /// + /// The trap was the result of trying to resume a thread which is not suspended. + /// + CannotResumeThread = 44, + /// + /// The trap was the result of a read/write being issued on a future/stream while there is a + /// pending operation already. + /// + ConcurrentFutureStreamOp = 45, } /// diff --git a/src/Value.cs b/src/Value.cs index eff55005..96b7df83 100644 --- a/src/Value.cs +++ b/src/Value.cs @@ -201,24 +201,16 @@ private static class Native /// /// /// - /// When owning the value and you are finished with using it, you must release/unroot - /// it by calling the method. After that, the - /// must no longer be used. - /// - /// - /// Previously, this type implemented the interface, but since - /// Wasmtime v20.0.0, unrooting the value requires passing a store context, which is why - /// the method needs to explicitly be called, passing a - /// . + /// Although previously this type had its own function for freeing the object, now the + /// interface is implemented. /// /// [StructLayout(LayoutKind.Sequential)] - internal struct Value + internal struct Value : IDisposable { - public void Release(Store store) + public void Dispose() { - Native.wasmtime_val_unroot(store.Context.handle, this); - GC.KeepAlive(store); + Native.wasmtime_val_unroot(this); } public static bool TryGetKind(Type type, out ValueKind kind) @@ -470,7 +462,7 @@ public static class Native public delegate void Finalizer(IntPtr data); [DllImport(Engine.LibraryName)] - public static extern void wasmtime_val_unroot(IntPtr context, in Value val); + public static extern void wasmtime_val_unroot(in Value val); [DllImport(Engine.LibraryName)] [return: MarshalAs(UnmanagedType.I1)] @@ -480,7 +472,7 @@ public static class Native public static extern IntPtr wasmtime_externref_data(IntPtr context, in ExternRef externref); [DllImport(Engine.LibraryName)] - public static extern void wasmtime_externref_unroot(IntPtr context, in ExternRef externref); + public static extern void wasmtime_externref_unroot(in ExternRef externref); [DllImport(Engine.LibraryName)] public static extern void wasmtime_externref_from_raw(IntPtr context, uint raw, out ExternRef @out); @@ -531,6 +523,8 @@ internal struct AnyRef private uint __private1; private uint __private2; + + private uint __private3; } [StructLayout(LayoutKind.Sequential)] @@ -541,5 +535,7 @@ internal struct ExternRef private uint __private1; private uint __private2; + + private uint __private3; } } diff --git a/src/ValueRaw.cs b/src/ValueRaw.cs index 180adc34..1d4affef 100644 --- a/src/ValueRaw.cs +++ b/src/ValueRaw.cs @@ -273,7 +273,7 @@ private GenericValueRawConverter() } finally { - Value.Native.wasmtime_externref_unroot(storeContext.handle, externref); + Value.Native.wasmtime_externref_unroot(externref); } } @@ -323,7 +323,7 @@ public void Box(StoreContext storeContext, Store store, ref ValueRaw valueRaw, T { // We still must unroot the old externref afterwards because // wasmtime_externref_to_raw doesn't transfer ownership. - Value.Native.wasmtime_externref_unroot(storeContext.handle, externref); + Value.Native.wasmtime_externref_unroot(externref); } }