Skip to content

Commit ed6e244

Browse files
Bas Geertsemajsturtevant
authored andcommitted
Upgrade to 34.0.1
Breaking changes to C-api: * Layout and size of structs in extern.h has changed * Trap codes have been added and the enum value for OutOfFuel has changed from 11 to 12 Due to externs having different sizes, we can no longer used the same ConcurrentDictionary for caching externals because the key size differs. Different dictionaries are now used depending on the extern type.
1 parent 65fa587 commit ed6e244

File tree

4 files changed

+108
-41
lines changed

4 files changed

+108
-41
lines changed

Directory.Build.props

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
<Project>
22
<PropertyGroup>
3-
<DevBuild Condition="'$(DevBuild)'==''">false</DevBuild>
4-
<WasmtimeVersion Condition="'$(WasmtimeVersion)'==''">33.0.1</WasmtimeVersion>
3+
<DevBuild Condition="'$(DevBuild)'==''">true</DevBuild>
4+
<WasmtimeVersion Condition="'$(WasmtimeVersion)'==''">34.0.1</WasmtimeVersion>
55
<WasmtimeDotnetVersion Condition="'$(WasmtimeDotnetVersion)'==''"></WasmtimeDotnetVersion>
6-
<WasmtimePackageVersion Condition="'$(DevBuild)'=='true'">
7-
$(WasmtimeVersion)$(WasmtimeDotnetVersion)-dev</WasmtimePackageVersion>
8-
<WasmtimePackageVersion Condition="'$(WasmtimePackageVersion)'==''">
9-
$(WasmtimeVersion)$(WasmtimeDotnetVersion)</WasmtimePackageVersion>
6+
<WasmtimePackageVersion Condition="'$(DevBuild)'=='true'">$(WasmtimeVersion)$(WasmtimeDotnetVersion)-dev</WasmtimePackageVersion>
7+
<WasmtimePackageVersion Condition="'$(WasmtimePackageVersion)'==''">$(WasmtimeVersion)$(WasmtimeDotnetVersion)</WasmtimePackageVersion>
108
</PropertyGroup>
119
</Project>

src/Externs.cs

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,69 @@
11
using System;
2+
using System.Diagnostics;
23
using System.Runtime.InteropServices;
34

