mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
wasi: use WasmMemoryObject handle for perf (#43544)
PR-URL: #43544 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
b6bc44f8bc
commit
f8bb0b183c
16
lib/wasi.js
16
lib/wasi.js
@ -10,14 +10,12 @@ const {
|
||||
} = primordials;
|
||||
|
||||
const {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_WASI_ALREADY_STARTED
|
||||
} = require('internal/errors').codes;
|
||||
const {
|
||||
emitExperimentalWarning,
|
||||
kEmptyObject,
|
||||
} = require('internal/util');
|
||||
const { isArrayBuffer } = require('internal/util/types');
|
||||
const {
|
||||
validateArray,
|
||||
validateBoolean,
|
||||
@ -39,20 +37,6 @@ function setupInstance(self, instance) {
|
||||
validateObject(instance, 'instance');
|
||||
validateObject(instance.exports, 'instance.exports');
|
||||
|
||||
// WASI::_SetMemory() in src/node_wasi.cc only expects that |memory| is
|
||||
// an object. It will try to look up the .buffer property when needed
|
||||
// and fail with UVWASI_EINVAL when the property is missing or is not
|
||||
// an ArrayBuffer. Long story short, we don't need much validation here
|
||||
// but we type-check anyway because it helps catch bugs in the user's
|
||||
// code early.
|
||||
validateObject(instance.exports.memory, 'instance.exports.memory');
|
||||
if (!isArrayBuffer(instance.exports.memory.buffer)) {
|
||||
throw new ERR_INVALID_ARG_TYPE(
|
||||
'instance.exports.memory.buffer',
|
||||
['WebAssembly.Memory'],
|
||||
instance.exports.memory.buffer);
|
||||
}
|
||||
|
||||
self[kInstance] = instance;
|
||||
self[kSetMemory](instance.exports.memory);
|
||||
}
|
||||
|
@ -72,9 +72,7 @@ inline void Debug(WASI* wasi, Args&&... args) {
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
using v8::Array;
|
||||
using v8::ArrayBuffer;
|
||||
using v8::BackingStore;
|
||||
using v8::BigInt;
|
||||
using v8::Context;
|
||||
@ -89,7 +87,7 @@ using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Uint32;
|
||||
using v8::Value;
|
||||
|
||||
using v8::WasmMemoryObject;
|
||||
|
||||
static MaybeLocal<Value> WASIException(Local<Context> context,
|
||||
int errorno,
|
||||
@ -1642,26 +1640,22 @@ void WASI::SockShutdown(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
void WASI::_SetMemory(const FunctionCallbackInfo<Value>& args) {
|
||||
WASI* wasi;
|
||||
CHECK_EQ(args.Length(), 1);
|
||||
CHECK(args[0]->IsObject());
|
||||
ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This());
|
||||
wasi->memory_.Reset(wasi->env()->isolate(), args[0].As<Object>());
|
||||
CHECK_EQ(args.Length(), 1);
|
||||
if (!args[0]->IsWasmMemoryObject()) {
|
||||
return node::THROW_ERR_INVALID_ARG_TYPE(
|
||||
wasi->env(),
|
||||
"\"instance.exports.memory\" property must be a WebAssembly.Memory "
|
||||
"object");
|
||||
}
|
||||
wasi->memory_.Reset(wasi->env()->isolate(), args[0].As<WasmMemoryObject>());
|
||||
}
|
||||
|
||||
|
||||
uvwasi_errno_t WASI::backingStore(char** store, size_t* byte_length) {
|
||||
Environment* env = this->env();
|
||||
Local<Object> memory = PersistentToLocal::Strong(this->memory_);
|
||||
Local<Value> prop;
|
||||
|
||||
if (!memory->Get(env->context(), env->buffer_string()).ToLocal(&prop))
|
||||
return UVWASI_EINVAL;
|
||||
|
||||
if (!prop->IsArrayBuffer())
|
||||
return UVWASI_EINVAL;
|
||||
|
||||
Local<ArrayBuffer> ab = prop.As<ArrayBuffer>();
|
||||
std::shared_ptr<BackingStore> backing_store = ab->GetBackingStore();
|
||||
Local<WasmMemoryObject> memory = PersistentToLocal::Strong(this->memory_);
|
||||
std::shared_ptr<BackingStore> backing_store =
|
||||
memory->Buffer()->GetBackingStore();
|
||||
*byte_length = backing_store->ByteLength();
|
||||
*store = static_cast<char*>(backing_store->Data());
|
||||
CHECK_NOT_NULL(*store);
|
||||
|
@ -94,7 +94,7 @@ class WASI : public BaseObject,
|
||||
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::Object> memory_;
|
||||
v8::Global<v8::WasmMemoryObject> memory_;
|
||||
uvwasi_mem_t alloc_info_;
|
||||
size_t current_uvwasi_memory_ = 0;
|
||||
};
|
||||
|
@ -47,7 +47,10 @@ const bufferSource = fixtures.readSync('simple.wasm');
|
||||
|
||||
Object.defineProperty(instance, 'exports', {
|
||||
get() {
|
||||
return { _initialize: 5, memory: new Uint8Array() };
|
||||
return {
|
||||
_initialize: 5,
|
||||
memory: new WebAssembly.Memory({ initial: 1 }),
|
||||
};
|
||||
},
|
||||
});
|
||||
assert.throws(
|
||||
@ -70,7 +73,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
|
||||
return {
|
||||
_start() {},
|
||||
_initialize() {},
|
||||
memory: new Uint8Array(),
|
||||
memory: new WebAssembly.Memory({ initial: 1 }),
|
||||
};
|
||||
}
|
||||
});
|
||||
@ -97,55 +100,11 @@ const bufferSource = fixtures.readSync('simple.wasm');
|
||||
() => { wasi.initialize(instance); },
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: /"instance\.exports\.memory" property must be of type object/
|
||||
message: /"instance\.exports\.memory" property must be a WebAssembly\.Memory object/
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
// Verify that a non-ArrayBuffer memory.buffer is rejected.
|
||||
const wasi = new WASI({});
|
||||
const wasm = await WebAssembly.compile(bufferSource);
|
||||
const instance = await WebAssembly.instantiate(wasm);
|
||||
|
||||
Object.defineProperty(instance, 'exports', {
|
||||
get() {
|
||||
return {
|
||||
_initialize() {},
|
||||
memory: {},
|
||||
};
|
||||
}
|
||||
});
|
||||
// The error message is a little white lie because any object
|
||||
// with a .buffer property of type ArrayBuffer is accepted,
|
||||
// but 99% of the time a WebAssembly.Memory object is used.
|
||||
assert.throws(
|
||||
() => { wasi.initialize(instance); },
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: /"instance\.exports\.memory\.buffer" property must be an WebAssembly\.Memory/
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
// Verify that an argument that duck-types as a WebAssembly.Instance
|
||||
// is accepted.
|
||||
const wasi = new WASI({});
|
||||
const wasm = await WebAssembly.compile(bufferSource);
|
||||
const instance = await WebAssembly.instantiate(wasm);
|
||||
|
||||
Object.defineProperty(instance, 'exports', {
|
||||
get() {
|
||||
return {
|
||||
_initialize() {},
|
||||
memory: { buffer: new ArrayBuffer(0) },
|
||||
};
|
||||
}
|
||||
});
|
||||
wasi.initialize(instance);
|
||||
}
|
||||
|
||||
{
|
||||
// Verify that a WebAssembly.Instance from another VM context is accepted.
|
||||
const wasi = new WASI({});
|
||||
|
@ -47,7 +47,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
|
||||
|
||||
Object.defineProperty(instance, 'exports', {
|
||||
get() {
|
||||
return { memory: new Uint8Array() };
|
||||
return { memory: new WebAssembly.Memory({ initial: 1 }) };
|
||||
},
|
||||
});
|
||||
assert.throws(
|
||||
@ -70,7 +70,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
|
||||
return {
|
||||
_start() {},
|
||||
_initialize() {},
|
||||
memory: new Uint8Array(),
|
||||
memory: new WebAssembly.Memory({ initial: 1 }),
|
||||
};
|
||||
}
|
||||
});
|
||||
@ -97,55 +97,11 @@ const bufferSource = fixtures.readSync('simple.wasm');
|
||||
() => { wasi.start(instance); },
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: /"instance\.exports\.memory" property must be of type object/
|
||||
message: /"instance\.exports\.memory" property must be a WebAssembly\.Memory object/
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
// Verify that a non-ArrayBuffer memory.buffer is rejected.
|
||||
const wasi = new WASI({});
|
||||
const wasm = await WebAssembly.compile(bufferSource);
|
||||
const instance = await WebAssembly.instantiate(wasm);
|
||||
|
||||
Object.defineProperty(instance, 'exports', {
|
||||
get() {
|
||||
return {
|
||||
_start() {},
|
||||
memory: {},
|
||||
};
|
||||
}
|
||||
});
|
||||
// The error message is a little white lie because any object
|
||||
// with a .buffer property of type ArrayBuffer is accepted,
|
||||
// but 99% of the time a WebAssembly.Memory object is used.
|
||||
assert.throws(
|
||||
() => { wasi.start(instance); },
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: /"instance\.exports\.memory\.buffer" property must be an WebAssembly\.Memory/
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
// Verify that an argument that duck-types as a WebAssembly.Instance
|
||||
// is accepted.
|
||||
const wasi = new WASI({});
|
||||
const wasm = await WebAssembly.compile(bufferSource);
|
||||
const instance = await WebAssembly.instantiate(wasm);
|
||||
|
||||
Object.defineProperty(instance, 'exports', {
|
||||
get() {
|
||||
return {
|
||||
_start() {},
|
||||
memory: { buffer: new ArrayBuffer(0) },
|
||||
};
|
||||
}
|
||||
});
|
||||
wasi.start(instance);
|
||||
}
|
||||
|
||||
{
|
||||
// Verify that a WebAssembly.Instance from another VM context is accepted.
|
||||
const wasi = new WASI({});
|
||||
|
Loading…
Reference in New Issue
Block a user