@@ -505,6 +505,62 @@ After the last `DEOPT_IF` has passed, a hit should be recorded with
505505` STAT_INC(BASE_INSTRUCTION, hit) ` .
506506After an optimization has been deferred in the adaptive instruction,
507507that should be recorded with ` STAT_INC(BASE_INSTRUCTION, deferred) ` .
508+ ## How to add a new bytecode specialization
509+
510+ Assuming you found an instruction that serves as a good specialization candidate.
511+ Let's use the example of [ ` CONTAINS_OP ` ] ( ../Doc/library/dis.rst#contains_op ) :
512+
513+ 1 . Update below in [ Python/bytecodes.c] ( ../Python/bytecodes.c )
514+
515+ - Convert ` CONTAINS_OP ` to a micro-operation (uop) by renaming
516+ it to ` _CONTAINS_OP ` and changing the instruction definition
517+ from ` inst ` to ` op ` .
518+
519+ ``` c
520+ // Before
521+ inst (CONTAINS_OP, ...);
522+
523+ // After
524+ op(_CONTAINS_OP, ...);
525+ ```
526+
527+ - Add a uop that calls the specializing function `_SPECIALIZE_CONTAINS_OP`.
528+ For example.
529+
530+ ```c
531+ specializing op(_SPECIALIZE_CONTAINS_OP, (counter/1, left, right -- left, right)) {
532+ #if ENABLE_SPECIALIZATION
533+ if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
534+ next_instr = this_instr;
535+ _Py_Specialize_ContainsOp(right, next_instr);
536+ DISPATCH_SAME_OPARG();
537+ }
538+ STAT_INC(CONTAINS_OP, deferred);
539+ DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
540+ #endif /* ENABLE_SPECIALIZATION */
541+ }
542+ ```
543+
544+ - The original ` CONTAINS_OP ` is now a new macro consisting of
545+ ` _SPECIALIZE_CONTAINS_OP ` and ` _CONTAINS_OP ` .
546+
547+ 2 . Define the cache structure in [ Include/internal/pycore_code.h] ( ../Include/internal/pycore_code.h ) ,
548+ at the very least, a 16-bit counter is needed.
549+
550+ ```c
551+ typedef struct {
552+ uint16_t counter;
553+ } _PyContainsOpCache;
554+ ```
555+
556+ 3 . Write the specializing function itself in [ Python/specialize.c ] ( ../Python/specialize.c ) .
557+ Refer to any other function in that file for the format.
558+ 4 . Remember to update operation stats by calling add_stat_dict in
559+ [ Python/specialize.c ] ( ../Python/specialize.c ) .
560+ 5 . Add the cache layout in [ Lib/opcode.py] ( ../Lib/opcode.py ) so that Python's
561+ dis module will know how to represent it properly.
562+ 6 . Bump magic number in [ Include/core/pycore_magic_number.h] ( ../Include/internal/pycore_magic_number.h ) .
563+ 7 . Run `` make regen-all `` on ` *nix ` or ` build.bat --regen ` on Windows.
508564
509565
510566Additional resources
0 commit comments