After you take all of these factors into account, and look at where the bottlenecks in most programs arise are not a even in the raw manipulation of data structures but:
- waiting for disk / network / bus IO
- waiting for DMA transfers to update video, audio, etc.
- polling for system events, keyboard, mouse, and touchpad
- waiting for a timer to fire, a vertical sync, a user
You then realize most tasks can be completed equally fast by a high or low level language. About 15 years ago, I had this epiphany and produced bindings for the Simple DirectMedia Layer for Perl (and python too but I handed what code I had to Pete to add to PyGame...), and it is as true today as it was 15 years ago; very little of your code is HLL. Most HLL code, too, isn't so high level or dynamic to suffer from JIT optimizations.
- Core objects in a hyper-static environment (no mutation but overrideable via subcontext overlays)
- Integer, Float, Double, Char, Short, Pointer, Register, Aaaqaaqqqqaaaqaaaqainterface for these machine oriented types.
- An ABI for interacting with low level JIT generated code, suitable for use with other languages.
- A non-C style stack, separating code flow storage (return stack) from block local storage.
- Blocks as anonymous function objects, with all locals bound to the block function as properties.
- A message passing cross process memory Binary JSON API for a shared-nothing memory transfer for data and code
There are security concerns with the last of these, in that any 3rd party code can in theory trigger that behavior, but segmenting the memory model merely helps prevent the JIT from breaking the JIT while JITTING. Since 3rd party code may be compiled into a separate memory space, keeping a separation of concerns between memory regions becomes critical to ensuring safety. Message passing and fundamental types allows for passing data across segments, avoiding taint problems and privilege escalation attack vectors.