Class HostCompilerDirectives

java.lang.Object
com.oracle.truffle.api.HostCompilerDirectives

public final class HostCompilerDirectives extends Object
Directives that influence the optimizations of the host compiler. These operations affect how the Truffle interpreter is itself compiled.
Since:
21.0
  • Method Details

    • inInterpreterFastPath

      public static boolean inInterpreterFastPath()
      Indicates whether a branch is executed only in the interpreter. In addition to CompilerDirectives.inInterpreter(), this method instructs the host compiler to treat the positive branch as frequently executed code of high importance. Branches protected by this method should be treated as if they were runtime compiled code paths, even if they may never actually be compiled. This means that slow-paths must be protected using either CompilerDirectives.transferToInterpreterAndInvalidate() or CompilerDirectives.TruffleBoundary.

      A common use case for this directive is in counting condition profiles, where counters must be protected by CompilerDirectives.inInterpreter() but also need to be optimized as fast-path by the host compiler. Without this directive, the host compiler may treat the branch as a slow-path branch.

      Returns:
      true if executed in the interpreter, false in compiled code.
      Since:
      23.0
    • markThreadedSwitch

      public static int markThreadedSwitch(int input)
      Marks a switch statement within a loop as a candidate for threaded switch optimization. Threaded switch replicates the switch statement at the end of each case, improving branch prediction at the processor level. Usage example:
      while (cond) {
        input = inlinedNextOpcode();
        switch (markThreadedSwitch(input)) {
          case op1: { body1; }
          case op2: { body2; }
        }
      }
      
      The compiler recognizes the code blocks from the loop header up to the switch and duplicates them into each case that continues the while loop. This effectively transforms the structure as follows:
      if (cond) {
        input = inlinedNextOpcode();
        switch (markThreadedSwitch(input)) {
          case op1: {
              body1;
              if (cond) {
                input = inlinedNextOpcode();
                switch (markThreadedSwitch(input)) // go to matching case of outer switch
              }
          }
          case op2: {
              body2;
              if (cond) {
                input = inlinedNextOpcode();
                switch (markThreadedSwitch(input)) // go to matching case of outer switch
              }
          }
        }
      }
      
      When additional statements follow the switch block within a loop, the compiler may trigger an optimization to duplicate these statements into each case block. If this duplication does not occur, the compiler can still identify the loop as a candidate for threaded switch optimization and apply relevant optimizations to minimize overhead in the loop header, such as postponing register spilling from the loop header to cases with actual register pressure, even at the cost of code bloat. However, due to the presence of these tail statements, the loop has only one back edge, which effectively disables threading. The compiler may also reject candidates for threaded switch optimization if the identified code blocks, after inlining, contain complex control flow or operations beyond memory reads. To log decisions related to threaded switch optimization, use the Graal option TraceThreadedSwitchOptimization.
      Since:
      25.1