What we haven't had before are architecture-independent executables that can be compiled into from a large number of programming languages.
So how many languages do they need to be to be considered large?
Don't take me wrong, I love those bytecode environments, including Web Assembly.
I just don't think Web Assembly is that much different from other ones, other than politics.
Look for IBM redbooks on IBM i and IBM z language environments.
How was the performance of the old mainframe formats?
The kernel has a JIT and they are converted into native code at installation time, or when an operator decides to retrigger the operation.
In a way, Android (5 - 7), iOS bitcode and WP 8.x MDIL follow similar ideas.
And something that I forgot, MSIL also has support for C and C++, hence why all C# 7.x performance improvements don't require any runtime change, just exposing features that C and C++ already make use of on MSIL.
The mainframe ones, are just like any other OS, code gets generated at installation time, then they are OS processes just like any other.
Java and MSIL depend on how they get used.
Both have bytecode verifiers, and multiple ways to deploy.
Either as single runtime, where strong typing plays the role of sandboxing, or as multiple processes/containers.
Just to use .NET as example, not going to make an exhaustive list.
.NET Micro Framework deployed on Netduino, the runtime is the OS, only strong typing takes place.
.NET Framework on Windows, and .NET Core on Windows/Mac/Linux, each CLR instance gets their own OS process, which might be additionally wrapped into an OS container.
.NET Core on UWP, applications run as separate sandboxed process using the UWP sandbox model.
Xamarin on iOS runs with the iOS sandbox model, after AOT compiling for deployment.
Xamarin on Android, runs with the Android sandbox model where binary code gets dynamically loaded into ART instance, sandboxed via SELinux and Linux container mechanisms.
And regarding security, Web Assembly still fails short of preventing memory corruption inside of the loaded module.
I was hoping pointers would be tagged, but that doesn't seem to be part of the design goals.
Then we have JVM, MSIL and DEX.
What would wasm bring that isn't already done?