refactor: Try to better align to wasm spec

mmap-opt
Sean McBride 4 years ago
parent 65c363d93d
commit d014641efd

@ -6,6 +6,7 @@
"includePath": [
"/usr/include/",
"${workspaceFolder}/runtime/include/",
"${workspaceFolder}/runtime/include/common",
"${workspaceFolder}/runtime/thirdparty/ck/include/",
"${workspaceFolder}/runtime/thirdparty/http-parser/",
"${workspaceFolder}/runtime/thirdparty/jsmn/"

@ -100,12 +100,12 @@
"sandbox_set_as_running_user.h": "c",
"scheduler.h": "c",
"sandbox_set_as_returned.h": "c",
"wasm_linear_memory.h": "c",
"wasm_memory.h": "c",
"software_interrupt_counts.h": "c",
"sandbox_set_as_running_sys.h": "c",
"compiletime.h": "c",
"sandbox_context_cache.h": "c",
"wasm_indirect_table.h": "c"
"wasm_store.h": "c",
"wasm_table.h": "c"
},
"files.exclude": {
"**/.git": true,

@ -0,0 +1,6 @@
A WebAssembly module instance is statically linked with the backing functions implementing the wasm32 ABI, yielding a *.so file that SLEdge can execute. This ensures that the instance is able to aggressively inline and optimize this code.
They are broken into instruction types as on https://webassembly.github.io/spec/core/exec/instructions.html. They depend on common headers for the WebAssembly types located in the WebAssembly instance struct. These are located in runtime/include/common.
The stubs correspond to awsm/src/codegen/runtime_stubs.rs

@ -1,373 +0,0 @@
#include <assert.h>
#include <assert.h>
#include <math.h>
#include "types.h"
#include "sandbox_context_cache.h"
/* This file contains the stub functions that the aWsm compiler expects
* This corresponds to awsm/src/codegen/runtime_stubs.rs
* This should be linked with the *.bc file generated by aWsm in order to compile a module as a *.so
*/
extern thread_local struct sandbox_context_cache local_sandbox_context_cache;
EXPORT void
initialize_region(uint32_t offset, uint32_t region_size, uint8_t region[region_size])
{
wasm_linear_memory_initialize_region(local_sandbox_context_cache.memory, offset, region_size, region);
}
EXPORT uint32_t
instruction_memory_size()
{
return wasm_linear_memory_get_page_count(local_sandbox_context_cache.memory);
}
/**
* @brief Stub that implements the WebAssembly memory.grow instruction
*
* @param count number of pages to grow the WebAssembly linear memory by
* @return The previous size of the linear memory in pages or -1 if enough memory cannot be allocated
*/
EXPORT int32_t
instruction_memory_grow(uint32_t count)
{
int rc = local_sandbox_context_cache.memory->size / WASM_PAGE_SIZE;
/* Return -1 if we've hit the linear memory max */
if (unlikely(wasm_linear_memory_expand(local_sandbox_context_cache.memory, WASM_PAGE_SIZE * count) == -1))
return -1;
#ifdef LOG_SANDBOX_MEMORY_PROFILE
// Cache the runtime of the first N page allocations
for (int i = 0; i < count; i++) {
if (likely(sandbox->timestamp_of.page_allocations_size < SANDBOX_PAGE_ALLOCATION_TIMESTAMP_COUNT)) {
sandbox->timestamp_of.page_allocations[sandbox->timestamp_of.page_allocations_size++] =
sandbox->duration_of_state.running
+ (uint32_t)(__getcycles() - sandbox->timestamp_of.last_state_change);
}
}
#endif
return rc;
}
EXPORT float
get_f32(uint32_t offset)
{
return wasm_linear_memory_get_float(local_sandbox_context_cache.memory, offset);
}
EXPORT void
set_f32(uint32_t offset, float v)
{
wasm_linear_memory_set_float(local_sandbox_context_cache.memory, offset, v);
}
EXPORT double
get_f64(uint32_t offset)
{
return wasm_linear_memory_get_double(local_sandbox_context_cache.memory, offset);
}
EXPORT void
set_f64(uint32_t offset, double v)
{
wasm_linear_memory_set_double(local_sandbox_context_cache.memory, offset, v);
}
EXPORT int8_t
get_i8(uint32_t offset)
{
return wasm_linear_memory_get_int8(local_sandbox_context_cache.memory, offset);
}
EXPORT void
set_i8(uint32_t offset, int8_t v)
{
wasm_linear_memory_set_int8(local_sandbox_context_cache.memory, offset, v);
}
EXPORT int16_t
get_i16(uint32_t offset)
{
return wasm_linear_memory_get_int16(local_sandbox_context_cache.memory, offset);
}
EXPORT void
set_i16(uint32_t offset, int16_t v)
{
wasm_linear_memory_set_int16(local_sandbox_context_cache.memory, offset, v);
}
EXPORT int32_t
get_i32(uint32_t offset)
{
return wasm_linear_memory_get_int32(local_sandbox_context_cache.memory, offset);
}
EXPORT void
set_i32(uint32_t offset, int32_t v)
{
wasm_linear_memory_set_int32(local_sandbox_context_cache.memory, offset, v);
}
EXPORT int64_t
get_i64(uint32_t offset)
{
return wasm_linear_memory_get_int64(local_sandbox_context_cache.memory, offset);
}
EXPORT void
set_i64(uint32_t offset, int64_t v)
{
wasm_linear_memory_set_int64(local_sandbox_context_cache.memory, offset, v);
}
EXPORT void
add_function_to_table(uint32_t idx, uint32_t type_id, char *pointer)
{
wasm_indirect_table_set(local_sandbox_context_cache.module_indirect_table, idx, type_id, pointer);
}
/* char * is used as a generic pointer to a function pointer */
EXPORT char *
get_function_from_table(uint32_t idx, uint32_t type_id)
{
return wasm_indirect_table_get(local_sandbox_context_cache.module_indirect_table, idx, type_id);
}
EXPORT int32_t
get_global_i32(uint32_t offset)
{
return get_i32(offset);
}
EXPORT void
set_global_i32(uint32_t offset, int32_t v)
{
set_i32(offset, v);
}
EXPORT int64_t
get_global_i64(uint32_t offset)
{
return get_i64(offset);
}
EXPORT void
set_global_i64(uint32_t offset, int64_t v)
{
set_i64(offset, v);
}
#define CHAR_BIT 8
// TODO: Throughout here we use `assert` for error conditions, which isn't optimal
// Instead we should use `unlikely` branches to a single trapping function (which should optimize better)
// The below functions are for implementing WASM instructions
// ROTL and ROTR helper functions
INLINE uint32_t
rotl_u32(uint32_t n, uint32_t c_u32)
{
// WASM requires a modulus here (usually a single bitwise op, but it means we need no assert)
unsigned int c = c_u32 % (CHAR_BIT * sizeof(n));
const unsigned int mask = (CHAR_BIT * sizeof(n) - 1); // assumes width is a power of 2.
c &= mask;
return (n << c) | (n >> ((-c) & mask));
}
INLINE uint32_t
rotr_u32(uint32_t n, uint32_t c_u32)
{
// WASM requires a modulus here (usually a single bitwise op, but it means we need no assert)
unsigned int c = c_u32 % (CHAR_BIT * sizeof(n));
const unsigned int mask = (CHAR_BIT * sizeof(n) - 1);
c &= mask;
return (n >> c) | (n << ((-c) & mask));
}
INLINE uint64_t
rotl_u64(uint64_t n, uint64_t c_u64)
{
// WASM requires a modulus here (usually a single bitwise op, but it means we need no assert)
unsigned int c = c_u64 % (CHAR_BIT * sizeof(n));
const unsigned int mask = (CHAR_BIT * sizeof(n) - 1); // assumes width is a power of 2.
c &= mask;
return (n << c) | (n >> ((-c) & mask));
}
INLINE uint64_t
rotr_u64(uint64_t n, uint64_t c_u64)
{
// WASM requires a modulus here (usually a single bitwise op, but it means we need no assert)
unsigned int c = c_u64 % (CHAR_BIT * sizeof(n));
const unsigned int mask = (CHAR_BIT * sizeof(n) - 1);
c &= mask;
return (n >> c) | (n << ((-c) & mask));
}
// Now safe division and remainder
INLINE uint32_t
u32_div(uint32_t a, uint32_t b)
{
assert(b);
return a / b;
}
INLINE uint32_t
u32_rem(uint32_t a, uint32_t b)
{
assert(b);
return a % b;
}
INLINE int32_t
i32_div(int32_t a, int32_t b)
{
assert(b && (a != INT32_MIN || b != -1));
return a / b;
}
INLINE int32_t
i32_rem(int32_t a, int32_t b)
{
assert(b && (a != INT32_MIN || b != -1));
return a % b;
}
INLINE uint64_t
u64_div(uint64_t a, uint64_t b)
{
assert(b);
return a / b;
}
INLINE uint64_t
u64_rem(uint64_t a, uint64_t b)
{
assert(b);
return a % b;
}
INLINE int64_t
i64_div(int64_t a, int64_t b)
{
assert(b && (a != INT64_MIN || b != -1));
return a / b;
}
INLINE int64_t
i64_rem(int64_t a, int64_t b)
{
assert(b && (a != INT64_MIN || b != -1));
return a % b;
}
// float to integer conversion methods
// In C, float => int conversions always truncate
// If a int2float(int::min_value) <= float <= int2float(int::max_value), it must always be safe to truncate it
uint32_t
u32_trunc_f32(float f)
{
assert(0 <= f && f <= (float)UINT32_MAX);
return (uint32_t)f;
}
int32_t
i32_trunc_f32(float f)
{
assert(INT32_MIN <= f && f <= (float)INT32_MAX);
return (int32_t)f;
}
uint32_t
u32_trunc_f64(double f)
{
assert(0 <= f && f <= (double)UINT32_MAX);
return (uint32_t)f;
}
int32_t
i32_trunc_f64(double f)
{
assert(INT32_MIN <= f && f <= (double)INT32_MAX);
return (int32_t)f;
}
uint64_t
u64_trunc_f32(float f)
{
assert(0 <= f && f <= (float)UINT64_MAX);
return (uint64_t)f;
}
int64_t
i64_trunc_f32(float f)
{
assert(INT64_MIN <= f && f <= (float)INT64_MAX);
return (int64_t)f;
}
uint64_t
u64_trunc_f64(double f)
{
assert(0 <= f && f <= (double)UINT64_MAX);
return (uint64_t)f;
}
int64_t
i64_trunc_f64(double f)
{
assert(INT64_MIN <= f && f <= (double)INT64_MAX);
return (int64_t)f;
}
// Float => Float truncation functions
INLINE float
f32_trunc_f32(float f)
{
return trunc(f);
}
INLINE float
f32_min(float a, float b)
{
return a < b ? a : b;
}
INLINE float
f32_max(float a, float b)
{
return a > b ? a : b;
}
INLINE float
f32_floor(float a)
{
return floor(a);
}
INLINE double
f64_min(double a, double b)
{
return a < b ? a : b;
}
INLINE double
f64_max(double a, double b)
{
return a > b ? a : b;
}
INLINE double
f64_floor(double a)
{
return floor(a);
}

@ -0,0 +1,144 @@
#include <assert.h>
#include <assert.h>
#include <math.h>
#include "wasm_store.h"
extern thread_local struct wasm_module_instance current_wasm_module_instance;
INLINE void
initialize_region(uint32_t offset, uint32_t region_size, uint8_t region[region_size])
{
wasm_memory_initialize_region(current_wasm_module_instance.memory, offset, region_size, region);
}
INLINE uint32_t
instruction_memory_size()
{
return wasm_memory_get_page_count(current_wasm_module_instance.memory);
}
/**
* @brief Stub that implements the WebAssembly memory.grow instruction
*
* @param count number of pages to grow the WebAssembly linear memory by
* @return The previous size of the linear memory in pages or -1 if enough memory cannot be allocated
*/
INLINE int32_t
instruction_memory_grow(uint32_t count)
{
int old_page_count = current_wasm_module_instance.memory->size / WASM_PAGE_SIZE;
/* Return -1 if we've hit the linear memory max */
int rc = wasm_memory_expand(current_wasm_module_instance.memory, WASM_PAGE_SIZE * count);
if (unlikely(rc == -1)) return -1;
#ifdef LOG_SANDBOX_MEMORY_PROFILE
// Cache the runtime of the first N page allocations
for (int i = 0; i < count; i++) {
if (likely(sandbox->timestamp_of.page_allocations_size < SANDBOX_PAGE_ALLOCATION_TIMESTAMP_COUNT)) {
sandbox->timestamp_of.page_allocations[sandbox->timestamp_of.page_allocations_size++] =
sandbox->duration_of_state.running
+ (uint32_t)(__getcycles() - sandbox->timestamp_of.last_state_change);
}
}
#endif
return rc;
}
INLINE float
get_f32(uint32_t offset)
{
return wasm_memory_get_float(current_wasm_module_instance.memory, offset);
}
INLINE void
set_f32(uint32_t offset, float v)
{
wasm_memory_set_float(current_wasm_module_instance.memory, offset, v);
}
INLINE double
get_f64(uint32_t offset)
{
return wasm_memory_get_double(current_wasm_module_instance.memory, offset);
}
INLINE void
set_f64(uint32_t offset, double v)
{
wasm_memory_set_double(current_wasm_module_instance.memory, offset, v);
}
INLINE int8_t
get_i8(uint32_t offset)
{
return wasm_memory_get_int8(current_wasm_module_instance.memory, offset);
}
INLINE void
set_i8(uint32_t offset, int8_t v)
{
wasm_memory_set_int8(current_wasm_module_instance.memory, offset, v);
}
INLINE int16_t
get_i16(uint32_t offset)
{
return wasm_memory_get_int16(current_wasm_module_instance.memory, offset);
}
INLINE void
set_i16(uint32_t offset, int16_t v)
{
wasm_memory_set_int16(current_wasm_module_instance.memory, offset, v);
}
INLINE int32_t
get_i32(uint32_t offset)
{
return wasm_memory_get_int32(current_wasm_module_instance.memory, offset);
}
INLINE void
set_i32(uint32_t offset, int32_t v)
{
wasm_memory_set_int32(current_wasm_module_instance.memory, offset, v);
}
INLINE int64_t
get_i64(uint32_t offset)
{
return wasm_memory_get_int64(current_wasm_module_instance.memory, offset);
}
INLINE void
set_i64(uint32_t offset, int64_t v)
{
wasm_memory_set_int64(current_wasm_module_instance.memory, offset, v);
}
INLINE int32_t
get_global_i32(uint32_t offset)
{
return get_i32(offset);
}
INLINE void
set_global_i32(uint32_t offset, int32_t v)
{
set_i32(offset, v);
}
INLINE int64_t
get_global_i64(uint32_t offset)
{
return get_i64(offset);
}
INLINE void
set_global_i64(uint32_t offset, int64_t v)
{
set_i64(offset, v);
}

@ -0,0 +1,23 @@
#include "types.h"
#include "wasm_store.h"
/* This file contains the stub functions that the aWsm compiler expects
* This corresponds to awsm/src/codegen/runtime_stubs.rs
* This should be linked with the *.bc file generated by aWsm in order to compile a module as a *.so
*/
extern thread_local struct wasm_module_instance current_wasm_module_instance;
INLINE void
add_function_to_table(uint32_t idx, uint32_t type_id, char *pointer)
{
wasm_table_set(current_wasm_module_instance.table, idx, type_id, pointer);
}
/* char * is used as a generic pointer to a function pointer */
INLINE char *
get_function_from_table(uint32_t idx, uint32_t type_id)
{
return wasm_table_get(current_wasm_module_instance.table, idx, type_id);
}

@ -3,24 +3,8 @@
#include <assert.h>
#include <dlfcn.h>
#include "wasm_types.h"
/* Wasm initialization functions generated by the compiler */
#define AWSM_ABI_INITIALIZE_GLOBALS "populate_globals"
#define AWSM_ABI_INITIALIZE_MEMORY "populate_memory"
#define AWSM_ABI_INITIALIZE_TABLE "populate_table"
#define AWSM_ABI_INITIALIZE_LIBC "wasmf___init_libc"
#define AWSM_ABI_ENTRYPOINT "wasmf_main"
#define AWSM_ABI_STARTING_PAGES "starting_pages"
#define AWSM_ABI_MAX_PAGES "max_pages"
/* functions in the module to lookup and call per sandbox. */
typedef int32_t (*awsm_abi_entrypoint_fn_t)(int32_t a, int32_t b);
typedef void (*awsm_abi_init_globals_fn_t)(void);
typedef void (*awsm_abi_init_mem_fn_t)(void);
typedef void (*awsm_abi_init_tbl_fn_t)(void);
typedef void (*awsm_abi_init_libc_fn_t)(int32_t, int32_t);
#include "common/wasm_types.h"
#include "debuglog.h"
struct awsm_abi {
void * handle;

@ -0,0 +1,3 @@
This folder includes headers used by the compiletime and runtime components.
Changes in here break our ABI and require *.so module to be recompiled.

@ -7,21 +7,20 @@
#include <string.h>
#include <sys/mman.h>
#include "debuglog.h"
#include "types.h" /* PAGE_SIZE */
#include "wasm_types.h"
#define WASM_LINEAR_MEMORY_MAX (size_t) UINT32_MAX + 1
#define wasm_memory_MAX (size_t) UINT32_MAX + 1
struct wasm_linear_memory {
struct wasm_memory {
size_t size; /* Initial Size in bytes */
size_t capacity; /* Size backed by actual pages */
size_t max; /* Soft cap in bytes. Defaults to 4GB */
uint8_t data[];
};
static inline struct wasm_linear_memory *
wasm_linear_memory_allocate(size_t initial, size_t max)
static inline struct wasm_memory *
wasm_memory_allocate(size_t initial, size_t max)
{
assert(initial > 0);
assert(initial <= (size_t)UINT32_MAX + 1);
@ -29,21 +28,21 @@ wasm_linear_memory_allocate(size_t initial, size_t max)
assert(max <= (size_t)UINT32_MAX + 1);
/* Allocate contiguous virtual addresses for struct, full linear memory, and guard page */
size_t size_to_alloc = sizeof(struct wasm_linear_memory) + WASM_LINEAR_MEMORY_MAX + /* guard page */ PAGE_SIZE;
size_t size_to_alloc = sizeof(struct wasm_memory) + wasm_memory_MAX + /* guard page */ PAGE_SIZE;
void * temp = mmap(NULL, size_to_alloc, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (temp == MAP_FAILED) {
debuglog("wasm_linear_memory_allocate - allocation failed, (size: %lu) %s\n", size_to_alloc,
strerror(errno));
fprintf(stderr, "wasm_memory_allocate - allocation failed, (size: %lu) %s\n", size_to_alloc,
strerror(errno));
return NULL;
}
struct wasm_linear_memory *self = (struct wasm_linear_memory *)temp;
struct wasm_memory *self = (struct wasm_memory *)temp;
/* Set the struct and initial pages to read / write */
size_t size_to_read_write = sizeof(struct wasm_linear_memory) + initial;
size_t size_to_read_write = sizeof(struct wasm_memory) + initial;
int rc = mprotect(self, size_to_read_write, PROT_READ | PROT_WRITE);
if (rc != 0) {
perror("wasm_linear_memory_allocate - prot r/w failed");
perror("wasm_memory_allocate - prot r/w failed");
munmap(self, size_to_alloc);
assert(0);
return NULL;
@ -56,31 +55,31 @@ wasm_linear_memory_allocate(size_t initial, size_t max)
}
static inline void
wasm_linear_memory_free(struct wasm_linear_memory *self)
wasm_memory_free(struct wasm_memory *self)
{
size_t size_to_free = sizeof(struct wasm_linear_memory) + self->max + /* guard page */ PAGE_SIZE;
size_t size_to_free = sizeof(struct wasm_memory) + self->max + /* guard page */ PAGE_SIZE;
munmap(self, size_to_free);
}
static inline void
wasm_linear_memory_wipe(struct wasm_linear_memory *self)
wasm_memory_wipe(struct wasm_memory *self)
{
memset(self->data, 0, self->size);
}
static inline int
wasm_linear_memory_expand(struct wasm_linear_memory *self, size_t size_to_expand)
wasm_memory_expand(struct wasm_memory *self, size_t size_to_expand)
{
size_t target_size = self->size + size_to_expand;
if (unlikely(target_size > self->max)) {
fprintf(stderr, "wasm_linear_memory_expand - Out of Memory!. %lu out of %lu\n", self->size, self->max);
fprintf(stderr, "wasm_memory_expand - Out of Memory!. %lu out of %lu\n", self->size, self->max);
return -1;
}
if (target_size > self->capacity) {
int rc = mprotect(self, sizeof(struct wasm_linear_memory) + target_size, PROT_READ | PROT_WRITE);
int rc = mprotect(self, sizeof(struct wasm_memory) + target_size, PROT_READ | PROT_WRITE);
if (rc != 0) {
perror("wasm_linear_memory_expand mprotect");
perror("wasm_memory_expand mprotect");
return -1;
}
@ -98,7 +97,7 @@ wasm_linear_memory_expand(struct wasm_linear_memory *self, size_t size_to_expand
* @return void pointer to something in WebAssembly linear memory
*/
static inline void *
wasm_linear_memory_get_ptr_void(struct wasm_linear_memory *self, uint32_t offset, uint32_t size)
wasm_memory_get_ptr_void(struct wasm_memory *self, uint32_t offset, uint32_t size)
{
assert(offset + size <= self->size);
return (void *)&self->data[offset];
@ -110,7 +109,7 @@ wasm_linear_memory_get_ptr_void(struct wasm_linear_memory *self, uint32_t offset
* @return char at the offset
*/
static inline char
wasm_linear_memory_get_char(struct wasm_linear_memory *self, uint32_t offset)
wasm_memory_get_char(struct wasm_memory *self, uint32_t offset)
{
assert(offset + sizeof(char) <= self->size);
return (char)self->data[offset];
@ -122,7 +121,7 @@ wasm_linear_memory_get_char(struct wasm_linear_memory *self, uint32_t offset)
* @return float at the offset
*/
static inline float
wasm_linear_memory_get_float(struct wasm_linear_memory *self, uint32_t offset)
wasm_memory_get_float(struct wasm_memory *self, uint32_t offset)
{
assert(offset + sizeof(float) <= self->size);
return *(float *)&self->data[offset];
@ -134,7 +133,7 @@ wasm_linear_memory_get_float(struct wasm_linear_memory *self, uint32_t offset)
* @return double at the offset
*/
static inline double
wasm_linear_memory_get_double(struct wasm_linear_memory *self, uint32_t offset)
wasm_memory_get_double(struct wasm_memory *self, uint32_t offset)
{
assert(offset + sizeof(double) <= self->size);
return *(double *)&self->data[offset];
@ -146,7 +145,7 @@ wasm_linear_memory_get_double(struct wasm_linear_memory *self, uint32_t offset)
* @return int8_t at the offset
*/
static inline int8_t
wasm_linear_memory_get_int8(struct wasm_linear_memory *self, uint32_t offset)
wasm_memory_get_int8(struct wasm_memory *self, uint32_t offset)
{
assert(offset + sizeof(int8_t) <= self->size);
return (int8_t)self->data[offset];
@ -158,7 +157,7 @@ wasm_linear_memory_get_int8(struct wasm_linear_memory *self, uint32_t offset)
* @return int16_t at the offset
*/
static inline int16_t
wasm_linear_memory_get_int16(struct wasm_linear_memory *self, uint32_t offset)
wasm_memory_get_int16(struct wasm_memory *self, uint32_t offset)
{
assert(offset + sizeof(int16_t) <= self->size);
return *(int16_t *)&self->data[offset];
@ -170,7 +169,7 @@ wasm_linear_memory_get_int16(struct wasm_linear_memory *self, uint32_t offset)
* @return int32_t at the offset
*/
static inline int32_t
wasm_linear_memory_get_int32(struct wasm_linear_memory *self, uint32_t offset)
wasm_memory_get_int32(struct wasm_memory *self, uint32_t offset)
{
assert(offset + sizeof(int32_t) <= self->size);
return *(int32_t *)&self->data[offset];
@ -182,14 +181,14 @@ wasm_linear_memory_get_int32(struct wasm_linear_memory *self, uint32_t offset)
* @return int32_t at the offset
*/
static inline int64_t
wasm_linear_memory_get_int64(struct wasm_linear_memory *self, uint32_t offset)
wasm_memory_get_int64(struct wasm_memory *self, uint32_t offset)
{
assert(offset + sizeof(int64_t) <= self->size);
return *(int64_t *)&self->data[offset];
}
static inline uint32_t
wasm_linear_memory_get_page_count(struct wasm_linear_memory *self)
wasm_memory_get_page_count(struct wasm_memory *self)
{
return (uint32_t)(self->size / WASM_PAGE_SIZE);
}
@ -201,7 +200,7 @@ wasm_linear_memory_get_page_count(struct wasm_linear_memory *self)
* @return pointer to the string or NULL if max_length is reached without finding null-terminator
*/
static inline char *
wasm_linear_memory_get_string(struct wasm_linear_memory *self, uint32_t offset, uint32_t size)
wasm_memory_get_string(struct wasm_memory *self, uint32_t offset, uint32_t size)
{
assert(offset + (sizeof(char) * size) <= self->size);
@ -217,7 +216,7 @@ wasm_linear_memory_get_string(struct wasm_linear_memory *self, uint32_t offset,
* @return double at the offset
*/
static inline void
wasm_linear_memory_set_double(struct wasm_linear_memory *self, uint32_t offset, double value)
wasm_memory_set_double(struct wasm_memory *self, uint32_t offset, double value)
{
assert(offset + sizeof(double) <= self->size);
*(double *)&self->data[offset] = value;
@ -229,7 +228,7 @@ wasm_linear_memory_set_double(struct wasm_linear_memory *self, uint32_t offset,
* @return float at the offset
*/
static inline void
wasm_linear_memory_set_float(struct wasm_linear_memory *self, uint32_t offset, float value)
wasm_memory_set_float(struct wasm_memory *self, uint32_t offset, float value)
{
assert(offset + sizeof(float) <= self->size);
*(float *)&self->data[offset] = value;
@ -241,7 +240,7 @@ wasm_linear_memory_set_float(struct wasm_linear_memory *self, uint32_t offset, f
* @return int8_t at the offset
*/
static inline void
wasm_linear_memory_set_int8(struct wasm_linear_memory *self, uint32_t offset, int8_t value)
wasm_memory_set_int8(struct wasm_memory *self, uint32_t offset, int8_t value)
{
assert(offset + sizeof(int8_t) <= self->size);
self->data[offset] = value;
@ -253,7 +252,7 @@ wasm_linear_memory_set_int8(struct wasm_linear_memory *self, uint32_t offset, in
* @return int16_t at the offset
*/
static inline void
wasm_linear_memory_set_int16(struct wasm_linear_memory *self, uint32_t offset, int16_t value)
wasm_memory_set_int16(struct wasm_memory *self, uint32_t offset, int16_t value)
{
assert(offset + sizeof(int16_t) <= self->size);
*(int16_t *)&self->data[offset] = value;
@ -265,7 +264,7 @@ wasm_linear_memory_set_int16(struct wasm_linear_memory *self, uint32_t offset, i
* @return int32_t at the offset
*/
static inline void
wasm_linear_memory_set_int32(struct wasm_linear_memory *self, uint32_t offset, int32_t value)
wasm_memory_set_int32(struct wasm_memory *self, uint32_t offset, int32_t value)
{
assert(offset + sizeof(int32_t) <= self->size);
*(int32_t *)&self->data[offset] = value;
@ -277,27 +276,27 @@ wasm_linear_memory_set_int32(struct wasm_linear_memory *self, uint32_t offset, i
* @return int64_t at the offset
*/
static inline void
wasm_linear_memory_set_int64(struct wasm_linear_memory *self, uint64_t offset, int64_t value)
wasm_memory_set_int64(struct wasm_memory *self, uint64_t offset, int64_t value)
{
assert(offset + sizeof(int64_t) <= self->size);
*(int32_t *)&self->data[offset] = value;
}
static inline void
wasm_linear_memory_set_size(struct wasm_linear_memory *self, size_t size)
wasm_memory_set_size(struct wasm_memory *self, size_t size)
{
self->size = size;
}
static inline size_t
wasm_linear_memory_get_size(struct wasm_linear_memory *self)
wasm_memory_get_size(struct wasm_memory *self)
{
return self->size;
}
static inline void
wasm_linear_memory_initialize_region(struct wasm_linear_memory *self, uint32_t offset, uint32_t region_size,
uint8_t region[region_size])
wasm_memory_initialize_region(struct wasm_memory *self, uint32_t offset, uint32_t region_size,
uint8_t region[region_size])
{
assert((size_t)offset + region_size <= self->size);
memcpy(&self->data[offset], region, region_size);

@ -0,0 +1,14 @@
#pragma once
#include "wasm_memory.h"
#include "wasm_table.h"
/* This structure is the runtime representation of the unique state of a module instance
* Currently this is not spec-compliant, as it only supports a single table and a single memory and it excludes many
* entities https://webassembly.github.io/spec/core/exec/runtime.html#module-instances
*/
struct wasm_module_instance {
struct wasm_memory *memory;
struct wasm_table * table;
};
extern thread_local struct wasm_module_instance current_wasm_module_instance;

@ -0,0 +1,65 @@
#pragma once
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
/* memory also provides the table access functions */
#define INDIRECT_TABLE_SIZE (1 << 10)
struct wasm_table_entry {
uint32_t type_id;
void * func_pointer;
};
struct wasm_table {
uint32_t length;
uint32_t capacity;
struct wasm_table_entry data[];
};
static inline struct wasm_table *
wasm_table_allocate(size_t capacity)
{
struct wasm_table *self = (struct wasm_table *)malloc(sizeof(struct wasm_table)
+ capacity * sizeof(struct wasm_table_entry));
self->capacity = capacity;
self->length = 0;
return self;
}
static inline void
wasm_table_free(struct wasm_table *self)
{
assert(self != NULL);
free(self);
}
static inline char *
wasm_table_get(struct wasm_table *self, uint32_t idx, uint32_t type_id)
{
assert(self != NULL);
assert(idx < self->capacity);
struct wasm_table_entry f = self->data[idx];
// FIXME: Commented out function type check because of gocr
// assert(f.type_id == type_id);
assert(f.func_pointer != NULL);
return f.func_pointer;
}
static inline void
wasm_table_set(struct wasm_table *self, uint32_t idx, uint32_t type_id, char *pointer)
{
assert(self != NULL);
assert(idx < self->capacity);
/* TODO: atomic for multiple concurrent invocations? Issue #97 */
if (self->data[idx].type_id == type_id && self->data[idx].func_pointer == pointer) return;
self->data[idx] = (struct wasm_table_entry){ .type_id = type_id, .func_pointer = pointer };
}

@ -0,0 +1,22 @@
#pragma once
#define WASM_PAGE_SIZE (1024 * 64) /* 64KB */
#define WASM_MEMORY_PAGES_MAX (1 << 16) /* 32,768 Pages ~4GB */
#define WASM_STACK_SIZE (1 << 19) /* 512KB */
/* Wasm initialization functions generated by the compiler */
#define AWSM_ABI_INITIALIZE_GLOBALS "populate_globals"
#define AWSM_ABI_INITIALIZE_MEMORY "populate_memory"
#define AWSM_ABI_INITIALIZE_TABLE "populate_table"
#define AWSM_ABI_INITIALIZE_LIBC "wasmf___init_libc"
#define AWSM_ABI_ENTRYPOINT "wasmf_main"
#define AWSM_ABI_STARTING_PAGES "starting_pages"
#define AWSM_ABI_MAX_PAGES "max_pages"
/* functions in the module to lookup and call per sandbox. */
typedef int32_t (*awsm_abi_entrypoint_fn_t)(int32_t a, int32_t b);
typedef void (*awsm_abi_init_globals_fn_t)(void);
typedef void (*awsm_abi_init_mem_fn_t)(void);
typedef void (*awsm_abi_init_tbl_fn_t)(void);
typedef void (*awsm_abi_init_libc_fn_t)(int32_t, int32_t);

@ -3,7 +3,7 @@
#include <threads.h>
#include "sandbox_types.h"
#include "sandbox_context_cache.h"
#include "common/wasm_store.h"
/* current sandbox that is active.. */
extern thread_local struct sandbox *worker_thread_current_sandbox;
@ -29,16 +29,16 @@ current_sandbox_set(struct sandbox *sandbox)
{
/* Unpack hierarchy to avoid pointer chasing */
if (sandbox == NULL) {
local_sandbox_context_cache = (struct sandbox_context_cache){
.memory = NULL,
.module_indirect_table = NULL,
current_wasm_module_instance = (struct wasm_module_instance){
.memory = NULL,
.table = NULL,
};
worker_thread_current_sandbox = NULL;
runtime_worker_threads_deadline[worker_thread_idx] = UINT64_MAX;
} else {
local_sandbox_context_cache = (struct sandbox_context_cache){
.memory = sandbox->memory,
.module_indirect_table = sandbox->module->indirect_table,
current_wasm_module_instance = (struct wasm_module_instance){
.memory = sandbox->memory,
.table = sandbox->module->indirect_table,
};
worker_thread_current_sandbox = sandbox;
runtime_worker_threads_deadline[worker_thread_idx] = sandbox->absolute_deadline;
@ -50,19 +50,19 @@ extern void current_sandbox_sleep();
static inline void *
current_sandbox_get_ptr_void(uint32_t offset, uint32_t bounds_check)
{
assert(local_sandbox_context_cache.memory != NULL);
return wasm_linear_memory_get_ptr_void(local_sandbox_context_cache.memory, offset, bounds_check);
assert(current_wasm_module_instance.memory != NULL);
return wasm_memory_get_ptr_void(current_wasm_module_instance.memory, offset, bounds_check);
}
static inline char
current_sandbox_get_char(uint32_t offset)
{
assert(local_sandbox_context_cache.memory != NULL);
return wasm_linear_memory_get_char(local_sandbox_context_cache.memory, offset);
assert(current_wasm_module_instance.memory != NULL);
return wasm_memory_get_char(current_wasm_module_instance.memory, offset);
}
static inline char *
current_sandbox_get_string(uint32_t offset, uint32_t size)
{
return wasm_linear_memory_get_string(local_sandbox_context_cache.memory, offset, size);
return wasm_memory_get_string(current_wasm_module_instance.memory, offset, size);
}

@ -11,8 +11,9 @@
#include "http.h"
#include "panic.h"
#include "pool.h"
#include "types.h"
#include "wasm_indirect_table.h"
#include "common/types.h"
#include "common/wasm_table.h"
#define MODULE_DEFAULT_REQUEST_RESPONSE_SIZE (PAGE_SIZE)
@ -55,9 +56,9 @@ struct module {
/* Handle and ABI Symbols for *.so file */
struct awsm_abi abi;
_Atomic uint32_t reference_count; /* ref count how many instances exist here. */
struct wasm_indirect_table *indirect_table;
struct pool ** linear_memory_pool;
_Atomic uint32_t reference_count; /* ref count how many instances exist here. */
struct wasm_table *indirect_table;
struct pool ** linear_memory_pool;
};
/*************************

@ -5,9 +5,8 @@
#include <stdatomic.h>
#include <stdbool.h>
#include "wasm_linear_memory.h"
#include "likely.h"
#include "types.h"
#include "common/types.h"
/**
* Optimizing compilers and modern CPUs reorder instructions however it sees fit. This means that the resulting
@ -51,11 +50,6 @@ extern void runtime_initialize(void);
extern void runtime_set_pthread_prio(pthread_t thread, unsigned int nice);
extern void runtime_set_resource_limits_to_max(void);
/* External Symbols */
extern void alloc_linear_memory(void);
INLINE char *get_function_from_table(uint32_t idx, uint32_t type_id);
extern void stub_init(int32_t offset);
static inline char *
runtime_print_sigalrm_handler(enum RUNTIME_SIGALRM_HANDLER variant)
{

@ -1,11 +0,0 @@
#pragma once
#include "wasm_linear_memory.h"
#include "wasm_indirect_table.h"
/* Cache of Frequently Accessed Members used to avoid pointer chasing */
struct sandbox_context_cache {
struct wasm_linear_memory * memory;
struct wasm_indirect_table *module_indirect_table;
};
extern thread_local struct sandbox_context_cache local_sandbox_context_cache;

@ -8,6 +8,7 @@
#include "panic.h"
#include "pool.h"
#include "sandbox_request.h"
#include "common/wasm_memory.h"
/***************************
* Public API *
@ -37,9 +38,9 @@ static inline void
sandbox_free_linear_memory(struct sandbox *sandbox)
{
/* TODO Replace pool with parsec linked list */
wasm_linear_memory_wipe(sandbox->memory);
wasm_memory_wipe(sandbox->memory);
if (pool_free_object(sandbox->module->linear_memory_pool[worker_thread_idx], sandbox) < 0) {
wasm_linear_memory_free(sandbox->memory);
wasm_memory_free(sandbox->memory);
}
sandbox->memory = NULL;
}

@ -7,6 +7,8 @@
#include "sandbox_types.h"
extern void stub_init(int32_t offset);
/**
* Takes the arguments from the sandbox struct and writes them into the WebAssembly linear memory
*/
@ -19,8 +21,8 @@ sandbox_setup_arguments(struct sandbox *sandbox)
/* Copy arguments into linear memory. It seems like malloc would clobber this, but I think this goes away in
* WASI, so not worth fixing*/
sandbox->arguments_offset = wasm_linear_memory_get_size(sandbox->memory);
int rc = wasm_linear_memory_expand(sandbox->memory, WASM_PAGE_SIZE);
sandbox->arguments_offset = wasm_memory_get_size(sandbox->memory);
int rc = wasm_memory_expand(sandbox->memory, WASM_PAGE_SIZE);
assert(rc == 0);
stub_init(sandbox->arguments_offset);

@ -12,7 +12,8 @@
#include "module.h"
#include "ps_list.h"
#include "sandbox_state.h"
#include "wasm_types.h"
#include "common/wasm_types.h"
#include "common/wasm_memory.h"
#ifdef LOG_SANDBOX_MEMORY_PROFILE
#define SANDBOX_PAGE_ALLOCATION_TIMESTAMP_COUNT 1024
@ -94,9 +95,9 @@ struct sandbox {
struct module *module; /* the module this is an instance of */
/* WebAssembly Instance State */
struct arch_context ctxt;
struct sandbox_stack stack;
struct wasm_linear_memory *memory;
struct arch_context ctxt;
struct sandbox_stack stack;
struct wasm_memory * memory;
/* Scheduling and Temporal State */
struct sandbox_timestamps timestamp_of;

@ -1,63 +0,0 @@
#pragma once
#include <stdint.h>
/* memory also provides the table access functions */
#define INDIRECT_TABLE_SIZE (1 << 10)
struct wasm_indirect_table_entry {
uint32_t type_id;
void * func_pointer;
};
struct wasm_indirect_table {
uint32_t length;
uint32_t capacity;
struct wasm_indirect_table_entry data[];
};
static inline struct wasm_indirect_table *
wasm_indirect_table_allocate(size_t capacity)
{
struct wasm_indirect_table *self = (struct wasm_indirect_table *)malloc(
sizeof(struct wasm_indirect_table) + capacity * sizeof(struct wasm_indirect_table_entry));
self->capacity = capacity;
self->length = 0;
return self;
}
static inline void
wasm_indirect_table_free(struct wasm_indirect_table *self)
{
assert(self != NULL);
free(self);
}
static inline char *
wasm_indirect_table_get(struct wasm_indirect_table *self, uint32_t idx, uint32_t type_id)
{
assert(self != NULL);
assert(idx < self->capacity);
struct wasm_indirect_table_entry f = self->data[idx];
// FIXME: Commented out function type check because of gocr
// assert(f.type_id == type_id);
assert(f.func_pointer != NULL);
return f.func_pointer;
}
static inline void
wasm_indirect_table_set(struct wasm_indirect_table *self, uint32_t idx, uint32_t type_id, char *pointer)
{
assert(self != NULL);
assert(idx < self->capacity);
/* TODO: atomic for multiple concurrent invocations? Issue #97 */
if (self->data[idx].type_id == type_id && self->data[idx].func_pointer == pointer) return;
self->data[idx] = (struct wasm_indirect_table_entry){ .type_id = type_id, .func_pointer = pointer };
}

@ -1,10 +0,0 @@
#pragma once
#include <stdint.h>
/* FIXME: per-module configuration? Issue #101 */
#define WASM_PAGE_SIZE (1024 * 64) /* 64KB */
#define WASM_MEMORY_PAGES_INITIAL (1 << 8) /* 256 Pages ~16MB */
#define WASM_MEMORY_PAGES_MAX (1 << 16) /* 32,768 Pages ~4GB */
#define WASM_STACK_SIZE (1 << 19) /* 512KB */

@ -16,9 +16,9 @@
thread_local struct sandbox *worker_thread_current_sandbox = NULL;
thread_local struct sandbox_context_cache local_sandbox_context_cache = {
.memory = NULL,
.module_indirect_table = NULL,
thread_local struct wasm_module_instance current_wasm_module_instance = {
.memory = NULL,
.table = NULL,
};
/**

@ -14,7 +14,7 @@
#include "scheduler.h"
#include "sandbox_functions.h"
#include "worker_thread.h"
#include "sandbox_context_cache.h"
#include "common/wasm_store.h"
// What should we tell the child program its UID and GID are?
#define UID 0xFF
@ -45,7 +45,7 @@ stub_init(int32_t offset)
char *program_name = current_sandbox->module->name;
// Copy the program name into WASM accessible memory
int32_t program_name_offset = offset;
strcpy(wasm_linear_memory_get_ptr_void(current_sandbox->memory, offset, sizeof(program_name)), program_name);
strcpy(wasm_memory_get_ptr_void(current_sandbox->memory, offset, sizeof(program_name)), program_name);
offset += sizeof(program_name);
// The construction of this is:
@ -71,7 +71,7 @@ stub_init(int32_t offset)
0,
};
int32_t env_vec_offset = offset;
memcpy(wasm_linear_memory_get_ptr_void(current_sandbox->memory, env_vec_offset, sizeof(env_vec)), env_vec,
memcpy(wasm_memory_get_ptr_void(current_sandbox->memory, env_vec_offset, sizeof(env_vec)), env_vec,
sizeof(env_vec));
module_initialize_libc(current_sandbox_get()->module, env_vec_offset, program_name_offset);
@ -222,8 +222,8 @@ wasm_mmap(int32_t addr, int32_t len, int32_t prot, int32_t flags, int32_t fd, in
assert(len % WASM_PAGE_SIZE == 0);
int32_t result = wasm_linear_memory_get_size(local_sandbox_context_cache.memory);
if (wasm_linear_memory_expand(local_sandbox_context_cache.memory, len) == -1) { result = (uint32_t)-1; }
int32_t result = wasm_memory_get_size(current_wasm_module_instance.memory);
if (wasm_memory_expand(current_wasm_module_instance.memory, len) == -1) { result = (uint32_t)-1; }
return result;
}
@ -320,18 +320,18 @@ wasm_mremap(int32_t offset, int32_t old_size, int32_t new_size, int32_t flags)
if (new_size <= old_size) return offset;
// If at end of linear memory, just expand and return same address
if (offset + old_size == local_sandbox_context_cache.memory->size) {
if (offset + old_size == current_wasm_module_instance.memory->size) {
int32_t amount_to_expand = new_size - old_size;
wasm_linear_memory_expand(local_sandbox_context_cache.memory, amount_to_expand);
wasm_memory_expand(current_wasm_module_instance.memory, amount_to_expand);
return offset;
}
// Otherwise allocate at end of address space and copy
int32_t new_offset = local_sandbox_context_cache.memory->size;
wasm_linear_memory_expand(local_sandbox_context_cache.memory, new_size);
int32_t new_offset = current_wasm_module_instance.memory->size;
wasm_memory_expand(current_wasm_module_instance.memory, new_size);
// Get pointer of old offset and pointer of new offset
uint8_t *linear_mem = local_sandbox_context_cache.memory->data;
uint8_t *linear_mem = current_wasm_module_instance.memory->data;
uint8_t *src = &linear_mem[offset];
uint8_t *dest = &linear_mem[new_offset];

@ -16,7 +16,7 @@
#include "panic.h"
#include "runtime.h"
#include "scheduler.h"
#include "wasm_indirect_table.h"
#include "common/wasm_table.h"
const int JSON_MAX_ELEMENT_COUNT = 16;
const int JSON_MAX_ELEMENT_SIZE = 1024;
@ -192,7 +192,7 @@ module_new(char *name, char *path, uint32_t stack_size, uint32_t max_memory, uin
/* WebAssembly Indirect Table */
/* TODO: Should this be part of the module or per-sandbox? */
/* TODO: How should this table be sized? */
module->indirect_table = wasm_indirect_table_allocate(INDIRECT_TABLE_SIZE);
module->indirect_table = wasm_table_allocate(INDIRECT_TABLE_SIZE);
/* Request Response Buffer */
if (request_size == 0) request_size = MODULE_DEFAULT_REQUEST_RESPONSE_SIZE;
@ -201,22 +201,22 @@ module_new(char *name, char *path, uint32_t stack_size, uint32_t max_memory, uin
module->max_response_size = round_up_to_page(response_size);
/* Table initialization calls a function that runs within the sandbox. Rather than setting the current sandbox,
* we partially fake this out by only setting the module_indirect_table and then clearing after table
* we partially fake this out by only setting the table and then clearing after table
* initialization is complete.
*
* assumption: This approach depends on module_new only being invoked at program start before preemption is
* enabled. We are check that local_sandbox_context_cache.module_indirect_table is NULL to gain confidence that
* enabled. We are check that current_wasm_module_instance.table is NULL to gain confidence that
* we are not invoking this in a way that clobbers a current module.
*
* If we want to be able to do this later, we can possibly defer module_initialize_table until the first
* invocation. Alternatively, we can maintain the module_indirect_table per sandbox and call initialize
* invocation. Alternatively, we can maintain the table per sandbox and call initialize
* on each sandbox if this "assumption" is too restrictive and we're ready to pay a per-sandbox performance hit.
*/
assert(local_sandbox_context_cache.module_indirect_table == NULL);
local_sandbox_context_cache.module_indirect_table = module->indirect_table;
assert(current_wasm_module_instance.table == NULL);
current_wasm_module_instance.table = module->indirect_table;
module_initialize_table(module);
local_sandbox_context_cache.module_indirect_table = NULL;
current_wasm_module_instance.table = NULL;
/* Initialize per worker linear memory pools */
module->linear_memory_pool = calloc(runtime_worker_threads_count, sizeof(struct pool *));

@ -9,7 +9,7 @@
#include "sandbox_functions.h"
#include "sandbox_set_as_error.h"
#include "sandbox_set_as_initialized.h"
#include "wasm_linear_memory.h"
#include "common/wasm_memory.h"
/**
* Allocates a WebAssembly sandbox represented by the following layout
@ -30,14 +30,13 @@ sandbox_allocate_linear_memory(struct sandbox *self)
assert(initial <= (size_t)UINT32_MAX + 1);
assert(max <= (size_t)UINT32_MAX + 1);
self->memory = (struct wasm_linear_memory *)pool_allocate_object(
self->module->linear_memory_pool[worker_thread_idx]);
self->memory = (struct wasm_memory *)pool_allocate_object(self->module->linear_memory_pool[worker_thread_idx]);
if (self->memory == NULL) {
self->memory = wasm_linear_memory_allocate(initial, max);
self->memory = wasm_memory_allocate(initial, max);
if (unlikely(self->memory == NULL)) return -1;
} else {
wasm_linear_memory_set_size(self->memory, self->module->abi.starting_pages * WASM_PAGE_SIZE);
wasm_memory_set_size(self->memory, self->module->abi.starting_pages * WASM_PAGE_SIZE);
}
return 0;

@ -0,0 +1,3 @@
*.wasm
*.bc
*.so

@ -1,60 +1,67 @@
include Makefile.inc
CC=clang # Source -> Native
WASMCC=wasm32-unknown-unknown-wasm-clang # Source -> WebAssembly
TESTS=fibonacci empty empty
OPTFLAGS=-O0 -g
TMP_DIR=tmp/
TESTSRT=$(TESTS:%=%_rt)
# same stack-size for all
WASMLINKFLAGS=-Wl,-z,stack-size=524288,--allow-undefined,--no-threads,--stack-first,--no-entry,--export-all,--export=main,--export=dummy
WASMCFLAGS=${WASMLINKFLAGS} -nostartfiles
.PHONY: all
all: rttests tinyekf cifar10 gocr sod
@echo "Test Compilation done!"
# aWsm Compiler Runtime (WebAssembly -> LLVM Bitcode)
AWSM_NAME=awsm
AWSM_BASE_DIR=../../${AWSM_NAME}
DUMMY=${AWSM_BASE_DIR}/code_benches/dummy.c
# for SLEdge
SLEDGE_BASE_DIR=../../
SLEDGE_RT_DIR=${SLEDGE_BASE_DIR}/runtime/
SLEDGE_COMPILETIME_INC=${SLEDGE_RT_DIR}/include/common
SLEDGE_BIN_DIR=${SLEDGE_RT_DIR}/bin/
SLEDGE_COMPILETIME_SRC=${SLEDGE_RT_DIR}/compiletime/*.c
ALL=fibonacci empty license_plate_detection resize_image gocr cifar10
ALL_COPY_DEST=$(ALL:%=../../runtime/bin/%_wasm.so)
.PHONY: rttests
rttests: $(TESTSRT)
.PHONY: all
all: $(ALL_COPY_DEST)
.PHONY: clean
clean:
@echo "Cleaning Test Applications"
@rm -rf ${TMP_DIR}
@make clean -C ./CMSIS_5_NN/ -f Makefile
@make clean -C ./gocr/src/ -f wasm.mk
@make clean -C ./sod/
@make clean -C ./TinyEKF/extras/c/ -f wasm.mk
@rm -f ../../runtime/bin/*.so
cifar10.wasm:
@make cifar10.wasm -C ./CMSIS_5_NN/ -f Makefile
@cp ./CMSIS_5_NN/cifar10.wasm cifar10.wasm
gocr.wasm:
@make gocr.wasm -C ./gocr/src/ -f wasm.mk
@cp ./gocr/src/gocr.wasm gocr.wasm
resize_image.wasm:
@make dir resize_image.wasm -C ./sod/
@cp ./sod/bin/resize_image.wasm resize_image.wasm
license_plate_detection.wasm:
@make dir license_plate_detection.wasm -C ./sod/
@cp ./sod/bin/license_plate_detection.wasm license_plate_detection.wasm
gps_ekf_fn.wasm:
@make gps_ekf_fn.wasm -C ./TinyEKF/extras/c/ -f wasm.mk
@cp ./TinyEKF/extras/c/gps_ekf_fn.wasm gps_ekf_fn.wasm
%.wasm: %.c $(DUMMY)
${WASMCC} ${WASMCFLAGS} ${OPTFLAGS} $^ -o $@
%.bc: %.wasm
${AWSM_NAME} --inline-constant-globals --runtime-globals $^ -o $@
.PHONY: tinyekf
tinyekf:
@echo "Making and Installing tinyekf"
@make gps_ekf_fn.so -C ./TinyEKF/extras/c/ -f wasm.mk
@cp ./TinyEKF/extras/c/gps_ekf_fn.so ${SLEDGE_BIN_DIR}/ekf_wasm.so
.PHONY: cifar10
cifar10:
@echo "Making and Installing cifar10"
@make cifar10.so -C ./CMSIS_5_NN/ -f Makefile
@cp ./CMSIS_5_NN/cifar10.so ${SLEDGE_BIN_DIR}/cifar10_wasm.so
.PHONY: gocr
gocr:
@echo "Making and Installing gocr"
@make gocr.so -C ./gocr/src/ -f wasm.mk
@cp ./gocr/src/gocr.so ${SLEDGE_BIN_DIR}/gocr_wasm.so
.PHONY: sod
sod:
@echo "Making and Installing license_plate_detection and image_resize"
@make dir samples.so -C ./sod/
@cp ./sod/bin/license_plate_detection.so ${SLEDGE_BIN_DIR}/lpd_wasm.so
@cp ./sod/bin/resize_image.so ${SLEDGE_BIN_DIR}/resize_wasm.so
%_rt:
@mkdir -p ${TMP_DIR}
# Compile the wasm file
@echo "Compiling $(@:%_rt=%)"
${WASMCC} ${$(@:%_rt=%)_CFLAGS} ${WASMCFLAGS} ${OPTFLAGS} $(@:%_rt=%)/*.c $(AWSM_DUMMY) -o ${TMP_DIR}/$(@:%_rt=%).wasm
# Compile the *.bc file
${AWSM_NAME} --inline-constant-globals --runtime-globals ${TMP_DIR}/$(@:%_rt=%).wasm -o ${TMP_DIR}/$(@:%_rt=%).bc
# Compile the *.so file
${CC} --shared -fPIC ${OPTFLAGS} -I${SLEDGE_RT_INC} -D${USE_MEM} ${TMP_DIR}/$(@:%_rt=%).bc ${SLEDGE_MEMC} ${SLEDGE_WASMISA} -o ${TMP_DIR}/$(@:%_rt=%)_wasm.so
# Copy the *.so file to the binary directory
@cp ${TMP_DIR}/$(@:%_rt=%)_wasm.so ${SLEDGE_BIN_DIR}
# @rm -rf ${TMP_DIR}
%_wasm.so: %.bc ${SLEDGE_COMPILETIME_SRC}
${CC} --shared -fPIC ${OPTFLAGS} -I${SLEDGE_COMPILETIME_INC} $^ -o $@
../../runtime/bin/%.so: %.so
cp $^ $@

@ -1,42 +0,0 @@
ARCH := $(shell uname -m)
CC=clang # Source -> Native
WASMCC=wasm32-unknown-unknown-wasm-clang # Source -> WebAssembly
OPTFLAGS=-O3 -flto
MEMC_64=64bit_nix.c
# MEMC_NO=no_protection.c
# MEMC_GEN=generic.c
# MEMC_MPX=mpx.c
# MEMC_SEG=segmented.c
TMP_DIR=tmp/
# same stack-size for all
WASMLINKFLAGS=-Wl,-z,stack-size=524288,--allow-undefined,--no-threads,--stack-first,--no-entry,--export-all,--export=main,--export=dummy
WASMCFLAGS=${WASMLINKFLAGS} -nostartfiles
# aWsm Compiler Runtime (WebAssembly -> LLVM Bitcode)
AWSM_NAME=awsm
AWSM_BASE_DIR=../../${AWSM_NAME}
AWSM_RT_DIR=${AWSM_BASE_DIR}/runtime/
AWSM_RT_MEM=${AWSM_RT_DIR}/memory/
AWSM_RT_LIBC=${AWSM_RT_DIR}/libc/libc_backing.c
AWSM_RT_RT=${AWSM_RT_DIR}/runtime.c
AWSM_RT_ENV=${AWSM_RT_DIR}/libc/env.c
# Is seems like the arch specific code no longer exists
# AWSM_RT_ENV=${AWSM_RT_DIR}/libc/env.c ${AWSM_RT_DIR}/libc/env_${ARCH}.c
AWSM_MEMC=${AWSM_RT_MEM}/${MEMC_64}
AWSM_DUMMY=${AWSM_BASE_DIR}/code_benches/dummy.c
# for SLEdge
SLEDGE_BASE_DIR=../../
SLEDGE_RT_DIR=${SLEDGE_BASE_DIR}/runtime/
SLEDGE_RT_INC=${SLEDGE_RT_DIR}/include/
SLEDGE_BIN_DIR=${SLEDGE_RT_DIR}/bin/
SLEDGE_WASMISA=${SLEDGE_RT_DIR}/compiletime/instr.c
USE_MEM=USE_MEM_VM
ifeq ($(USE_MEM),USE_MEM_VM)
SLEDGE_MEMC=${SLEDGE_RT_DIR}/compiletime/memory/${MEMC_64}
endif

@ -1,5 +1,4 @@
#include <stdio.h>
// #include "get_time.h"
unsigned long int
fib(unsigned long int n)
{
@ -12,11 +11,7 @@ main(int argc, char **argv)
{
unsigned long n = 0, r;
scanf("%lu", &n);
// unsigned long long st = get_time(), en;
r = fib(n);
// en = get_time();
printf("%lu\n", r);
// print_time(st, en);
return 0;
}

@ -1,44 +0,0 @@
#ifndef GET_TIME_H
#define GET_TIME_H
#include <time.h>
#include <sys/time.h>
#include <stdio.h>
#ifndef WASM
#ifndef CPU_FREQ
#define CPU_FREQ 1000
#endif
#endif
static unsigned long long
get_time()
{
#if 0
unsigned long long int ret = 0;
unsigned int cycles_lo;
unsigned int cycles_hi;
__asm__ volatile ("rdtsc" : "=a" (cycles_lo), "=d" (cycles_hi));
ret = (unsigned long long int)cycles_hi << 32 | cycles_lo;
return ret;
#else
struct timeval Tp;
int stat;
stat = gettimeofday(&Tp, NULL);
if (stat != 0) printf("Error return from gettimeofday: %d", stat);
return (Tp.tv_sec * 1000000 + Tp.tv_usec);
#endif
}
static inline void
print_time(unsigned long long s, unsigned long long e)
{
#if 0
printf("%llu cycs, %llu us\n", e - s, (e - s) / CPU_FREQ);
#else
fprintf(stdout, "%llu us\n", e - s);
#endif
}
#endif /* GET_TIME_H */

@ -1,32 +0,0 @@
#!/bin/sh
ITERS=$3
# before running this benchmark,
# copy fibonacci to fibonacci_native.out
testeach() {
tmp_cnt=${ITERS}
exe_relpath=$1
echo "${exe_relpath} ($2) for ${tmp_cnt}"
while [ ${tmp_cnt} -gt 0 ]; do
bench=$(echo $2 | $exe_relpath 2> /dev/null)
tmp_cnt=$((tmp_cnt - 1))
echo "$bench"
done
echo "Done!"
}
MAXNUM=$2
tmp1_cnt=${MAXNUM}
while [ ${tmp1_cnt} -gt 28 ]; do
testeach ./fibonacci_$1.out ${tmp1_cnt}
tmp1_cnt=$((tmp1_cnt - 1))
done
echo "All done!"
Loading…
Cancel
Save