Skip to content

Commit

Permalink
Update to recent Wasmtime C API changes regarding values.
Browse files Browse the repository at this point in the history
This includes updates for:
- bytecodealliance/wasmtime#8451
- bytecodealliance/wasmtime#8461
- bytecodealliance/wasmtime#8011

TODOs:
- Allocating an `externref` can now fail (by `wasmtime_externref_new` returning `false`). Currently, we throw a `WasmtimeException` in that case. We need to check where that exception can be thrown, and whether we need to do any additional clean-up (e.g. when converting arguments for a function call).
- Check whether it's ok to compare the `__private` field of externs (which has been remaned in the C API, previously it was `index`).
- `anyref` type is not yet supported, but I'm not sure what exactly it is and whether we need to add it.

Fixes bytecodealliance#315
  • Loading branch information
kpreisser committed Jun 24, 2024
1 parent b2b0480 commit 1baabf1
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 93 deletions.
14 changes: 9 additions & 5 deletions src/Externs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,35 @@ namespace Wasmtime
internal struct ExternFunc
{
public ulong store;
public UIntPtr index;
public nuint __private;
}

[StructLayout(LayoutKind.Sequential)]
internal struct ExternTable
{
public ulong store;
public UIntPtr index;
public nuint __private;
}

[StructLayout(LayoutKind.Sequential)]
internal struct ExternMemory
{
public ulong store;
public UIntPtr index;
public nuint __private;
}

[StructLayout(LayoutKind.Sequential)]
internal struct ExternInstance
{
public ulong store;
public UIntPtr index;
public nuint __private;
}

[StructLayout(LayoutKind.Sequential)]
internal struct ExternGlobal
{
public ulong store;
public UIntPtr index;
public nuint __private;
}

internal enum ExternKind : byte
Expand All @@ -44,6 +44,7 @@ internal enum ExternKind : byte
Global,
Table,
Memory,
SharedMemory,
}

[StructLayout(LayoutKind.Explicit)]
Expand All @@ -60,6 +61,9 @@ internal struct ExternUnion

[FieldOffset(0)]
public ExternMemory memory;

[FieldOffset(0)]
public IntPtr sharedmemory;
}

[StructLayout(LayoutKind.Sequential)]
Expand Down
9 changes: 4 additions & 5 deletions src/Function.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ out externFunc
/// <summary>
/// Determines if the underlying function reference is null.
/// </summary>
public bool IsNull => func.index == UIntPtr.Zero && func.store == 0;
public bool IsNull => func.IsNull();

/// <summary>
/// Represents a null function reference.
Expand Down Expand Up @@ -333,15 +333,15 @@ private unsafe void InvokeWithoutReturn(Span<ValueRaw> arguments, StoreContext s
{
for (int i = 0; i < Results.Count; ++i)
{
resultsSpan[i].Dispose();
resultsSpan[i].Release(store);
}
}
}
finally
{
for (int i = 0; i < arguments.Length; ++i)
{
args[i].Dispose();
args[i].Release(store);
}
}

Expand Down Expand Up @@ -444,8 +444,7 @@ Extern IExternal.AsExtern()
internal Function()
{
this.store = null;
this.func.store = 0;
this.func.index = (UIntPtr)0;
this.func = default;
this.Parameters = this.Results = Array.Empty<ValueKind>();
}

Expand Down
61 changes: 45 additions & 16 deletions src/Global.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,20 @@ public Global(Store store, ValueKind kind, object? initialValue, Mutability muta
}

var value = Value.FromObject(store, initialValue, Kind);
var error = Native.wasmtime_global_new(store.Context.handle, globalType, in value, out this.global);
GC.KeepAlive(store);

value.Dispose();
try
{
var error = Native.wasmtime_global_new(store.Context.handle, globalType, in value, out this.global);
GC.KeepAlive(store);

if (error != IntPtr.Zero)
if (error != IntPtr.Zero)
{
throw WasmtimeException.FromOwnedError(error);
}
}
finally
{
throw WasmtimeException.FromOwnedError(error);
value.Release(store);
}
}

Expand All @@ -139,9 +145,15 @@ public Global(Store store, ValueKind kind, object? initialValue, Mutability muta
Native.wasmtime_global_get(context.handle, this.global, out var v);
GC.KeepAlive(store);

var val = v.ToObject(store);
v.Dispose();
return val;
try
{
var val = v.ToObject(store);
return val;
}
finally
{
v.Release(store);
}
}

/// <summary>
Expand All @@ -156,10 +168,16 @@ public void SetValue(object? value)
}

var v = Value.FromObject(store, value, Kind);
Native.wasmtime_global_set(store.Context.handle, this.global, in v);
GC.KeepAlive(store);

v.Dispose();
try
{
Native.wasmtime_global_set(store.Context.handle, this.global, in v);
GC.KeepAlive(store);
}
finally
{
v.Release(store);
}
}

