MCPcopy Index your code
hub / github.com/RustPython/RustPython / instrument_code

Function instrument_code

crates/vm/src/stdlib/sys/monitoring.rs:237–510  ·  view source on GitHub ↗

Rewrite a code object's bytecode in-place with layered instrumentation. Three layers (outermost first): 1. INSTRUMENTED_LINE — wraps line-start instructions (stores original in side-table) 2. INSTRUMENTED_INSTRUCTION — wraps all traceable instructions (stores original in side-table) 3. Regular INSTRUMENTED_* — direct 1:1 opcode swap (no side-table needed) De-instrumentation peels layers in rever

(code: &PyCode, events: u32)

Source from the content-addressed store, hash-verified

235///
236/// De-instrumentation peels layers in reverse order.
237pub fn instrument_code(code: &PyCode, events: u32) {
238 use rustpython_compiler_core::bytecode::{self, Instruction};
239
240 let len = code.code.instructions.len();
241 let mut monitoring_data = code.monitoring_data.lock();
242
243 // === Phase 1-3: De-instrument all layers (outermost first) ===
244
245 // Phase 1: Remove INSTRUMENTED_LINE → restore from side-table
246 if let Some(data) = monitoring_data.as_mut() {
247 for i in 0..len {
248 if data.line_opcodes[i] != 0 {
249 let original = Instruction::try_from(data.line_opcodes[i])
250 .expect("invalid opcode in line side-table");
251 unsafe {
252 code.code.instructions.replace_op(i, original);
253 }
254 data.line_opcodes[i] = 0;
255 }
256 }
257 }
258
259 // Phase 2: Remove INSTRUMENTED_INSTRUCTION → restore from side-table
260 if let Some(data) = monitoring_data.as_mut() {
261 for i in 0..len {
262 if data.per_instruction_opcodes[i] != 0 {
263 let original = Instruction::try_from(data.per_instruction_opcodes[i])
264 .expect("invalid opcode in instruction side-table");
265 unsafe {
266 code.code.instructions.replace_op(i, original);
267 }
268 data.per_instruction_opcodes[i] = 0;
269 }
270 }
271 }
272
273 // Phase 3: Remove regular INSTRUMENTED_* and specialized opcodes → restore base opcodes.
274 // Also clear all CACHE entries so specialization starts fresh.
275 {
276 let mut i = 0;
277 while i < len {
278 let op = code.code.instructions[i].op;
279 let base_op = op.deoptimize();
280 if u8::from(base_op) != u8::from(op) {
281 unsafe {
282 code.code.instructions.replace_op(i, base_op);
283 }
284 }
285 let caches = base_op.cache_entries();
286 // Zero all CACHE entries (the op+arg bytes may have been overwritten
287 // by specialization with arbitrary data like pointers).
288 for c in 1..=caches {
289 if i + c < len {
290 unsafe {
291 code.code.instructions.write_cache_u16(i + c, 0);
292 }
293 }
294 }

Callers 3

execute_instructionMethod · 0.85
execute_instrumentedMethod · 0.85
update_events_maskFunction · 0.85

Calls 15

build_no_location_maskFunction · 0.85
decode_exception_tableFunction · 0.85
replace_opMethod · 0.80
deoptimizeMethod · 0.80
cache_entriesMethod · 0.80
write_cache_u16Method · 0.80
to_instrumentedMethod · 0.80
SomeClass · 0.50
lenMethod · 0.45
lockMethod · 0.45
as_mutMethod · 0.45
is_noneMethod · 0.45

Tested by

no test coverage detected