45
namespace Wasmtime
56
{
67
[StructLayout(LayoutKind.Sequential)]
7-
internal struct ExternFunc
8+
internal record struct ExternFunc
89
{
10+
static ExternFunc() => Debug.Assert(Marshal.SizeOf(typeof(ExternFunc)) == 16);
11+
912
public ulong store;
10-
public nuint __private;
13+
public IntPtr __private;
1114
}
1215

13-
[StructLayout(LayoutKind.Sequential)]
14-
internal struct ExternTable
16+
[StructLayout(LayoutKind.Explicit)]
17+
internal record struct ExternTable
1518
{
19+
static ExternTable() => Debug.Assert(Marshal.SizeOf(typeof(ExternTable)) == 24);
20+
21+
// Use explicit offsets because the struct in the C api has extra padding
22+
// due to field alignments. The total struct size is 24 bytes.
23+
24+
[FieldOffset(0)]
1625
public ulong store;
17-
public nuint __private;
26+
[FieldOffset(8)]
27+
public uint __private1;
28+
[FieldOffset(16)]
29+
public uint __private2;
1830
}
1931

20-
[StructLayout(LayoutKind.Sequential)]
21-
internal struct ExternMemory
32+
33+
[StructLayout(LayoutKind.Explicit)]
34+
internal record struct ExternMemory
2235
{
36+
static ExternMemory() => Debug.Assert(Marshal.SizeOf(typeof(ExternMemory)) == 24);
37+
38+
// Use explicit offsets because the struct in the C api has extra padding
39+
// due to field alignments. The total struct size is 24 bytes.
40+
41+
[FieldOffset(0)]
2342
public ulong store;
24-
public nuint __private;
43+
[FieldOffset(8)]
44+
public uint __private1;
45+
[FieldOffset(16)]
46+
public uint __private2;
2547
}
2648

2749
[StructLayout(LayoutKind.Sequential)]
28-
internal struct ExternInstance
50+
internal record struct ExternInstance
2951
{
52+
static ExternInstance() => Debug.Assert(Marshal.SizeOf(typeof(ExternInstance)) == 16);
53+
3054
public ulong store;
3155
public nuint __private;
3256
}
3357

3458
[StructLayout(LayoutKind.Sequential)]
35-
internal struct ExternGlobal
59+
internal record struct ExternGlobal
3660
{
61+
static ExternGlobal() => Debug.Assert(Marshal.SizeOf(typeof(ExternMemory)) == 24);
62+
3763
public ulong store;
38-
public nuint __private;
64+
public uint __private1;
65+
public uint __private2;
66+
public uint __private3;
3967
}
4068

4169
internal enum ExternKind : byte
@@ -50,6 +78,8 @@ internal enum ExternKind : byte
5078
[StructLayout(LayoutKind.Explicit)]
5179
internal struct ExternUnion
5280
{
81+
static ExternUnion() => Debug.Assert(Marshal.SizeOf(typeof(ExternUnion)) == 24);
82+
5383
[FieldOffset(0)]
5484
public ExternFunc func;
5585

@@ -69,6 +99,8 @@ internal struct ExternUnion
6999
[StructLayout(LayoutKind.Sequential)]
70100
internal struct Extern : IDisposable
71101
{
102+
static Extern() => Debug.Assert(Marshal.SizeOf(typeof(Extern)) == 32);
103+
72104
public ExternKind kind;
73105
public ExternUnion of;
74106

src/Store.cs

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -339,52 +339,44 @@ private static class Native
339339
private object? data;
340340

341341
private static readonly Native.Finalizer Finalizer = (p) => GCHandle.FromIntPtr(p).Free();
342-
343-
private readonly ConcurrentDictionary<(ExternKind kind, ulong store, nuint __private), object> _externCache = new();
342+
343+
// The caches below use the external struct type as key type. These structs contain
344+
// __private fields, but these are not interpreted and merely used for value comparison.
345+
private readonly ConcurrentDictionary<ExternFunc, Function> _externFunctionCache = new();
346+
private readonly ConcurrentDictionary<ExternMemory, Memory> _externMemoryCache = new();
347+
private readonly ConcurrentDictionary<ExternGlobal, Global> _externGlobalCache = new();
344348

345349
internal Function GetCachedExtern(ExternFunc @extern)
346350
{
347-
// We use a `ValueTuple` as key, consisting of the extern type and the both
348-
// struct fields, which works since all `Extern...` structs have the same
349-
// fields.
350-
// Even though the second field is named "__private", it should be Ok to
351-
// access it since we won't interpret the value in any way, but just use it
352-
// to compare it to other values.
353-
var key = (ExternKind.Func, @extern.store, @extern.__private);
354-
355-
if (!_externCache.TryGetValue(key, out var func))
351+
if (!_externFunctionCache.TryGetValue(@extern, out var func))
356352
{
357353
func = new Function(this, @extern);
358-
func = _externCache.GetOrAdd(key, func);
354+
func = _externFunctionCache.GetOrAdd(@extern, func);
359355
}
360356

361-
return (Function)func;
357+
return func;
362358
}
363359

364360
internal Memory GetCachedExtern(ExternMemory @extern)
365361
{
366-
var key = (ExternKind.Memory, @extern.store, @extern.__private);
367-
368-
if (!_externCache.TryGetValue(key, out var mem))
362+
if (!_externMemoryCache.TryGetValue(@extern, out var mem))
369363
{
370364
mem = new Memory(this, @extern);
371-
mem = _externCache.GetOrAdd(key, mem);
365+
mem = _externMemoryCache.GetOrAdd(@extern, mem);
372366
}
373367

374-
return (Memory)mem;
368+
return mem;
375369
}
376370

377371
internal Global GetCachedExtern(ExternGlobal @extern)
378372
{
379-
var key = (ExternKind.Global, @extern.store, @extern.__private);
380-
381-
if (!_externCache.TryGetValue(key, out var global))
373+
if (!_externGlobalCache.TryGetValue(@extern, out var global))
382374
{
383375
global = new Global(this, @extern);
384-
global = _externCache.GetOrAdd(key, global);
376+
global = _externGlobalCache.GetOrAdd(@extern, global);
385377
}
386378

387-
return (Global)global;
379+
return global;
388380
}
389381
}
390382
}

src/TrapException.cs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,53 @@ public enum TrapCode
3737
Unreachable = 9,
3838
/// <summary>The trap was the result of interrupting execution.</summary>
3939
Interrupt = 10,
40+
/// <summary>
41+
/// The trap was the result of executing a function that was `canon lift`'d, then `canonlower`'d, then called.
42+
/// </summary>
43+
/// <remarks>
44+
/// When the component model feature is enabled this trap represents a function that was `canon lift`'d,
45+
/// then `canonlower`'d, then called. This combination of creation of a function in the component model
46+
/// generates a function that always traps and, when called, produces this flavor of trap.
47+
/// </remarks>
48+
AlwaysTrapAdapter = 11,
4049
/// <summary>The trap was the result of running out of the configured fuel amount.</summary>
41-
OutOfFuel = 11,
50+
OutOfFuel = 12,
51+
/// <summary>
52+
/// The trap was the result of atomic wait operations on non-shared memory.
53+
/// </summary>
54+
AtomicWaitNonSharedMemory = 13,
55+
/// <summary>
56+
/// The trap was the result of a call to a null reference.
57+
/// </summary>
58+
NullReference = 14,
59+
/// <summary>
60+
/// The trap was the result of an attempt to access beyond the bounds of an array.
61+
/// </summary>
62+
ArrayOutOfBounds = 15,
63+
/// <summary>
64+
/// The trap was the result of an allocation that was too large to succeed.
65+
/// </summary>
66+
AllocationTooLarge = 16,
67+
/// <summary>
68+
/// The trap was the result of an attempt to cast a reference to a type that it is not an instance of.
69+
/// </summary>
70+
CastFailure = 17,
71+
/// <summary>
72+
/// The trap was the result of a component calling another component that would have violated the reentrance rules.
73+
/// </summary>
74+
CannotEnterComponent = 18,
75+
/// <summary>
76+
/// The trap was the result of an async-lifted export failing to return a valid async result.
77+
/// </summary>
78+
/// <remarks>
79+
/// An async-lifted export failed to produce a result by calling `task.return` before returning `STATUS_DONE`
80+
/// and/or after all host tasks completed.
81+
/// </remarks>
82+
NoAsyncResult = 19,
83+
/// <summary>
84+
/// The trap was the result of a Pulley opcode executed at runtime when the opcode was disabled at compile time.
85+
/// </summary>
86+
DisabledOpCode = 20
4287
}
4388

4489
/// <summary>

0 commit comments

Comments
 (0)