/// <summary>
Expand Down Expand Up @@ -300,10 +318,15 @@ public T GetValue()
Native.wasmtime_global_get(context.handle, _global.global, out var v);
GC.KeepAlive(_store);

var result = _converter.Unbox(_store, v.ToValueBox(_store));
v.Dispose();

return result;
try
{
var result = _converter.Unbox(_store, v.ToValueBox(_store));
return result;
}
finally
{
v.Release(_store);
}
}

/// <summary>
Expand All @@ -317,12 +340,18 @@ public void SetValue(T value)
throw new InvalidOperationException("The global is immutable and cannot be changed.");
}

using (var v = _converter.Box(value).ToValue(_store, _global.Kind))
var v = _converter.Box(value).ToValue(_store, _global.Kind);

try
{
var context = _store.Context;
Native.wasmtime_global_set(context.handle, _global.global, in v);
GC.KeepAlive(_store);
}
finally
{
v.Release(_store);
}
}

Extern IExternal.AsExtern()
Expand Down
7 changes: 4 additions & 3 deletions src/Store.cs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ private static class Native

internal Function GetCachedExtern(ExternFunc @extern)
{
var key = (ExternKind.Func, @extern.store, @extern.index);
// TODO: Check if using the __private field is Ok.
var key = (ExternKind.Func, @extern.store, @extern.__private);

if (!_externCache.TryGetValue(key, out var func))
{
Expand All @@ -357,7 +358,7 @@ internal Function GetCachedExtern(ExternFunc @extern)

internal Memory GetCachedExtern(ExternMemory @extern)
{
var key = (ExternKind.Memory, @extern.store, @extern.index);
var key = (ExternKind.Memory, @extern.store, @extern.__private);

if (!_externCache.TryGetValue(key, out var mem))
{
Expand All @@ -370,7 +371,7 @@ internal Memory GetCachedExtern(ExternMemory @extern)

internal Global GetCachedExtern(ExternGlobal @extern)
{
var key = (ExternKind.Global, @extern.store, @extern.index);
var key = (ExternKind.Global, @extern.store, @extern.__private);

if (!_externCache.TryGetValue(key, out var global))
{
Expand Down
66 changes: 46 additions & 20 deletions src/Table.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,20 @@ public Table(Store store, TableKind kind, object? initialValue, uint initial, ui
));

var value = Value.FromObject(store, initialValue, Kind);
var error = Native.wasmtime_table_new(store.Context.handle, tableType, in value, out this.table);
GC.KeepAlive(store);
value.Dispose();

if (error != IntPtr.Zero)
try
{
throw WasmtimeException.FromOwnedError(error);
var error = Native.wasmtime_table_new(store.Context.handle, tableType, in value, out this.table);
GC.KeepAlive(store);

if (error != IntPtr.Zero)
{
throw WasmtimeException.FromOwnedError(error);
}
}
finally
{
value.Release(store);
}
}

Expand Down Expand Up @@ -120,9 +127,15 @@ public Table(Store store, TableKind kind, object? initialValue, uint initial, ui

GC.KeepAlive(store);

var val = v.ToObject(store);
v.Dispose();
return val;
try
{
var val = v.ToObject(store);
return val;
}
finally
{
v.Release(store);
}
}

/// <summary>
Expand All @@ -133,13 +146,20 @@ public Table(Store store, TableKind kind, object? initialValue, uint initial, ui
public void SetElement(uint index, object? value)
{
var v = Value.FromObject(store, value, Kind);
var error = Native.wasmtime_table_set(store.Context.handle, this.table, index, v);
GC.KeepAlive(store);
v.Dispose();

if (error != IntPtr.Zero)
try
{
throw WasmtimeException.FromOwnedError(error);
var error = Native.wasmtime_table_set(store.Context.handle, this.table, index, v);
GC.KeepAlive(store);

if (error != IntPtr.Zero)
{
throw WasmtimeException.FromOwnedError(error);
}
}
finally
{
v.Release(store);
}
}

Expand All @@ -164,16 +184,22 @@ public uint Grow(uint delta, object? initialValue)
{
var v = Value.FromObject(store, initialValue, Kind);

var error = Native.wasmtime_table_grow(store.Context.handle, this.table, delta, v, out var prev);
GC.KeepAlive(store);
v.Dispose();
try
{
var error = Native.wasmtime_table_grow(store.Context.handle, this.table, delta, v, out var prev);
GC.KeepAlive(store);

if (error != IntPtr.Zero)
{
throw WasmtimeException.FromOwnedError(error);
}

if (error != IntPtr.Zero)
return prev;
}
finally
{
throw WasmtimeException.FromOwnedError(error);
v.Release(store);
}

return prev;
}

internal Table(Store store, ExternTable table)
Expand Down
Loading

0 comments on commit 1baabf1

Please sign in to comment.