OPT-13 Pre-load functions for binary operations to known types#

Background#

CPython will compile complex mathematical operations into opcodes based on operator precedence and stack. All binary operations and inplace operations (Add, subtract, divide, floor divide, power), take 2 arguments, the left and right hand objects.

E.g.

c = a + b

In this example, the value of a and b is loaded (from LOAD_FAST, LOAD_NAME, or LOAD_GLOBAL depending on the scoping) and the reference count is incremented. The binary add operation then calculates a new value and decrements the reference to a and b.

The API for working out the correct magic-method to call is in CPython’s abstract API.

For example, the + operator will call PyNumber_Add(a, b).

This will resolve to:

  1. IF b is a subtype of a and it implements that slot, use that

  2. If a has that slot implemented, use that

  3. If b has that slot implemented, use that

For each of these, the call can return a singleton string, Py_NotImplemented.

There is also another branch for inplace operators, where if the inplace slot is not implemented, it will fall back to the regular slot.

Solution#

If the left-hand and right-hand operands are both known types at compile-time, Pyjion will work out the logic of which slot has preference at compile time and emit a method call to the implementation of that slot.

Gains#

  • Add binary operations where left and right are known types are faster.

Edge-cases#

  • None

Further Enhancements#

  • Determine more types through profiling.

Configuration#

This optimization is enabled at level 1 by default. See Optimizations for help on changing runtime optimization settings.