Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasi: fast calls #43697

Merged
merged 1 commit into from Dec 8, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1,826 changes: 705 additions & 1,121 deletions src/node_wasi.cc

Large diffs are not rendered by default.

195 changes: 135 additions & 60 deletions src/node_wasi.h
Expand Up @@ -6,10 +6,15 @@
#include "base_object.h"
#include "node_mem.h"
#include "uvwasi.h"
#include "v8-fast-api-calls.h"

namespace node {
namespace wasi {

struct WasmMemory {
char* data;
size_t size;
};

class WASI : public BaseObject,
public mem::NgLibMemoryManager<WASI, uvwasi_mem_t> {
Expand All @@ -23,57 +28,120 @@ class WASI : public BaseObject,
SET_MEMORY_INFO_NAME(WASI)
SET_SELF_SIZE(WASI)

static void ArgsGet(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ArgsSizesGet(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ClockResGet(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ClockTimeGet(const v8::FunctionCallbackInfo<v8::Value>& args);
static void EnvironGet(const v8::FunctionCallbackInfo<v8::Value>& args);
static void EnvironSizesGet(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdAdvise(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdAllocate(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdClose(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdDatasync(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdFdstatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdFdstatSetFlags(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdFdstatSetRights(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdFilestatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdFilestatSetSize(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdFilestatSetTimes(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdPread(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdPrestatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdPrestatDirName(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdPwrite(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdRead(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdReaddir(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdRenumber(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdSeek(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdSync(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdTell(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FdWrite(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PathCreateDirectory(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void PathFilestatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PathFilestatSetTimes(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void PathLink(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PathOpen(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PathReadlink(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PathRemoveDirectory(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void PathRename(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PathSymlink(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PathUnlinkFile(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PollOneoff(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ProcExit(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ProcRaise(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RandomGet(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SchedYield(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SockRecv(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SockSend(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SockShutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
static uint32_t ArgsGet(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t ArgsSizesGet(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t ClockResGet(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t ClockTimeGet(WASI&, WasmMemory, uint32_t, uint64_t, uint32_t);
static uint32_t EnvironGet(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t EnvironSizesGet(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t FdAdvise(
WASI&, WasmMemory, uint32_t, uint64_t, uint64_t, uint32_t);
static uint32_t FdAllocate(WASI&, WasmMemory, uint32_t, uint64_t, uint64_t);
static uint32_t FdClose(WASI&, WasmMemory, uint32_t);
static uint32_t FdDatasync(WASI&, WasmMemory, uint32_t);
static uint32_t FdFdstatGet(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t FdFdstatSetFlags(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t FdFdstatSetRights(
WASI&, WasmMemory, uint32_t, uint64_t, uint64_t);
static uint32_t FdFilestatGet(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t FdFilestatSetSize(WASI&, WasmMemory, uint32_t, uint64_t);
static uint32_t FdFilestatSetTimes(
WASI&, WasmMemory, uint32_t, uint64_t, uint64_t, uint32_t);
static uint32_t FdPread(WASI&,
WasmMemory memory,
uint32_t,
uint32_t,
uint32_t,
uint64_t,
uint32_t);
static uint32_t FdPrestatGet(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t FdPrestatDirName(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t);
static uint32_t FdPwrite(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t, uint64_t, uint32_t);
static uint32_t FdRead(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t, uint32_t);
static uint32_t FdReaddir(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t, uint64_t, uint32_t);
static uint32_t FdRenumber(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t FdSeek(
WASI&, WasmMemory, uint32_t, int64_t, uint32_t, uint32_t);
static uint32_t FdSync(WASI&, WasmMemory, uint32_t);
static uint32_t FdTell(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t FdWrite(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t, uint32_t);
static uint32_t PathCreateDirectory(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t);
static uint32_t PathFilestatGet(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
static uint32_t PathFilestatSetTimes(WASI&,
WasmMemory,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint64_t,
uint64_t,
uint32_t);
static uint32_t PathLink(WASI&,
WasmMemory,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint32_t);
static uint32_t PathOpen(WASI&,
WasmMemory,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint64_t,
uint64_t,
uint32_t,
uint32_t);
static uint32_t PathReadlink(WASI&,
WasmMemory,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint32_t);
static uint32_t PathRemoveDirectory(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t);
static uint32_t PathRename(WASI&,
WasmMemory,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint32_t);
static uint32_t PathSymlink(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
static uint32_t PathUnlinkFile(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t);
static uint32_t PollOneoff(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t, uint32_t);
static void ProcExit(WASI&, WasmMemory, uint32_t);
static uint32_t ProcRaise(WASI&, WasmMemory, uint32_t);
static uint32_t RandomGet(WASI&, WasmMemory, uint32_t, uint32_t);
static uint32_t SchedYield(WASI&, WasmMemory);
static uint32_t SockRecv(WASI&,
WasmMemory,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint32_t,
uint32_t);
static uint32_t SockSend(
WASI&, WasmMemory, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
static uint32_t SockShutdown(WASI&, WasmMemory, uint32_t, uint32_t);

static void _SetMemory(const v8::FunctionCallbackInfo<v8::Value>& args);

Expand All @@ -82,17 +150,24 @@ class WASI : public BaseObject,
void IncreaseAllocatedSize(size_t size);
void DecreaseAllocatedSize(size_t size);

// <typename FT, FT F> as a C++14 desugaring of `<auto F>`
template <typename FT, FT F, typename R, typename... Args>
class WasiFunction {
public:
static void SetFunction(Environment*,
const char*,
v8::Local<v8::FunctionTemplate>);

private:
static R FastCallback(v8::Local<v8::Object> receiver,
Args...,
v8::FastApiCallbackOptions&);

static void SlowCallback(const v8::FunctionCallbackInfo<v8::Value>&);
};

private:
~WASI() override;
inline void readUInt8(char* memory, uint8_t* value, uint32_t offset);
inline void readUInt16(char* memory, uint16_t* value, uint32_t offset);
inline void readUInt32(char* memory, uint32_t* value, uint32_t offset);
inline void readUInt64(char* memory, uint64_t* value, uint32_t offset);
inline void writeUInt8(char* memory, uint8_t value, uint32_t offset);
inline void writeUInt16(char* memory, uint16_t value, uint32_t offset);
inline void writeUInt32(char* memory, uint32_t value, uint32_t offset);
inline void writeUInt64(char* memory, uint64_t value, uint32_t offset);
uvwasi_errno_t backingStore(char** store, size_t* byte_length);
uvwasi_t uvw_;
v8::Global<v8::WasmMemoryObject> memory_;
uvwasi_mem_t alloc_info_;
Expand Down
5 changes: 3 additions & 2 deletions test/wasi/Makefile
@@ -1,12 +1,13 @@
CC = /opt/wasi-sdk/bin/clang
TARGET = wasm32-unknown-wasi
TARGET = wasm32-wasi
SYSROOT =
CFLAGS = -D_WASI_EMULATED_PROCESS_CLOCKS -lwasi-emulated-process-clocks

OBJ = $(patsubst c/%.c, wasm/%.wasm, $(wildcard c/*.c))
all: $(OBJ)

wasm/%.wasm : c/%.c
$(CC) $< --target=$(TARGET) --sysroot=$(SYSROOT) -s -o $@
$(CC) $< $(CFLAGS) --target=$(TARGET) --sysroot=$(SYSROOT) -s -o $@

.PHONY clean:
rm -f $(OBJ)
8 changes: 7 additions & 1 deletion test/wasi/test-wasi.js
Expand Up @@ -35,7 +35,7 @@ if (process.argv[2] === 'wasi-child') {
const cp = require('child_process');
const { checkoutEOL } = common;

function runWASI(options) {
function innerRunWASI(options, args) {
console.log('executing', options.test);
const opts = {
env: {
Expand All @@ -49,6 +49,7 @@ if (process.argv[2] === 'wasi-child') {
opts.input = options.stdin;

const child = cp.spawnSync(process.execPath, [
...args,
'--experimental-wasi-unstable-preview1',
__filename,
'wasi-child',
Expand All @@ -60,6 +61,11 @@ if (process.argv[2] === 'wasi-child') {
assert.strictEqual(child.stdout.toString(), options.stdout || '');
}

function runWASI(options) {
innerRunWASI(options, ['--no-turbo-fast-api-calls']);
innerRunWASI(options, ['--turbo-fast-api-calls']);
}

runWASI({ test: 'cant_dotdot' });

// Tests that are currently unsupported on IBM i PASE.
Expand Down
Binary file modified test/wasi/wasm/cant_dotdot.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/clock_getres.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/create_symlink.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/exitcode.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/fd_prestat_get_refresh.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/follow_symlink.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/freopen.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/ftruncate.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/getentropy.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/getrusage.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/gettimeofday.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/link.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/main_args.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/notdir.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/poll.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/preopen_populates.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/read_file.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/read_file_twice.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/readdir.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/stat.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/stdin.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/symlink_escape.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/symlink_loop.wasm
Binary file not shown.
Binary file modified test/wasi/wasm/write_file.wasm
Binary file not shown.