From: Brendan Hansen Date: Mon, 18 Oct 2021 14:08:09 +0000 (-0500) Subject: updated js loader to support multiple threads X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=d6698fa0bb882f80a5d4e26e0f3f409a52a07ca7;p=onyx.git updated js loader to support multiple threads --- diff --git a/bin/onyx b/bin/onyx index 4e597087..9e067728 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/bin/onyx-js b/bin/onyx-js index 80c843d2..8bf494fb 100755 --- a/bin/onyx-js +++ b/bin/onyx-js @@ -87,7 +87,7 @@ if (isMainThread) { wasm_instance = res.instance; const lib = res.instance.exports; - lib._thread_start(funcidx, dataptr); + lib._thread_start(thread_id, funcidx, dataptr); lib._thread_exit(thread_id); }); } diff --git a/bin/onyx-loader.js b/bin/onyx-loader.js index a48a38ac..017dbbb1 100644 --- a/bin/onyx-loader.js +++ b/bin/onyx-loader.js @@ -2,19 +2,62 @@ window.ONYX_MODULES = window.ONYX_MODULES || []; window.ONYX_MEMORY = null; window.ONYX_INSTANCE = null; +window.ONYX_BYTES = null; +window.ONYX_THREAD_SCRIPT = "onyx-thread.js"; window.ONYX_MODULES.push({ module_name: "host", print_str: function(ptr, len) { - var buffer = new Uint8Array(ONYX_MEMORY.buffer, ptr, len); - var string = new TextDecoder().decode(buffer); - console.log(string); + console.log(onyx_decode_text(ptr, len)); }, - exit: function() { debugger; } + exit: function() { debugger; }, + + spawn_thread: function(id, funcidx, dataptr) { + try { + let needed_imports = {}; + + for (let i = 0; i < window.ONYX_MODULES.length; i++) { + needed_imports[window.ONYX_MODULES[i].module_name] = []; + + for (let k of Object.keys(window.ONYX_MODULES[i])) { + if (k == "module_name") continue; + + needed_imports[window.ONYX_MODULES[i].module_name].push(k); + } + } + + const worker = new Worker(window.ONYX_THREAD_SCRIPT); + worker.postMessage({ + thread_id : id, + memory : window.ONYX_MEMORY, + wasm_bytes : window.ONYX_BYTES, + funcidx : funcidx, + dataptr : dataptr, + imports : needed_imports, + }); + + return 1; + + } catch (e) { + console.error(e); + return 0; + } + }, }); +function onyx_decode_text(ptr, len) { + let v = new DataView(window.ONYX_MEMORY.buffer); + + let s = ""; + for (let i = 0; i < len; i++) { + s += String.fromCharCode(v.getUint8(ptr + i)); + } + + return s; +} + function launch_onyx_program(script_path, call_start) { fetch(script_path) .then(function(res) { return res.arrayBuffer(); }) @@ -35,13 +78,41 @@ function launch_onyx_program(script_path, call_start) { }); } +function launch_multi_threaded_onyx_program(script_path, data_path, call_start) { + Promise.all([fetch(script_path), fetch(data_path)]) + .then(function(xs) { return Promise.all([xs[0].arrayBuffer(), xs[1].arrayBuffer()]); }) + .then(function(data) { + var import_object = {}; + + for (var i = 0; i < window.ONYX_MODULES.length; i++) { + import_object[window.ONYX_MODULES[i].module_name] = window.ONYX_MODULES[i]; + } + + import_object["onyx"] = { memory: new WebAssembly.Memory({ initial: 1024, maximum: 65536, shared: true }) }; + window.ONYX_MEMORY = import_object["onyx"]["memory"]; + window.ONYX_BYTES = data[0]; + + WebAssembly.instantiate(data[1], import_object) + .then(function (data_module) { + WebAssembly.instantiate(data[0], import_object) + .then(function (code_module) { + window.ONYX_INSTANCE = code_module.instance; + code_module.instance.exports._start(); + }); + }); + }); +} + window.onload = function() { var script_tags = document.getElementsByTagName("script"); for (var i = 0; i < script_tags.length; i++) { if (script_tags[i].getAttribute("type") == "application/onyx") { - // @ROBUSTNESS: It should be configurable which function is called on start up of a Onyx WASM module. - launch_onyx_program(script_tags[i].getAttribute("src"), true); + if (script_tags[i].getAttribute("multi-threaded")) { + launch_multi_threaded_onyx_program(script_tags[i].getAttribute("src"), script_tags[i].getAttribute("data"), true); + } else { + launch_onyx_program(script_tags[i].getAttribute("src"), true); + } } } }; diff --git a/bin/onyx-thread.js b/bin/onyx-thread.js new file mode 100644 index 00000000..881b2ee6 --- /dev/null +++ b/bin/onyx-thread.js @@ -0,0 +1,38 @@ + +function onyx_decode_text(ptr, len) { + let v = new DataView(self.ONYX_MEMORY.buffer); + + let s = ""; + for (let i = 0; i < len; i++) { + s += String.fromCharCode(v.getUint8(ptr + i)); + } + + return s; +} + + +self.onmessage = function (msg) { + const data = msg.data; + + let import_object = {}; + for (let k of Object.keys(data.imports)) { + import_object[k] = {}; + for (let v of data.imports[k]) { + import_object[k][v] = function(a, b, c, d, e, f, g, h, i, j) { + console.error("ATTEMPT TO CALL MAIN THREAD FUNCTION FROM WORKER THREAD! " + v + "." + k); + } + } + } + + import_object.host.print_str = function(ptr, len) { console.log(onyx_decode_text(ptr, len)); }; + import_object.host.exit = function() { debugger; }; + import_object.onyx = { memory: data.memory }; + + WebAssembly.instantiate(new Uint8Array(data.wasm_bytes), import_object) + .then(function(res) { + self.ONYX_MEMORY = data.memory; + + res.instance.exports._thread_start(data.thread_id, data.funcidx, data.dataptr); + res.instance.exports._thread_exit(data.thread_id); + }); +} \ No newline at end of file diff --git a/core/builtin.onyx b/core/builtin.onyx index f20a4805..7cfa05c1 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -56,6 +56,8 @@ OnyxContext :: struct { logger : Logger = .{ default_logger, null }; assert_handler : (msg: str, site: CallSite) -> void; + + thread_id : i32; } #if runtime.Runtime != runtime.Runtime_Custom { diff --git a/core/runtime/js.onyx b/core/runtime/js.onyx index d3bce96d..c70a4f85 100644 --- a/core/runtime/js.onyx +++ b/core/runtime/js.onyx @@ -4,13 +4,14 @@ package runtime use package core -__output_string :: (s: str) -> u32 #foreign "host" "print_str" --- +__output_string :: (s: str) -> u32 #foreign "host" "print_str" --- __exit :: (status: i32) -> void #foreign "host" "exit" --- // The builtin _start proc. // Sets up everything needed for execution. #export "_start" () { __runtime_initialize(); + context.thread_id = 0; args: [] cstr = .{ null, 0 }; (package main).main(args); @@ -21,10 +22,12 @@ __exit :: (status: i32) -> void #foreign "host" "exit" --- #if Multi_Threading_Enabled { __spawn_thread :: (id: i32, func: (data: rawptr) -> void, data: rawptr) -> bool #foreign "host" "spawn_thread" --- - #export "_thread_start" (func: (data: rawptr) -> void, data: rawptr) { + #export "_thread_start" (id: i32, func: (data: rawptr) -> void, data: rawptr) { __stack_top = raw_alloc(alloc.heap_allocator, 1 << 20); __thread_initialize(); + context.thread_id = id; + func(data); __flush_stdio(); diff --git a/core/runtime/wasi.onyx b/core/runtime/wasi.onyx index be8f7fad..18fa2b5e 100644 --- a/core/runtime/wasi.onyx +++ b/core/runtime/wasi.onyx @@ -22,6 +22,7 @@ __exit :: (status: i32) do proc_exit(status); // Sets up everything needed for execution. #export "_start" () { __runtime_initialize(); + context.thread_id = 0; args : [] cstr; argv_buf_size : Size; diff --git a/modules/js_events/js_events.js b/modules/js_events/js_events.js index 2679c3e2..9a406037 100644 --- a/modules/js_events/js_events.js +++ b/modules/js_events/js_events.js @@ -66,7 +66,7 @@ window.ONYX_MODULES.push({ if (ev.altKey) modifiers |= 0x02; if (ev.metaKey) modifiers |= 0x04; if (ev.shiftKey) modifiers |= 0x08; - + push_event_to_buffer(esp, event_size, 0x05, [ ev.keyCode, modifiers ]); var keyname = ev.code; @@ -141,8 +141,9 @@ window.ONYX_MODULES.push({ request_file(esp, event_size, filename_ptr, filename_len, fileid) { esp /= 4; - var path_memory = new Uint8Array(ONYX_MEMORY.buffer, filename_ptr, filename_len); - var path = new TextDecoder("utf-8").decode(path_memory); + var data_view = new DataView(ONYX_MEMORY.buffer); + var path = ""; + for (var i = 0; i < filename_len; i++) path += String.fromCharCode(data_view.getUint8(filename_ptr + i)); console.log(`Requesting file '${path}'`); fetch(path) diff --git a/modules/webgl2/webgl2.js b/modules/webgl2/webgl2.js index df8936d2..6964651b 100644 --- a/modules/webgl2/webgl2.js +++ b/modules/webgl2/webgl2.js @@ -15,9 +15,7 @@ window.ONYX_MODULES.push({ module_name: "gl", init(name, namelen) { - const decoder = new TextDecoder(); - const str = new Uint8Array(window.ONYX_MEMORY.buffer, name, namelen); - const canvasname = decoder.decode(str); + const canvasname = onyx_decode_text(name, namelen); canvas = document.getElementById(canvasname); if (canvas == null) return 0; @@ -207,9 +205,7 @@ window.ONYX_MODULES.push({ }, // getAttachedShaders() { console.log("NOT IMPLEMENTED!"); }, getAttribLocation(program, name, namelen) { - const decoder = new TextDecoder(); - const str = new Uint8Array(window.ONYX_MEMORY.buffer, name, namelen); - const attribname = decoder.decode(str); + const attribname = onyx_decode_text(name, namelen); return gl.getAttribLocation(programs[program], attribname); }, @@ -224,9 +220,7 @@ window.ONYX_MODULES.push({ getShaderParameter(shader, param) { return gl.getShaderParameter(shaders[shader], param); }, getProgramParameter(program, param) { return gl.getProgramParameter(programs[program], param); }, getUniformLocation(program, name, namelen) { - const decoder = new TextDecoder(); - const str = new Int8Array(window.ONYX_MEMORY.buffer, name, namelen); - const uniname = decoder.decode(str); + const uniname = onyx_decode_text(name, namelen); uniformlocs.push(gl.getUniformLocation(programs[program], uniname)); return uniformlocs.length - 1; @@ -261,9 +255,7 @@ window.ONYX_MODULES.push({ scissor(x, y, width, height) { gl.scissor(x, y, width, height); }, setSize(width, height) { canvas.width = width; canvas.height = height; }, shaderSource(shader, source, sourcelen) { - const decoder = new TextDecoder(); - const str = new Int8Array(window.ONYX_MEMORY.buffer, source, sourcelen); - const sourcedata = decoder.decode(str); + const sourcedata = onyx_decode_text(source, sourcelen); gl.shaderSource(shaders[shader], sourcedata); }, diff --git a/src/wasm_intrinsics.c b/src/wasm_intrinsics.c index 2c0ad877..c563d51e 100644 --- a/src/wasm_intrinsics.c +++ b/src/wasm_intrinsics.c @@ -176,7 +176,7 @@ bad_type: EMIT_FUNC_NO_ARGS(intrinsic_atomic_notify) { bh_arr(WasmInstruction) code = *pcode; - WI(WI_ATOMIC_NOTIFY); + WID(WI_ATOMIC_NOTIFY, ((WasmInstructionData) { 2, 0 })); *pcode = code; }