Skip to content

JIT Compiler

Guille Polito edited this page Mar 17, 2022 · 1 revision

Interpreter Optimizations -- Static Type predictions

Pharo's interpreter implements for many of its bytecodes static type predictions. Static typre predictions inline the common case in the bytecode with type checks, for example for integer arithmetic, and falls back to user-defined methods if not suitable. This is the case for example of the add bytecode illustrated below.

Interpreter >> bytecodePrimAdd
  | rcvr arg result |
  rcvr := self internalStackValue: 1.
  arg := self internalStackValue: 0.
  (objectMemory areIntegers: rcvr and: arg) ifTrue: [
    result := (objectMemory integerValueOf: rcvr) + ( objectMemory integerValueOf: arg).
    "Check for overflow"
    (objectMemory isIntegerValue: result) ifTrue: [
      self
        internalPop: 2
        thenPush: (objectMemory integerObjectOf: result). ^ self fetchNextBytecode "success"]].
  "Slow path, message send"
  self normalSend

Such instruction pops two elements from the operand stack, checks if they are both small integers and, if they are, it adds them up. If the result does not overflow, arguments are popped, the result is pushed to the operand stack, and execution continues with the next byte-code. If none of the conditions above hold, the instruction takes a slow path and performs a message send.

Static Type Predictions in the JIT Compiler

Many primitives are statically inlined in the interpreter but not in the compiled code of RegisterAllocatingCogit and StackToRegisterMappingCogit. This is for example the case of the following bytecodes that directly perform message sends in compiled code:

  • bytecodePrimMultiply
  • bytecodePrimDiv
  • bytecodePrimDivide
  • bytecodePrimBitShift

In addition, SimpleStackBasedCogit does not inline the following

  • bytecodePrimBitAnd
  • bytecodePrimBitOr
  • bytecodePrimAdd
  • bytecodePrimSubtract
Clone this wiki locally