Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,11 @@ jobs:
- name: Test WebAssembly spec (in Wasm3, self-hosting)
run: |
cd test
python3 run-spec-test.py --exec "../build/wasm3 --stack-size 2097152 wasm3.wasm --repl"
python3 run-spec-test.py --exec "../build/wasm3 --stack-size 8388608 wasm3.wasm --repl"
- name: Test WASI apps (in Wasm3, self-hosting)
run: |
cd test
python3 run-wasi-test.py --fast --exec "../build/wasm3 --stack-size 2097152 wasm3.wasm"
python3 run-wasi-test.py --fast --exec "../build/wasm3 --stack-size 8388608 wasm3.wasm"

ios:
runs-on: macos-latest
Expand Down Expand Up @@ -496,20 +496,26 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
if: "github.event_name == 'push'"
env:
PARTICLE_TOKEN: ${{ secrets.PARTICLE_TOKEN }}

steps:
- uses: actions/checkout@v7
- name: Set up Particle CLI
if: env.PARTICLE_TOKEN != ''
run: sudo npm install -g particle-cli
- name: Log in
env:
PARTICLE_TOKEN: ${{ secrets.PARTICLE_TOKEN }}
run: particle login --token $PARTICLE_TOKEN
if: env.PARTICLE_TOKEN != ''
run: particle login --token "$PARTICLE_TOKEN"
- name: Build Photon
if: env.PARTICLE_TOKEN != ''
run: |
cd platforms/embedded/particle
particle compile --followSymlinks photon
particle compile --followSymlinks argon
- name: Skip Particle build without credentials
if: env.PARTICLE_TOKEN == ''
run: echo "PARTICLE_TOKEN is not configured; skipping Particle cloud builds"

esp-idf:
runs-on: ubuntu-latest
Expand Down
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ set_property(CACHE BUILD_WASI PROPERTY STRINGS none simple uvwasi metawasi)

option(BUILD_NATIVE "Build with machine-specific optimisations" ON)
option(BUILD_FUEL_TEST "Build the fuel/resume regression test" OFF)
option(BUILD_SNAPSHOT "Build runtime snapshot support" ON)
option(BUILD_M3C "Build optional .m3c persistent metacode support" OFF)
option(BUILD_DYLINK "Build optional dylink.0 runtime linker support" OFF)

Expand Down Expand Up @@ -213,7 +214,7 @@ elseif(BUILD_WASI MATCHES "uvwasi")
FetchContent_Declare(
uvwasi
GIT_REPOSITORY https://github.com/vshymanskyy/uvwasi.git
GIT_TAG master
GIT_TAG 0820128569533c855d60c0f6382acbb14aa62ad2
)
FetchContent_MakeAvailable(libuv)
FetchContent_MakeAvailable(uvwasi)
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ Fuel accounting runs in one shared metacode dispatcher instead of being
inlined into every operation handler. This keeps the compiled interpreter
smaller without changing fuel, suspension, or resume semantics.

Fuel/resume support is compiled in by default. Flash-constrained ATmega1284P
builds default to `d_m3HasFuel=0`; define it explicitly to override that
platform default.

If wasm3 can capture the current continuation, the runtime becomes suspended and can later be resumed with `m3_Resume()`.

Use `m3_SetFuel()` to set a new fuel value.
Expand All @@ -217,6 +221,11 @@ Calling `m3_Call()` on a suspended runtime returns `m3Err_runtimeSuspended`.

## Runtime snapshots

Snapshot support is enabled by default, except on flash-constrained AVR targets.
Define `d_m3HasSnapshot` explicitly to override the platform default. CMake
builds can use `BUILD_SNAPSHOT=OFF` to compile the implementation out. The
public snapshot functions then return `m3Err_snapshotUnsupported`.

Snapshots can only be saved from suspended runtimes.

