It’s pretty hard to make things like math faster for real world use cases in a bytecode interpreter.
i ran a quick experiment where instead of doing boxing the way its done in the beam currently, i used a different boxing (NaN strategy and there was a 10x speedup
Java and Javascript run times do really well at that.
It's a JIT nowadays. Admittedly an extremely simple one, to minimize compile times and maintenance overhead.
You can get substantial performance improvements by using guards though. See what Wings3D does with is_float() everywhere in hot numeric-heavy code.