Skip to content

Commit 3bf2baf

Browse files
committed
Updated the interpreters.md with the how to add a new bytecode specialization steps
1 parent 3929af5 commit 3bf2baf

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

InternalDocs/interpreter.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,62 @@ After the last `DEOPT_IF` has passed, a hit should be recorded with
505505
`STAT_INC(BASE_INSTRUCTION, hit)`.
506506
After an optimization has been deferred in the adaptive instruction,
507507
that 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

510566
Additional resources

0 commit comments

Comments
 (0)