A snapshot stores enough runtime state to recreate the runtime later and continue execution from the same suspended point.
Expand Down
4 changes: 4 additions & 0 deletions platforms/embedded/arduino/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ src_build_flags =
platform = atmelavr
board = wildfirev3

build_flags =
-mcall-prologues
-Wl,--relax

src_build_flags =
-Dd_m3CodePageAlignSize=512
-Os -Wfatal-errors
Expand Down
4 changes: 4 additions & 0 deletions source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ target_include_directories(m3 PUBLIC .)

target_compile_features(m3 PRIVATE c_std_99)

if(DEFINED BUILD_SNAPSHOT AND NOT BUILD_SNAPSHOT)
target_compile_definitions(m3 PUBLIC d_m3HasSnapshot=0)
endif()

if(BUILD_M3C)
target_compile_definitions(m3 PUBLIC d_m3HasM3C=1)
endif()
Expand Down
21 changes: 21 additions & 0 deletions source/m3_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,27 @@
# define d_m3HasFloat 1 // implement floating point ops
# endif

// Fuel/resume is enabled by default. The ATmega1284P example is already at
// its flash limit, so it opts out unless the embedding project overrides it.
# ifndef d_m3HasFuel
# if defined(__AVR_ATmega1284P__)
# define d_m3HasFuel 0
# else
# define d_m3HasFuel 1
# endif
# endif

// Runtime snapshots are enabled by default. AVR builds default to disabled
// because the implementation does not fit on the supported flash-constrained
// boards; either default can be overridden by defining d_m3HasSnapshot.
# ifndef d_m3HasSnapshot
# if defined(__AVR__)
# define d_m3HasSnapshot 0
# else
# define d_m3HasSnapshot 1
# endif
# endif

