This is a really cool project. I'm currently working on a tutorial on how to use it with Buildroot Linux and Tiny C Compiler, where I now have tcc in the browser. v86 is unable to debug with gdb (v8, 10.2, 11.2) (though it works if you use gdb to intercept gdbserver from another device), so I'm experimenting with strace, and have written a basic streaming parser for read/writev syscalls. What strace does is intercept printf/puts/gets/readline etc and by parsing its output, one can create a simple but highly stylable "console" in html that prints and reads text input. No support for TUI's, this is where xterm.js shines.
Compilation in tcc with a file of ~300 lines of code, linking to a library, takes roughly 50 ms. Compiling the entire libharu library takes 23 s. It's ~120.000 SLOC but where most is long arrays of encoding data.
I have used musl as toolchain, but will look into uclibc because of a weird problem: printf without \n in the end doesn't display the text before something creates a newline. And that could be readline, in which case you'd get:
Sounds like you have a problem with "line buffering". You can normally configure libc libraries at compile time how you want them to behave in that respect.
If the title is true, that would be a huge achievement. Unfortunately, the page says nothing about how it works and nothing about the speed advantage you get.
For my emulator jor1k [1] I tried something similar years ago [2]. However I haven't continued on this topic because of priority shifts. But the potential speed advantages are astonishing. My proof of context reached more than 1 billion emulated machine instructions per second.
> If the title is true, that would be a huge achievement.
Fundamentally it's "just" a JIT that compiles to WASM. It's a ton of effort to build something like that, but I think fundamentally it's not an impossible undertaking.
It is definitely not "just" a JIT compiler. For example, you can't just copy QEMU's JIT solution and hope that it works. So I'm interested in your solution.
For example, do you compile each code block (from jump to jump instruction) into a separate WebAssembly module?
If yes, then I wonder how many millions of small WebAssembly modules a browser can handle, how well the foreign function interface between JavaScript and WebAssembly actually performs and how much of the time the Browser JIT spends in compiling your generated code.
How do you handle machine code manipulation during execution for example? How do you mark already compiled memory pages as dirty.
I will definitely look at your code :-)
> WRT speed advantage: compared to what?
The speed advantage between interpreted and JIT compiled execution.
I'm not entirely sure that the browser runtimes are suited for this since I watched a friend demo-ing V86 and the amount of crashes with modern OSs just seemed to make it a toy (though I might be proven wrong).
One plausible guess I have is that they might be running out of memory since the browser runtimes are expecting the WASM code to be long lived whilst a emulator JIT by nature should be able to adapt to rapidly changing code and blows out of memory before things are cleaned up.
Presumably the crashes are happening because the instruction set implemented by the JIT is on Pentium II level and so encountering modern X86 instructions makes it fail. I am not familiar with the linked project but there is no real reason why you could not emulate a 32bit Intel perfectly in WASM. For 64bit I'm not sure if wasm64 wouldn't be required.
I think there are browser-level crashes too because you're using the WASM JIT-compiler in ways it hasn't been thoroughly tested for.
The Chromium team is pretty receptive to patches though, so for a big project like this it doesn't seem unreasonable to just patch the browser to perform well enough for your use case, and then upstream the patch so everyone has it within a few months when you're ready to launch your product.
> My proof of context reached more than 1 billion emulated machine instructions per second.
Which are the calculations about the billion instructions per second? Emulating instructions, even on a relatively simple system, requires a lot of support: decoding, cpu state, memory access/mapping, buses - and this doesn't even include the instructions themselves.
The calculations is based on the machine instructions, the compiled code by the JIT is able to perform on average. In this case a simple 32-Bit machine with OpenRISC architecture.
For the proof of concept, that was the compiled code in [1]. Just look for code snipplets such as "cycles = cyles - xxxx|0", that does the calculation during runtime.
So, my calculation does not include decoding, but CPU state, memory access/mapping, buses.
This is an awesome project! I've integrated it into my Desktop Environment in the browser so that you can drag on ISO/IMG files and run them directly in the emulator. It also automatically saves states on close into /Users/Public/Snapshots. For networking I am using the same WebSocket proxy that v86 uses.
I never actually played with Windows 1.0, but wanted to see what the concept was about.
It's interesting to see that the window sizes are automatic. There are no real windows.
Also, it's kind of fun to see that there's no "Maximize", but "Zoom", just like macOS.. And double-clicking the titlebar actually minimizes the application to an icon, just like macOS.
Windows 1.0 is more similar to Norton Commander and DOS Shell (built-in to later DOS versions), as well as the Borland Turbovision products, in that it's something between a textual and graphical "shell" that you can manipulate files and run other programs off of.
At that time, it was nowhere close to being called an OS. It was a collection of GUI-ish tools for DOS. This started to change with Windows 3. That one still required DOS to function, but by that time it was clear DOS was the past on the PC and Windows (in some form) was the way forward.
Well not completely as I see it. Yes functionality is limited, but I was able to execute multiple applications and multiple instances of them. I could also switch between then.
With Norton commander you could only spawn one process from NC. NC itself had quite a lot for built in tools (viewer, editor, comparison, 2 file panes).
So I’d call windows 1.0 more an OS in terms of process “management”, UI, etc. No hardware layer of course.
I tried WebVM but it feels a bit slow. Do you think performance could be improved by supporting native wasm binaries? Something like wasm-*-linux compilation target.
Compilation in tcc with a file of ~300 lines of code, linking to a library, takes roughly 50 ms. Compiling the entire libharu library takes 23 s. It's ~120.000 SLOC but where most is long arrays of encoding data.
I have used musl as toolchain, but will look into uclibc because of a weird problem: printf without \n in the end doesn't display the text before something creates a newline. And that could be readline, in which case you'd get:
At least I think this is because of musl where there's a problem with the syscall writev: https://www.openwall.com/lists/musl/2013/05/05/9.Really looking forward to get the tutorial out and I hope it'll be with the strace based console!