As a smart contract executes, the most frequently executed execution paths are identified through a combination of offline and online instrumentation. The offline instrumentation (inserted by the native code generator) identifies frequently executed loop regions in the code. When a hot loop region is detected at runtime, a runtime instrumentation library instruments the executing native code to identify frequently executed paths within that region. Once hot paths are identified, we duplicate the original LLVM code into a trace, perform LLVM optimizations on it, and the regenerate native code into a software-managed trace cache. We then insert branches between the original code and the new native code. The strategy described here is powerful because it combines the following three characteristics:
• Native code generation can be performed ahead-of-time using sophisticated algorithms to generate high-performance code.
•The native code generator and the runtime optimizer can work together since they are both parts of the LLVM framework, allowing the runtime optimizer to exploit support from the code generator (e.g., for instrumentation and simplifying transformations).
• The runtime optimizer can use high-level information from the LLVM representation to perform sophisticated runtime optimizations.