// Optional persistent wasm3 metacode cache (.m3c). The implementation is
// completely compiled out unless explicitly enabled by the embedding project.
# ifndef d_m3HasM3C
Expand Down
97 changes: 94 additions & 3 deletions source/m3_env.c
Original file line number Diff line number Diff line change
Expand Up @@ -892,8 +892,7 @@ M3Result m3_FindFunctionInModule (IM3Function * o_function,
if (not i_module->runtime)
return m3Err_moduleNotLinked;

function = (IM3Function) v_FindFunction (i_module,
(void *) i_functionName);
function = (IM3Function) v_FindFunction (i_module, i_functionName);
#if d_m3HasDylink
function = m3d_ResolveFunction (function);
#endif
Expand Down Expand Up @@ -1022,6 +1021,8 @@ u8 * GetStackPointerForArgs (IM3Function i_function)



#if d_m3HasFuel

void m3_SetFuel (IM3Runtime runtime, uint64_t fuel)
{
if (runtime) { runtime->fuel = fuel; runtime->fuelEnabled = true; }
Expand Down Expand Up @@ -1104,6 +1105,51 @@ M3Result m3_Resume (IM3Runtime runtime)
return m3Err_none;
}

#else

void m3_SetFuel (IM3Runtime runtime, uint64_t fuel)
{
(void) runtime;
(void) fuel;
}

void m3_AddFuel (IM3Runtime runtime, uint64_t fuel)
{
(void) runtime;
(void) fuel;
}

void m3_DisableFuel (IM3Runtime runtime)
{
(void) runtime;
}

uint64_t m3_GetFuel (IM3Runtime runtime)
{
(void) runtime;
return 0;
}

uint32_t m3_IsFuelEnabled (IM3Runtime runtime)
{
(void) runtime;
return 0;
}

uint32_t m3_IsSuspended (IM3Runtime runtime)
{
(void) runtime;
return 0;
}

M3Result m3_Resume (IM3Runtime runtime)
{
(void) runtime;
return m3Err_runtimeSuspended;
}

#endif // d_m3HasFuel

M3Result m3_CallV (IM3Function i_function, ...)
{
va_list ap;
Expand Down Expand Up @@ -1131,7 +1177,9 @@ M3Result m3_CallVL (IM3Function i_function, va_list i_args)
M3Result result = m3Err_none;
u8* s = NULL;

#if d_m3HasFuel
if (runtime->suspended) return m3Err_runtimeSuspended;
#endif

if (!i_function->compiled) {
return m3Err_missingCompiledCode;
Expand Down Expand Up @@ -1167,7 +1215,9 @@ _ (checkStartFunction(i_function->module))
# endif
ReportNativeStackUsage ();

#if d_m3HasFuel
if (result == m3Err_fuelExhausted) runtime->suspendedFunction = i_function;
#endif
runtime->lastCalled = result ? NULL : i_function;

_catch: return result;
Expand All @@ -1180,7 +1230,9 @@ M3Result m3_Call (IM3Function i_function, uint32_t i_argc, const void * i_argp
M3Result result = m3Err_none;
u8* s = NULL;

#if d_m3HasFuel
if (runtime->suspended) return m3Err_runtimeSuspended;
#endif


if (i_argc != ftype->numArgs) {
Expand Down Expand Up @@ -1221,7 +1273,9 @@ _ (checkStartFunction(i_function->module))

ReportNativeStackUsage ();

#if d_m3HasFuel
if (result == m3Err_fuelExhausted) runtime->suspendedFunction = i_function;
#endif
runtime->lastCalled = result ? NULL : i_function;

_catch: return result;
Expand Down Expand Up @@ -1272,7 +1326,9 @@ _ (checkStartFunction(i_function->module))

ReportNativeStackUsage ();

#if d_m3HasFuel
if (result == m3Err_fuelExhausted) runtime->suspendedFunction = i_function;
#endif
runtime->lastCalled = result ? NULL : i_function;

_catch: return result;
Expand Down Expand Up @@ -1494,6 +1550,8 @@ M3BacktraceInfo * m3_GetBacktrace (IM3Runtime i_runtime)
}


#if d_m3HasSnapshot

// Snapshot v1 is a process-local, same-binary/same-module continuation format.
// It avoids serializing raw stack, memory, function, and code pointers: continuation PCs
// are encoded as function identities plus offsets; SP is a stack-slot offset; memory
Expand Down Expand Up @@ -1536,7 +1594,12 @@ static u32 SnapshotCountModules (IM3Runtime runtime)

static IM3Module SnapshotGetModule (IM3Runtime runtime, u32 index)
{
for (IM3Module m = runtime ? runtime->modules : NULL; m; m = m->next, index--) if (index == 0) return m; return NULL;
for (IM3Module m = runtime ? runtime->modules : NULL; m; m = m->next, index--)
{
if (index == 0)
return m;
}
return NULL;
}

static bool SnapshotFunctionIndex (IM3Function f, u32 * moduleIndex, u32 * functionIndex)
Expand Down Expand Up @@ -1695,3 +1758,31 @@ M3Result m3_LoadRuntimeSnapshot (IM3Runtime runtime, const uint8_t * buffer, uin
runtime->numContinuationFrames = h.frameCount; runtime->suspendedFunction = &sm->functions[h.suspendedFunctionIndex]; runtime->lastCalled = NULL;
return m3Err_none;
}

#else

M3Result m3_GetRuntimeSnapshotSize (IM3Runtime runtime, uint32_t * out_size)
{
(void) runtime;
(void) out_size;
return m3Err_snapshotUnsupported;
}

M3Result m3_SaveRuntimeSnapshot (IM3Runtime runtime, uint8_t * buffer, uint32_t buffer_size, uint32_t * out_size)
{
(void) runtime;
(void) buffer;
(void) buffer_size;
(void) out_size;
return m3Err_snapshotUnsupported;
}

M3Result m3_LoadRuntimeSnapshot (IM3Runtime runtime, const uint8_t * buffer, uint32_t buffer_size)
{
(void) runtime;
(void) buffer;
(void) buffer_size;
return m3Err_snapshotUnsupported;
}

#endif
Loading
Loading