Saying eval is just confusing the concept with the implementation. There's no evidence that metaprogramming is "bad" unless you are ready to define "bad". Might as well say pointers are "bad" in the same vein.
Eval'ing during macroexpansion in Gambit Scheme is the basis for my book, http://billsix.github.io/bug.html#_computation_at_compile_ti...
It allows me to make a compile-time unit test framework in 7 lines of code
I can think of a few good use cases (though outside the context of JIT). Consider something like Jinja where you can put python code in your template - we've used this to generate C++ source files from JSON metadata in our embedded systems products. In this case it's pretty safe because both the producer and consumer of the eval is the same person.
In another life I did PHP shells. PHP (which has a weird relationship with JIT) had so many ways to use eval, without actually typing eval. One of the weird ways that was only removed in PHP 7 was the preg_replace function, with the e flag; which evals any php expression, outside the scope of the function.
My point is that if there is eval used in code; it either is meant for temporary use (because devs are lazy,) or the code needs to be done differently to support the desired outcome.