Taking many closures that are long-lived can cause a huge amount of work marking inter-generational roots. Analyze the problem, and find a solution.
Things are already notably better here, however there is ongoing work to further improve the situation.
Work is currently in progress to improve the quality of code generated by the JIT compiler.
Optimize away unrequired native reference takes and dereferences, including over inlining boundaries.
The not-actually-big-integer case can be inlined into the generated machine code, and various indirections can be eliminated.
MoarVM currently uses an event loop that gets started and stopped for each synchronous operation. Doing these operations without the overhead of a full event loop would surely be beneficial.
At the moment, the specializer struggles to inline or even lift guards in a number of situations when it easily could. This will involve some improvements to the takeclosure/capturelex API, so it's useful to Rakudo to use directly (rather than the more indirect approach taken today).
Implement escape analysis at bytecode specialization time.
Augment our existing callframe-level JIT, which already supports inlining, with a trace JIT. The trace JIT would be used for loops, replacing the current use of OSR (perhaps OSR remains as a fallback).