Historically, 6502s never had a lot of bandwidth available to do actual JIT.
Also, 6502 suffers from being a poor target for high level languages, especially in terms of memory space. With the constrained memory space, that's a bit of a double whammy.
That said, there was BASIC XL on the Atari, back in the day. It had the BEST BASIC statement ever: "FAST".
"FAST" was essentially a post processor. You added FAST as the first line of your program, and it would scan the program and make some calculations that it needs for runtime, but it only does it once rather than during processing.
Specifically, one of the things that it did was that in the original Atari BASIC, when you had something like:
Code:
10 FOR I = 1 to 10
20 PRINT "HELLO"
30 NEXT I
When the interpreter hits the FOR I, it pushes the line number of the statement, then when it hits NEXT I, it grab that line number, 10 in this case, then it searches the program for line 10. It doesn't "know" where line 10 is, so it goes and looks for it. It does this every. single. time. It does this by going to the start of the program, and just traversing the linked list that makes up lines of code, until it finds the appropriate line number.
You can see for a large program, if you have a simple FOR loop in the last lines of the program, that the NEXT has to scan the entirety of the code for each iteration. So, for performance, you would put common code at the top of the program.
The FAST statement calculated those destinations. It would sweep through the tokens and "link" the destinations for all of the FOR/NEXT, GOSUB, and GOTO statements. It was a noticeable improvement in performance.
Avalon Hill had a dungeon game, Telengard, for the Atari. We managed to break in to it and added the FAST statement. The game was borderline unplayable after that. We had to put in strategic delay loops (like FOR I = 1 TO 5000 : NEXT I) to make it work for us.
The FAST statement took a noticeable amount of time to run, there was a distinct pause at the beginning of the program.
I think a better approach is to do something like FAST, a static analysis phase that may be able to make some assertions and other computations, but not necessarily creating binary code. Just a phase that tries to eliminate lookups and indirection. Try and resolve as many of those as possible.