From f4d3c61f36776db6847834ec3577d7a53a5757d8 Mon Sep 17 00:00:00 2001 From: ivonastojanovic <80911834+ivonastojanovic@users.noreply.github.com> Date: Mon, 30 Mar 2026 12:31:06 +0100 Subject: [PATCH 1/6] gh-138122: Add differential flame graph (#145785) Differential flame graphs compare two profiling runs and highlight where performance has changed. This makes it easier to detect regressions introduced by code changes and to verify that optimizations have the intended effect. The visualization renders the current profile with frame widths representing current time consumption. Color is then applied to show the difference relative to the baseline profile: red gradients indicate regressions, while blue gradients indicate improvements. Some call paths may disappear entirely between profiles. These are referred to as elided stacks and occur when optimizations remove code paths or when certain branches stop executing. When elided stacks are present, an "Elided" toggle is displayed, allowing the user to switch between the main differential view and a view showing only the removed paths. Co-authored-by: Pablo Galindo Salgado --- Doc/library/profiling.sampling.rst | 45 ++ .../_flamegraph_assets/flamegraph.css | 82 ++- .../sampling/_flamegraph_assets/flamegraph.js | 285 +++++++--- .../flamegraph_template.html | 81 ++- Lib/profiling/sampling/cli.py | 52 +- Lib/profiling/sampling/stack_collector.py | 280 +++++++++- .../test_sampling_profiler/mocks.py | 19 + .../test_sampling_profiler/test_collectors.py | 500 +++++++++++++++++- ...-03-10-19-50-59.gh-issue-138122.CsoBEo.rst | 4 + 9 files changed, 1244 insertions(+), 104 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-10-19-50-59.gh-issue-138122.CsoBEo.rst diff --git a/Doc/library/profiling.sampling.rst b/Doc/library/profiling.sampling.rst index d2b7d9669ab07e..a6ce2f30eadb2c 100644 --- a/Doc/library/profiling.sampling.rst +++ b/Doc/library/profiling.sampling.rst @@ -1003,6 +1003,47 @@ at the top indicate functions that consume significant time either directly or through their callees. +Differential flame graphs +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Differential flame graphs compare two profiling runs to highlight where +performance changed. This helps identify regressions introduced by code changes +and validate that optimizations achieved their intended effect:: + + # Capture baseline profile + python -m profiling.sampling run --binary -o baseline.bin script.py + + # After modifying code, generate differential flamegraph + python -m profiling.sampling run --diff-flamegraph baseline.bin -o diff.html script.py + +The visualization draws the current profile with frame widths showing current +time consumption, then applies color to indicate how each function changed +relative to the baseline. + +**Color coding**: + +- **Red**: Functions consuming more time (regressions). Lighter shades indicate + modest increases, while darker shades show severe regressions. + +- **Blue**: Functions consuming less time (improvements). Lighter shades for + modest reductions, darker shades for significant speedups. + +- **Gray**: Minimal or no change. + +- **Purple**: New functions not present in the baseline. + +Frame colors indicate changes in **direct time** (time when the function was at +the top of the stack, actively executing), not cumulative time including callees. +Hovering over a frame shows comparison details including baseline time, current +time, and the percentage change. + +Some call paths may disappear entirely between profiles. These are called +**elided stacks** and occur when optimizations eliminate code paths or certain +branches stop executing. If elided stacks are present, an elided toggle appears +allowing you to switch between the main differential view and an elided-only +view that shows just the removed paths (colored purple). + + Gecko format ------------ @@ -1488,6 +1529,10 @@ Output options Generate self-contained HTML flame graph. +.. option:: --diff-flamegraph + + Generate differential flamegraph comparing to a baseline binary profile. + .. option:: --gecko Generate Gecko JSON format for Firefox Profiler. diff --git a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.css b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.css index 24e67bedee5242..c4da169d15de88 100644 --- a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.css +++ b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.css @@ -5,6 +5,46 @@ This file extends the shared foundation with flamegraph-specific styles. ========================================================================== */ +/* -------------------------------------------------------------------------- + Differential Flamegraph + -------------------------------------------------------------------------- */ + +:root { + /* Regression colors */ + --diff-regression-deep: #d32f2f; + --diff-regression-medium: #e57373; + --diff-regression-light: #ef9a9a; + --diff-regression-verylight: #ffcdd2; + + /* Improvement colors */ + --diff-improvement-deep: #1976d2; + --diff-improvement-medium: #42a5f5; + --diff-improvement-light: #64b5f6; + --diff-improvement-verylight: #90caf9; + + /* Other differential colors */ + --diff-neutral: #bdbdbd; + --diff-new: #9575cd; + --diff-elided: #b39ddb; +} + +/* Dark mode differential colors - adjusted for contrast against dark backgrounds */ +[data-theme="dark"] { + --diff-regression-deep: #ef5350; + --diff-regression-medium: #e57373; + --diff-regression-light: #ef9a9a; + --diff-regression-verylight: #ffcdd2; + + --diff-improvement-deep: #42a5f5; + --diff-improvement-medium: #64b5f6; + --diff-improvement-light: #90caf9; + --diff-improvement-verylight: #bbdefb; + + --diff-neutral: #757575; + --diff-new: #b39ddb; + --diff-elided: #ce93d8; +} + /* -------------------------------------------------------------------------- Layout Overrides (Flamegraph-specific) -------------------------------------------------------------------------- */ @@ -277,7 +317,9 @@ body.resizing-sidebar { /* View Mode Section */ .view-mode-section .section-content { display: flex; - justify-content: center; + flex-direction: column; + gap: 10px; + align-items: center; } /* Collapsible sections */ @@ -815,6 +857,41 @@ body.resizing-sidebar { color: var(--accent); } +.tooltip-diff { + margin-top: 12px; + padding-top: 12px; + border-top: 1px solid var(--border); +} + +.tooltip-diff-title { + font-size: 11px; + font-weight: 600; + color: var(--accent); + margin-bottom: 8px; +} + +.tooltip-diff-row { + display: grid; + grid-template-columns: auto 1fr; + gap: 4px 14px; + font-size: 12px; + margin-bottom: 4px; +} + +.tooltip-diff-row.regression .tooltip-stat-value { + color: var(--diff-regression-deep); + font-weight: 700; +} + +.tooltip-diff-row.improvement .tooltip-stat-value { + color: var(--diff-improvement-deep); + font-weight: 700; +} + +.tooltip-diff-row.neutral .tooltip-stat-value { + color: var(--text-secondary); +} + .tooltip-source { margin-top: 10px; padding-top: 10px; @@ -989,7 +1066,8 @@ body.resizing-sidebar { Flamegraph-Specific Toggle Override -------------------------------------------------------------------------- */ -#toggle-invert .toggle-track.on { +#toggle-invert .toggle-track.on, +#toggle-elided .toggle-track.on { background: #8e44ad; border-color: #8e44ad; box-shadow: 0 0 8px rgba(142, 68, 173, 0.3); diff --git a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js index a2b21da2970064..166c03d03fbe5b 100644 --- a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js +++ b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js @@ -40,44 +40,74 @@ function getOpcodeInfo(opcode) { // String Resolution // ============================================================================ -function resolveString(index) { +function resolveString(index, table = stringTable) { if (index === null || index === undefined) { return null; } - if (typeof index === 'number' && index >= 0 && index < stringTable.length) { - return stringTable[index]; + if (typeof index === 'number' && index >= 0 && index < table.length) { + return table[index]; } return String(index); } -function resolveStringIndices(node) { +function resolveStringIndices(node, table) { if (!node) return node; const resolved = { ...node }; if (typeof resolved.name === 'number') { - resolved.name = resolveString(resolved.name); + resolved.name = resolveString(resolved.name, table); } if (typeof resolved.filename === 'number') { - resolved.filename = resolveString(resolved.filename); + resolved.filename = resolveString(resolved.filename, table); } if (typeof resolved.funcname === 'number') { - resolved.funcname = resolveString(resolved.funcname); + resolved.funcname = resolveString(resolved.funcname, table); } if (Array.isArray(resolved.source)) { resolved.source = resolved.source.map(index => - typeof index === 'number' ? resolveString(index) : index + typeof index === 'number' ? resolveString(index, table) : index ); } if (Array.isArray(resolved.children)) { - resolved.children = resolved.children.map(child => resolveStringIndices(child)); + resolved.children = resolved.children.map(child => resolveStringIndices(child, table)); } return resolved; } +function selectFlamegraphData() { + const baseData = isShowingElided ? elidedFlamegraphData : normalData; + + if (!isInverted) { + return baseData; + } + + if (isShowingElided) { + if (!invertedElidedData) { + invertedElidedData = generateInvertedFlamegraph(baseData); + } + return invertedElidedData; + } + + if (!invertedData) { + invertedData = generateInvertedFlamegraph(baseData); + } + return invertedData; +} + +function updateFlamegraphView() { + const selectedData = selectFlamegraphData(); + const selectedThreadId = currentThreadFilter !== 'all' ? parseInt(currentThreadFilter, 10) : null; + const filteredData = selectedThreadId !== null ? filterDataByThread(selectedData, selectedThreadId) : selectedData; + const tooltip = createPythonTooltip(filteredData); + const chart = createFlamegraph(tooltip, filteredData.value, filteredData); + renderFlamegraph(chart, filteredData); + populateThreadStats(selectedData, selectedThreadId); +} + // ============================================================================ // Theme & UI Controls // ============================================================================ @@ -87,10 +117,7 @@ function toggleTheme() { // Re-render flamegraph with new theme colors if (window.flamegraphData && normalData) { - const currentData = isInverted ? invertedData : normalData; - const tooltip = createPythonTooltip(currentData); - const chart = createFlamegraph(tooltip, currentData.value); - renderFlamegraph(chart, window.flamegraphData); + updateFlamegraphView(); } } @@ -342,6 +369,34 @@ function createPythonTooltip(data) { const fileLocationHTML = isSpecialFrame ? "" : `
${filename}${d.data.lineno ? ":" + d.data.lineno : ""}
`; + // Differential stats section + let diffSection = ""; + if (d.data.diff !== undefined && d.data.baseline !== undefined) { + const baselineSelf = (d.data.baseline / 1000).toFixed(2); + const currentSelf = ((d.data.self_time || 0) / 1000).toFixed(2); + const diffMs = (d.data.diff / 1000).toFixed(2); + const diffPct = d.data.diff_pct; + const sign = d.data.diff >= 0 ? "+" : ""; + const diffClass = d.data.diff > 0 ? "regression" : (d.data.diff < 0 ? "improvement" : "neutral"); + + diffSection = ` +
+
Self-Time Comparison:
+
+ Baseline Self: + ${baselineSelf} ms +
+
+ Current Self: + ${currentSelf} ms +
+
+ Difference: + ${sign}${diffMs} ms (${sign}${diffPct.toFixed(1)}%) +
+
`; + } + const tooltipHTML = `
${funcname}
@@ -364,6 +419,7 @@ function createPythonTooltip(data) { ${childCount} ` : ''}
+ ${diffSection} ${sourceSection} ${opcodeSection}
@@ -458,11 +514,64 @@ function getHeatColors() { return colors; } -function createFlamegraph(tooltip, rootValue) { +function getDiffColors() { + const style = getComputedStyle(document.documentElement); + return { + elided: style.getPropertyValue('--diff-elided').trim(), + new: style.getPropertyValue('--diff-new').trim(), + neutral: style.getPropertyValue('--diff-neutral').trim(), + regressionDeep: style.getPropertyValue('--diff-regression-deep').trim(), + regressionMedium: style.getPropertyValue('--diff-regression-medium').trim(), + regressionLight: style.getPropertyValue('--diff-regression-light').trim(), + regressionVerylight: style.getPropertyValue('--diff-regression-verylight').trim(), + improvementDeep: style.getPropertyValue('--diff-improvement-deep').trim(), + improvementMedium: style.getPropertyValue('--diff-improvement-medium').trim(), + improvementLight: style.getPropertyValue('--diff-improvement-light').trim(), + improvementVerylight: style.getPropertyValue('--diff-improvement-verylight').trim(), + }; +} + +function getDiffColorForNode(node, diffColors) { + if (isShowingElided) { + return diffColors.elided; + } + + const diff_pct = node.data.diff_pct || 0; + const diff_samples = node.data.diff || 0; + const self_time = node.data.self_time || 0; + + if (diff_pct === 100 && self_time > 0 && Math.abs(diff_samples - self_time) < 0.1) { + return diffColors.new; + } + + // Neutral zone: small percentage change + if (Math.abs(diff_pct) < 15) { + return diffColors.neutral; + } + + // Regression (red scale) + if (diff_pct > 0) { + if (diff_pct >= 100) return diffColors.regressionDeep; + if (diff_pct > 50) return diffColors.regressionMedium; + if (diff_pct > 30) return diffColors.regressionLight; + return diffColors.regressionVerylight; + } + + // Improvement (blue scale) + if (diff_pct <= -100) return diffColors.improvementDeep; + if (diff_pct < -50) return diffColors.improvementMedium; + if (diff_pct < -30) return diffColors.improvementLight; + return diffColors.improvementVerylight; +} + +function createFlamegraph(tooltip, rootValue, data) { const chartArea = document.querySelector('.chart-area'); const width = chartArea ? chartArea.clientWidth - 32 : window.innerWidth - 320; const heatColors = getHeatColors(); + const isDifferential = data && data.stats && data.stats.is_differential; + const diffColors = isDifferential ? getDiffColors() : null; + let chart = flamegraph() .width(width) .cellHeight(20) @@ -471,9 +580,12 @@ function createFlamegraph(tooltip, rootValue) { .tooltip(tooltip) .inverted(true) .setColorMapper(function (d) { - // Root node should be transparent if (d.depth === 0) return 'transparent'; + if (isDifferential) { + return getDiffColorForNode(d, diffColors); + } + const percentage = d.data.value / rootValue; const level = getHeatLevel(percentage); return heatColors[level]; @@ -857,6 +969,37 @@ function populateProfileSummary(data) { } } +// ============================================================================ +// Elided Stacks (Differential) +// ============================================================================ + +let elidedFlamegraphData = null; +let invertedElidedData = null; +let isShowingElided = false; + +function setupElidedToggle(data) { + const stats = data.stats || {}; + const elidedCount = stats.elided_count || 0; + const elidedFlamegraph = stats.elided_flamegraph; + + if (!elidedCount || !elidedFlamegraph) { + return; + } + + elidedFlamegraphData = resolveStringIndices(elidedFlamegraph, elidedFlamegraph.strings); + + const toggleElided = document.getElementById('toggle-elided'); + if (toggleElided) { + toggleElided.style.display = 'flex'; + + toggleElided.onclick = function() { + isShowingElided = !isShowingElided; + updateToggleUI('toggle-elided', isShowingElided); + updateFlamegraphView(); + }; + } +} + // ============================================================================ // Hotspot Stats // ============================================================================ @@ -868,6 +1011,9 @@ function populateStats(data) { // Populate thread statistics if available populateThreadStats(data); + // Setup elided stacks toggle if this is a differential flamegraph + setupElidedToggle(data); + // For hotspots: use normal (non-inverted) tree structure, but respect thread filtering. // In inverted view, the tree structure changes but the hottest functions remain the same. // However, if a thread filter is active, we need to show that thread's hotspots. @@ -1040,28 +1186,8 @@ function filterByThread() { const selectedThread = threadFilter.value; currentThreadFilter = selectedThread; - const baseData = isInverted ? invertedData : normalData; - let filteredData; - let selectedThreadId = null; - - if (selectedThread === 'all') { - filteredData = baseData; - } else { - selectedThreadId = parseInt(selectedThread, 10); - filteredData = filterDataByThread(baseData, selectedThreadId); - - if (filteredData.strings) { - stringTable = filteredData.strings; - filteredData = resolveStringIndices(filteredData); - } - } - - const tooltip = createPythonTooltip(filteredData); - const chart = createFlamegraph(tooltip, filteredData.value); - renderFlamegraph(chart, filteredData); - - populateThreadStats(baseData, selectedThreadId); + updateFlamegraphView(); } function filterDataByThread(data, threadId) { @@ -1138,11 +1264,11 @@ function getInvertNodeKey(node) { return `${node.filename || '~'}|${node.lineno || 0}|${node.funcname || node.name}`; } -function accumulateInvertedNode(parent, stackFrame, leaf) { +function accumulateInvertedNode(parent, stackFrame, leaf, isDifferential) { const key = getInvertNodeKey(stackFrame); if (!parent.children[key]) { - parent.children[key] = { + const newNode = { name: stackFrame.name, value: 0, children: {}, @@ -1150,8 +1276,19 @@ function accumulateInvertedNode(parent, stackFrame, leaf) { lineno: stackFrame.lineno, funcname: stackFrame.funcname, source: stackFrame.source, + opcodes: null, threads: new Set() }; + + if (isDifferential) { + newNode.baseline = 0; + newNode.baseline_total = 0; + newNode.self_time = 0; + newNode.diff = 0; + newNode.diff_pct = 0; + } + + parent.children[key] = newNode; } const node = parent.children[key]; @@ -1159,33 +1296,55 @@ function accumulateInvertedNode(parent, stackFrame, leaf) { if (leaf.threads) { leaf.threads.forEach(t => node.threads.add(t)); } + if (stackFrame.opcodes) { + if (!node.opcodes) { + node.opcodes = { ...stackFrame.opcodes }; + } else { + for (const [op, count] of Object.entries(stackFrame.opcodes)) { + node.opcodes[op] = (node.opcodes[op] || 0) + count; + } + } + } + + if (isDifferential) { + node.baseline += stackFrame.baseline || 0; + node.baseline_total += stackFrame.baseline_total || 0; + node.self_time += stackFrame.self_time || 0; + node.diff += stackFrame.diff || 0; + + if (node.baseline > 0) { + node.diff_pct = (node.diff / node.baseline) * 100.0; + } else if (node.self_time > 0) { + node.diff_pct = 100.0; + } + } return node; } -function processLeaf(invertedRoot, path, leafNode) { +function processLeaf(invertedRoot, path, leafNode, isDifferential) { if (!path || path.length === 0) { return; } - let invertedParent = accumulateInvertedNode(invertedRoot, leafNode, leafNode); + let invertedParent = accumulateInvertedNode(invertedRoot, leafNode, leafNode, isDifferential); // Walk backwards through the call stack for (let i = path.length - 2; i >= 0; i--) { - invertedParent = accumulateInvertedNode(invertedParent, path[i], leafNode); + invertedParent = accumulateInvertedNode(invertedParent, path[i], leafNode, isDifferential); } } -function traverseInvert(path, currentNode, invertedRoot) { +function traverseInvert(path, currentNode, invertedRoot, isDifferential) { const children = currentNode.children || []; const childThreads = new Set(children.flatMap(c => c.threads || [])); const selfThreads = (currentNode.threads || []).filter(t => !childThreads.has(t)); if (selfThreads.length > 0) { - processLeaf(invertedRoot, path, { ...currentNode, threads: selfThreads }); + processLeaf(invertedRoot, path, { ...currentNode, threads: selfThreads }, isDifferential); } - children.forEach(child => traverseInvert(path.concat([child]), child, invertedRoot)); + children.forEach(child => traverseInvert(path.concat([child]), child, invertedRoot, isDifferential)); } function convertInvertDictToArray(node) { @@ -1203,6 +1362,8 @@ function convertInvertDictToArray(node) { } function generateInvertedFlamegraph(data) { + const isDifferential = data && data.stats && data.stats.is_differential; + const invertedRoot = { name: data.name, value: data.value, @@ -1214,9 +1375,9 @@ function generateInvertedFlamegraph(data) { const children = data.children || []; if (children.length === 0) { // Single-frame tree: the root is its own leaf - processLeaf(invertedRoot, [data], data); + processLeaf(invertedRoot, [data], data, isDifferential); } else { - children.forEach(child => traverseInvert([child], child, invertedRoot)); + children.forEach(child => traverseInvert([child], child, invertedRoot, isDifferential)); } convertInvertDictToArray(invertedRoot); @@ -1226,21 +1387,7 @@ function generateInvertedFlamegraph(data) { function toggleInvert() { isInverted = !isInverted; updateToggleUI('toggle-invert', isInverted); - - // Build inverted data on first use - if (isInverted && !invertedData) { - invertedData = generateInvertedFlamegraph(normalData); - } - - let dataToRender = isInverted ? invertedData : normalData; - - if (currentThreadFilter !== 'all') { - dataToRender = filterDataByThread(dataToRender, parseInt(currentThreadFilter)); - } - - const tooltip = createPythonTooltip(dataToRender); - const chart = createFlamegraph(tooltip, dataToRender.value); - renderFlamegraph(chart, dataToRender); + updateFlamegraphView(); } // ============================================================================ @@ -1254,7 +1401,7 @@ function initFlamegraph() { if (EMBEDDED_DATA.strings) { stringTable = EMBEDDED_DATA.strings; - normalData = resolveStringIndices(EMBEDDED_DATA); + normalData = resolveStringIndices(EMBEDDED_DATA, EMBEDDED_DATA.strings); } else { normalData = EMBEDDED_DATA; } @@ -1267,8 +1414,20 @@ function initFlamegraph() { initThreadFilter(normalData); + // Toggle legend based on differential mode + const isDifferential = normalData && normalData.stats && normalData.stats.is_differential; + const heatmapLegend = document.getElementById('heatmap-legend-section'); + const diffLegend = document.getElementById('diff-legend-section'); + if (isDifferential) { + if (heatmapLegend) heatmapLegend.style.display = 'none'; + if (diffLegend) diffLegend.style.display = 'block'; + } else { + if (heatmapLegend) heatmapLegend.style.display = 'block'; + if (diffLegend) diffLegend.style.display = 'none'; + } + const tooltip = createPythonTooltip(normalData); - const chart = createFlamegraph(tooltip, normalData.value); + const chart = createFlamegraph(tooltip, normalData.value, normalData); renderFlamegraph(chart, normalData); initSearchHandlers(); initSidebarResize(); diff --git a/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html b/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html index c0d40b2712beea..9a77178aeff7ec 100644 --- a/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html +++ b/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html @@ -3,7 +3,7 @@ - Tachyon Profiler - Flamegraph Report + {{TITLE}} @@ -18,7 +18,7 @@ Tachyon - Flamegraph Report + {{SUBTITLE}}
View Mode
+ + +
Flamegraph
@@ -294,9 +301,9 @@

Runtime Stats

- -
+ + +
diff --git a/Lib/profiling/sampling/cli.py b/Lib/profiling/sampling/cli.py index f4b31aad45b922..e22ab158d6a94d 100644 --- a/Lib/profiling/sampling/cli.py +++ b/Lib/profiling/sampling/cli.py @@ -16,7 +16,7 @@ from .errors import SamplingUnknownProcessError, SamplingModuleNotFoundError, SamplingScriptNotFoundError from .sample import sample, sample_live, _is_process_running from .pstats_collector import PstatsCollector -from .stack_collector import CollapsedStackCollector, FlamegraphCollector +from .stack_collector import CollapsedStackCollector, FlamegraphCollector, DiffFlamegraphCollector from .heatmap_collector import HeatmapCollector from .gecko_collector import GeckoCollector from .binary_collector import BinaryCollector @@ -56,6 +56,13 @@ class CustomFormatter( pass +class DiffFlamegraphAction(argparse.Action): + """Custom action for --diff-flamegraph that sets both format and baseline path.""" + def __call__(self, parser, namespace, values, option_string=None): + namespace.format = 'diff_flamegraph' + namespace.diff_baseline = values + + _HELP_DESCRIPTION = """Sample a process's stack frames and generate profiling data. Examples: @@ -85,6 +92,7 @@ class CustomFormatter( "pstats": "pstats", "collapsed": "txt", "flamegraph": "html", + "diff_flamegraph": "html", "gecko": "json", "heatmap": "html", "binary": "bin", @@ -94,6 +102,7 @@ class CustomFormatter( "pstats": PstatsCollector, "collapsed": CollapsedStackCollector, "flamegraph": FlamegraphCollector, + "diff_flamegraph": DiffFlamegraphCollector, "gecko": GeckoCollector, "heatmap": HeatmapCollector, "binary": BinaryCollector, @@ -467,6 +476,12 @@ def _add_format_options(parser, include_compression=True, include_binary=True): dest="format", help="Generate interactive HTML heatmap visualization with line-level sample counts", ) + format_group.add_argument( + "--diff-flamegraph", + metavar="BASELINE", + action=DiffFlamegraphAction, + help="Generate differential flamegraph comparing current profile to BASELINE binary file", + ) if include_binary: format_group.add_argument( "--binary", @@ -475,7 +490,7 @@ def _add_format_options(parser, include_compression=True, include_binary=True): dest="format", help="Generate high-performance binary format (use 'replay' command to convert)", ) - parser.set_defaults(format="pstats") + parser.set_defaults(format="pstats", diff_baseline=None) if include_compression: output_group.add_argument( @@ -545,17 +560,18 @@ def _sort_to_mode(sort_choice): return sort_map.get(sort_choice, SORT_MODE_NSAMPLES) def _create_collector(format_type, sample_interval_usec, skip_idle, opcodes=False, - output_file=None, compression='auto'): + output_file=None, compression='auto', diff_baseline=None): """Create the appropriate collector based on format type. Args: - format_type: The output format ('pstats', 'collapsed', 'flamegraph', 'gecko', 'heatmap', 'binary') + format_type: The output format ('pstats', 'collapsed', 'flamegraph', 'gecko', 'heatmap', 'binary', 'diff_flamegraph') sample_interval_usec: Sampling interval in microseconds skip_idle: Whether to skip idle samples opcodes: Whether to collect opcode information (only used by gecko format for creating interval markers in Firefox Profiler) output_file: Output file path (required for binary format) compression: Compression type for binary format ('auto', 'zstd', 'none') + diff_baseline: Path to baseline binary file for differential flamegraph Returns: A collector instance of the appropriate type @@ -564,6 +580,17 @@ def _create_collector(format_type, sample_interval_usec, skip_idle, opcodes=Fals if collector_class is None: raise ValueError(f"Unknown format: {format_type}") + if format_type == "diff_flamegraph": + if diff_baseline is None: + raise ValueError("Differential flamegraph requires a baseline file") + if not os.path.exists(diff_baseline): + raise ValueError(f"Baseline file not found: {diff_baseline}") + return collector_class( + sample_interval_usec, + baseline_binary_path=diff_baseline, + skip_idle=skip_idle + ) + # Binary format requires output file and compression if format_type == "binary": if output_file is None: @@ -663,7 +690,7 @@ def _handle_output(collector, args, pid, mode): collector.export(filename) # Auto-open browser for HTML output if --browser flag is set - if args.format in ('flamegraph', 'heatmap') and getattr(args, 'browser', False): + if args.format in ('flamegraph', 'diff_flamegraph', 'heatmap') and getattr(args, 'browser', False): _open_in_browser(filename) @@ -756,7 +783,7 @@ def _validate_args(args, parser): ) # Validate --opcodes is only used with compatible formats - opcodes_compatible_formats = ("live", "gecko", "flamegraph", "heatmap", "binary") + opcodes_compatible_formats = ("live", "gecko", "flamegraph", "diff_flamegraph", "heatmap", "binary") if getattr(args, 'opcodes', False) and args.format not in opcodes_compatible_formats: parser.error( f"--opcodes is only compatible with {', '.join('--' + f for f in opcodes_compatible_formats)}." @@ -953,7 +980,8 @@ def _handle_attach(args): collector = _create_collector( args.format, args.sample_interval_usec, skip_idle, args.opcodes, output_file=output_file, - compression=getattr(args, 'compression', 'auto') + compression=getattr(args, 'compression', 'auto'), + diff_baseline=args.diff_baseline ) with _get_child_monitor_context(args, args.pid): @@ -1031,7 +1059,8 @@ def _handle_run(args): collector = _create_collector( args.format, args.sample_interval_usec, skip_idle, args.opcodes, output_file=output_file, - compression=getattr(args, 'compression', 'auto') + compression=getattr(args, 'compression', 'auto'), + diff_baseline=args.diff_baseline ) with _get_child_monitor_context(args, process.pid): @@ -1180,7 +1209,10 @@ def _handle_replay(args): print(f" Sample interval: {interval} us") print(f" Compression: {'zstd' if info.get('compression_type', 0) == 1 else 'none'}") - collector = _create_collector(args.format, interval, skip_idle=False) + collector = _create_collector( + args.format, interval, skip_idle=False, + diff_baseline=args.diff_baseline + ) def progress_callback(current, total): if total > 0: @@ -1206,7 +1238,7 @@ def progress_callback(current, total): collector.export(filename) # Auto-open browser for HTML output if --browser flag is set - if args.format in ('flamegraph', 'heatmap') and getattr(args, 'browser', False): + if args.format in ('flamegraph', 'diff_flamegraph', 'heatmap') and getattr(args, 'browser', False): _open_in_browser(filename) print(f"Replayed {count} samples") diff --git a/Lib/profiling/sampling/stack_collector.py b/Lib/profiling/sampling/stack_collector.py index 931bc2c487b55b..05ebe4d9764758 100644 --- a/Lib/profiling/sampling/stack_collector.py +++ b/Lib/profiling/sampling/stack_collector.py @@ -333,7 +333,7 @@ def process_frames(self, frames, thread_id, weight=1): node = current["children"].get(func) if node is None: - node = {"samples": 0, "children": {}, "threads": set(), "opcodes": collections.Counter()} + node = {"samples": 0, "children": {}, "threads": set(), "opcodes": collections.Counter(), "self": 0} current["children"][func] = node node["samples"] += weight node["threads"].add(thread_id) @@ -343,6 +343,9 @@ def process_frames(self, frames, thread_id, weight=1): current = node + if current is not self._root: + current["self"] += weight + def _get_source_lines(self, func): filename, lineno, _ = func @@ -381,6 +384,18 @@ def _create_flamegraph_html(self, data): component_js = (template_dir / "_flamegraph_assets" / "flamegraph.js").read_text(encoding="utf-8") js_content = f"{base_js}\n{component_js}" + # Set title and subtitle based on whether this is a differential flamegraph + is_differential = data.get("stats", {}).get("is_differential", False) + if is_differential: + title = "Tachyon Profiler - Differential Flamegraph Report" + subtitle = "Differential Flamegraph Report" + else: + title = "Tachyon Profiler - Flamegraph Report" + subtitle = "Flamegraph Report" + + html_template = html_template.replace("{{TITLE}}", title) + html_template = html_template.replace("{{SUBTITLE}}", subtitle) + # Inline first-party CSS/JS html_template = html_template.replace( "", f"" @@ -427,3 +442,266 @@ def _create_flamegraph_html(self, data): ) return html_content + + +class DiffFlamegraphCollector(FlamegraphCollector): + """Differential flamegraph collector that compares against a baseline binary profile.""" + + def __init__(self, sample_interval_usec, *, baseline_binary_path, skip_idle=False): + super().__init__(sample_interval_usec, skip_idle=skip_idle) + if not os.path.exists(baseline_binary_path): + raise ValueError(f"Baseline file not found: {baseline_binary_path}") + self.baseline_binary_path = baseline_binary_path + self._baseline_collector = None + self._elided_paths = set() + + def _load_baseline(self): + """Load baseline profile from binary file.""" + from .binary_reader import BinaryReader + + with BinaryReader(self.baseline_binary_path) as reader: + info = reader.get_info() + + baseline_collector = FlamegraphCollector( + sample_interval_usec=info['sample_interval_us'], + skip_idle=self.skip_idle + ) + + reader.replay_samples(baseline_collector) + + self._baseline_collector = baseline_collector + + def _aggregate_path_samples(self, root_node, path=None): + """Aggregate samples by stack path, excluding line numbers for cross-profile matching.""" + if path is None: + path = () + + stats = {} + + for func, node in root_node["children"].items(): + filename, _lineno, funcname = func + func_key = (filename, funcname) + path_key = path + (func_key,) + + total_samples = node.get("samples", 0) + self_samples = node.get("self", 0) + + if path_key in stats: + stats[path_key]["total"] += total_samples + stats[path_key]["self"] += self_samples + else: + stats[path_key] = { + "total": total_samples, + "self": self_samples + } + + child_stats = self._aggregate_path_samples(node, path_key) + for key, data in child_stats.items(): + if key in stats: + stats[key]["total"] += data["total"] + stats[key]["self"] += data["self"] + else: + stats[key] = data + + return stats + + def _convert_to_flamegraph_format(self): + """Convert to flamegraph format with differential annotations.""" + if self._baseline_collector is None: + self._load_baseline() + + current_flamegraph = super()._convert_to_flamegraph_format() + + current_stats = self._aggregate_path_samples(self._root) + baseline_stats = self._aggregate_path_samples(self._baseline_collector._root) + + # Scale baseline values to make them comparable, accounting for both + # sample count differences and sample interval differences. + baseline_total = self._baseline_collector._total_samples + if baseline_total > 0 and self._total_samples > 0: + current_time = self._total_samples * self.sample_interval_usec + baseline_time = baseline_total * self._baseline_collector.sample_interval_usec + scale = current_time / baseline_time + elif baseline_total > 0: + # Current profile is empty - use interval-based scale for elided display + scale = self.sample_interval_usec / self._baseline_collector.sample_interval_usec + else: + scale = 1.0 + + self._annotate_nodes_with_diff(current_flamegraph, current_stats, baseline_stats, scale) + self._add_elided_flamegraph(current_flamegraph, current_stats, baseline_stats, scale) + + return current_flamegraph + + def _annotate_nodes_with_diff(self, current_flamegraph, current_stats, baseline_stats, scale): + """Annotate each node in the tree with diff metadata.""" + if "stats" not in current_flamegraph: + current_flamegraph["stats"] = {} + + current_flamegraph["stats"]["baseline_samples"] = self._baseline_collector._total_samples + current_flamegraph["stats"]["current_samples"] = self._total_samples + current_flamegraph["stats"]["baseline_scale"] = scale + current_flamegraph["stats"]["is_differential"] = True + + if self._is_promoted_root(current_flamegraph): + self._add_diff_data_to_node(current_flamegraph, (), current_stats, baseline_stats, scale) + else: + for child in current_flamegraph["children"]: + self._add_diff_data_to_node(child, (), current_stats, baseline_stats, scale) + + def _add_diff_data_to_node(self, node, path, current_stats, baseline_stats, scale): + """Recursively add diff metadata to nodes.""" + func_key = self._extract_func_key(node, self._string_table) + path_key = path + (func_key,) if func_key else path + + current_data = current_stats.get(path_key, {"total": 0, "self": 0}) + baseline_data = baseline_stats.get(path_key, {"total": 0, "self": 0}) + + current_self = current_data["self"] + baseline_self = baseline_data["self"] * scale + baseline_total = baseline_data["total"] * scale + + diff = current_self - baseline_self + if baseline_self > 0: + diff_pct = (diff / baseline_self) * 100.0 + elif current_self > 0: + diff_pct = 100.0 + else: + diff_pct = 0.0 + + node["baseline"] = baseline_self + node["baseline_total"] = baseline_total + node["self_time"] = current_self + node["diff"] = diff + node["diff_pct"] = diff_pct + + if "children" in node and node["children"]: + for child in node["children"]: + self._add_diff_data_to_node(child, path_key, current_stats, baseline_stats, scale) + + def _is_promoted_root(self, data): + """Check if the data represents a promoted root node.""" + return "filename" in data and "funcname" in data + + def _add_elided_flamegraph(self, current_flamegraph, current_stats, baseline_stats, scale): + """Calculate elided paths and add elided flamegraph to stats.""" + self._elided_paths = baseline_stats.keys() - current_stats.keys() + + current_flamegraph["stats"]["elided_count"] = len(self._elided_paths) + + if self._elided_paths: + elided_flamegraph = self._build_elided_flamegraph(baseline_stats, scale) + if elided_flamegraph: + current_flamegraph["stats"]["elided_flamegraph"] = elided_flamegraph + + def _build_elided_flamegraph(self, baseline_stats, scale): + """Build flamegraph containing only elided paths from baseline. + + This re-runs the base conversion pipeline on the baseline collector + to produce a complete formatted flamegraph, then prunes it to keep + only elided paths. + """ + if not self._baseline_collector or not self._elided_paths: + return None + + # Suppress source line collection for elided nodes - these functions + # no longer exist in the current profile, so source lines from the + # current machine's filesystem would be misleading or unavailable. + orig_get_source = self._baseline_collector._get_source_lines + self._baseline_collector._get_source_lines = lambda func: None + try: + baseline_data = self._baseline_collector._convert_to_flamegraph_format() + finally: + self._baseline_collector._get_source_lines = orig_get_source + + # Remove non-elided nodes and recalculate values + if not self._extract_elided_nodes(baseline_data, path=()): + return None + + self._add_elided_metadata(baseline_data, baseline_stats, scale, path=()) + + # Merge only profiling metadata, not thread-level stats + for key in ("sample_interval_usec", "duration_sec", "sample_rate", + "error_rate", "missed_samples", "mode"): + if key in self.stats: + baseline_data["stats"][key] = self.stats[key] + baseline_data["stats"]["is_differential"] = True + baseline_data["stats"]["baseline_samples"] = self._baseline_collector._total_samples + baseline_data["stats"]["current_samples"] = self._total_samples + + return baseline_data + + def _extract_elided_nodes(self, node, path): + """Remove non-elided nodes and recalculate values bottom-up.""" + if not node: + return False + + func_key = self._extract_func_key(node, self._baseline_collector._string_table) + current_path = path + (func_key,) if func_key else path + + is_elided = current_path in self._elided_paths if func_key else False + + if "children" in node: + # Filter children, keeping only those with elided descendants + elided_children = [] + total_value = 0 + for child in node["children"]: + if self._extract_elided_nodes(child, current_path): + elided_children.append(child) + total_value += child.get("value", 0) + node["children"] = elided_children + + # Recalculate value for structural (non-elided) ancestor nodes; + # elided nodes keep their original value to preserve self-samples + if elided_children and not is_elided: + node["value"] = total_value + + # Keep this node if it's elided or has elided descendants + return is_elided or bool(node.get("children")) + + def _add_elided_metadata(self, node, baseline_stats, scale, path): + """Add differential metadata showing this path disappeared.""" + if not node: + return + + func_key = self._extract_func_key(node, self._baseline_collector._string_table) + current_path = path + (func_key,) if func_key else path + + if func_key and current_path in baseline_stats: + baseline_data = baseline_stats[current_path] + baseline_self = baseline_data["self"] * scale + baseline_total = baseline_data["total"] * scale + + node["baseline"] = baseline_self + node["baseline_total"] = baseline_total + node["diff"] = -baseline_self + else: + node["baseline"] = 0 + node["baseline_total"] = 0 + node["diff"] = 0 + + node["self_time"] = 0 + # Elided paths have zero current self-time, so the change is always + # -100% when there was actual baseline self-time to lose. + # For internal nodes with no baseline self-time, use 0% to avoid + # misleading tooltips. + if baseline_self > 0: + node["diff_pct"] = -100.0 + else: + node["diff_pct"] = 0.0 + + if "children" in node and node["children"]: + for child in node["children"]: + self._add_elided_metadata(child, baseline_stats, scale, current_path) + + def _extract_func_key(self, node, string_table): + """Extract (filename, funcname) key from node, excluding line numbers. + + Line numbers are excluded to match functions even if they moved. + Returns None for root nodes that don't have function information. + """ + if "filename" not in node or "funcname" not in node: + return None + filename = string_table.get_string(node["filename"]) + funcname = string_table.get_string(node["funcname"]) + return (filename, funcname) diff --git a/Lib/test/test_profiling/test_sampling_profiler/mocks.py b/Lib/test/test_profiling/test_sampling_profiler/mocks.py index 4e0f7a87c6da54..6ac2d08e898d81 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/mocks.py +++ b/Lib/test/test_profiling/test_sampling_profiler/mocks.py @@ -91,3 +91,22 @@ def __init__(self, thread_id, awaited_by): def __repr__(self): return f"MockAwaitedInfo(thread_id={self.thread_id}, awaited_by={len(self.awaited_by)} tasks)" + + +def make_diff_collector_with_mock_baseline(baseline_samples): + """Create a DiffFlamegraphCollector with baseline injected directly, + skipping the binary round-trip that _load_baseline normally does.""" + from profiling.sampling.stack_collector import ( + DiffFlamegraphCollector, + FlamegraphCollector, + ) + + baseline = FlamegraphCollector(1000) + for sample in baseline_samples: + baseline.collect(sample) + + # Path is unused since we inject _baseline_collector directly; + # use __file__ as a dummy path that passes the existence check. + diff = DiffFlamegraphCollector(1000, baseline_binary_path=__file__) + diff._baseline_collector = baseline + return diff diff --git a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py index 06c9e51e0c9c55..86fb9d4c05b3bc 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py +++ b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py @@ -37,10 +37,26 @@ from test.support import captured_stdout, captured_stderr -from .mocks import MockFrameInfo, MockThreadInfo, MockInterpreterInfo, LocationInfo +from .mocks import MockFrameInfo, MockThreadInfo, MockInterpreterInfo, LocationInfo, make_diff_collector_with_mock_baseline from .helpers import close_and_unlink +def resolve_name(node, strings): + """Resolve a flamegraph node's name from the string table.""" + idx = node.get("name", 0) + if isinstance(idx, int) and 0 <= idx < len(strings): + return strings[idx] + return str(idx) + + +def find_child_by_name(children, strings, substr): + """Find a child node whose resolved name contains substr.""" + for child in children: + if substr in resolve_name(child, strings): + return child + return None + + class TestSampleProfilerComponents(unittest.TestCase): """Unit tests for individual profiler components.""" @@ -398,13 +414,7 @@ def test_flamegraph_collector_basic(self): data = collector._convert_to_flamegraph_format() # With string table, name is now an index - resolve it using the strings array strings = data.get("strings", []) - name_index = data.get("name", 0) - resolved_name = ( - strings[name_index] - if isinstance(name_index, int) and 0 <= name_index < len(strings) - else str(name_index) - ) - self.assertIn(resolved_name, ("No Data", "No significant data")) + self.assertIn(resolve_name(data, strings), ("No Data", "No significant data")) # Test collecting sample data test_frames = [ @@ -423,26 +433,13 @@ def test_flamegraph_collector_basic(self): data = collector._convert_to_flamegraph_format() # Expect promotion: root is the single child (func2), with func1 as its only child strings = data.get("strings", []) - name_index = data.get("name", 0) - name = ( - strings[name_index] - if isinstance(name_index, int) and 0 <= name_index < len(strings) - else str(name_index) - ) - self.assertIsInstance(name, str) + name = resolve_name(data, strings) self.assertTrue(name.startswith("Program Root: ")) self.assertIn("func2 (file.py:20)", name) # formatted name children = data.get("children", []) self.assertEqual(len(children), 1) child = children[0] - child_name_index = child.get("name", 0) - child_name = ( - strings[child_name_index] - if isinstance(child_name_index, int) - and 0 <= child_name_index < len(strings) - else str(child_name_index) - ) - self.assertIn("func1 (file.py:10)", child_name) # formatted name + self.assertIn("func1 (file.py:10)", resolve_name(child, strings)) self.assertEqual(child["value"], 1) def test_flamegraph_collector_export(self): @@ -1211,6 +1208,463 @@ def test_flamegraph_collector_per_thread_gc_percentage(self): self.assertEqual(collector.per_thread_stats[2]["total"], 6) self.assertAlmostEqual(per_thread_stats[2]["gc_pct"], 10.0, places=1) + def test_diff_flamegraph_identical_profiles(self): + """When baseline and current are identical, diff should be ~0.""" + test_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([test_frames] * 3) + for _ in range(3): + diff.collect(test_frames) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + self.assertEqual(data["stats"]["baseline_samples"], 3) + self.assertEqual(data["stats"]["current_samples"], 3) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 1.0) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("func1", resolve_name(child, strings)) + self.assertEqual(child["self_time"], 3) + self.assertAlmostEqual(child["baseline"], 3.0) + self.assertAlmostEqual(child["diff"], 0.0, places=1) + self.assertAlmostEqual(child["diff_pct"], 0.0, places=1) + + self.assertEqual(data["stats"]["elided_count"], 0) + self.assertNotIn("elided_flamegraph", data["stats"]) + + def test_diff_flamegraph_new_function(self): + """A function only in current should have diff_pct=100 and baseline=0.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + diff.collect([ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "new_func"), + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ]) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + func1_node = children[0] + self.assertIn("func1", resolve_name(func1_node, strings)) + + func1_children = func1_node.get("children", []) + self.assertEqual(len(func1_children), 1) + new_func_node = func1_children[0] + self.assertIn("new_func", resolve_name(new_func_node, strings)) + self.assertEqual(new_func_node["baseline"], 0) + self.assertGreater(new_func_node["self_time"], 0) + self.assertEqual(new_func_node["diff"], new_func_node["self_time"]) + self.assertAlmostEqual(new_func_node["diff_pct"], 100.0) + + def test_diff_flamegraph_changed_functions(self): + """Functions with different sample counts should have correct diff and diff_pct.""" + hot_leaf_sample = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "hot_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ]) + ]) + ] + cold_leaf_sample = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "cold_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ]) + ]) + ] + + # Baseline: 2 samples, current: 4, scale = 2.0 + diff = make_diff_collector_with_mock_baseline( + [hot_leaf_sample, cold_leaf_sample] + ) + for _ in range(3): + diff.collect(hot_leaf_sample) + diff.collect(cold_leaf_sample) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 2.0) + + children = data.get("children", []) + hot_node = find_child_by_name(children, strings, "hot_leaf") + cold_node = find_child_by_name(children, strings, "cold_leaf") + self.assertIsNotNone(hot_node) + self.assertIsNotNone(cold_node) + + # hot_leaf regressed (+50%) + self.assertAlmostEqual(hot_node["baseline"], 2.0) + self.assertEqual(hot_node["self_time"], 3) + self.assertAlmostEqual(hot_node["diff"], 1.0) + self.assertAlmostEqual(hot_node["diff_pct"], 50.0) + + # cold_leaf improved (-50%) + self.assertAlmostEqual(cold_node["baseline"], 2.0) + self.assertEqual(cold_node["self_time"], 1) + self.assertAlmostEqual(cold_node["diff"], -1.0) + self.assertAlmostEqual(cold_node["diff_pct"], -50.0) + + def test_diff_flamegraph_scale_factor(self): + """Scale factor adjusts when sample counts differ.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + for _ in range(4): + diff.collect(baseline_frames) + + data = diff._convert_to_flamegraph_format() + self.assertAlmostEqual(data["stats"]["baseline_scale"], 4.0) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + func1_node = children[0] + self.assertEqual(func1_node["self_time"], 4) + self.assertAlmostEqual(func1_node["baseline"], 4.0) + self.assertAlmostEqual(func1_node["diff"], 0.0) + self.assertAlmostEqual(func1_node["diff_pct"], 0.0) + + def test_diff_flamegraph_elided_stacks(self): + """Paths in baseline but not current produce elided stacks.""" + baseline_frames_1 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + baseline_frames_2 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "old_func"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames_1, baseline_frames_2]) + for _ in range(2): + diff.collect(baseline_frames_1) + + data = diff._convert_to_flamegraph_format() + + self.assertGreater(data["stats"]["elided_count"], 0) + self.assertIn("elided_flamegraph", data["stats"]) + elided = data["stats"]["elided_flamegraph"] + self.assertTrue(elided["stats"]["is_differential"]) + self.assertIn("strings", elided) + + elided_strings = elided.get("strings", []) + children = elided.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("old_func", resolve_name(child, elided_strings)) + self.assertEqual(child["self_time"], 0) + self.assertAlmostEqual(child["diff_pct"], -100.0) + self.assertGreater(child["baseline"], 0) + self.assertAlmostEqual(child["diff"], -child["baseline"]) + + def test_diff_flamegraph_function_matched_despite_line_change(self): + """Functions match by (filename, funcname), ignoring lineno.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + # Same functions but different line numbers + diff.collect([ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 99, "func1"), + MockFrameInfo("file.py", 55, "func2"), + ]) + ]) + ]) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("func1", resolve_name(child, strings)) + self.assertGreater(child["baseline"], 0) + self.assertGreater(child["self_time"], 0) + self.assertAlmostEqual(child["diff"], 0.0, places=1) + self.assertAlmostEqual(child["diff_pct"], 0.0, places=1) + + def test_diff_flamegraph_empty_current(self): + """Empty current profile still produces differential metadata and elided paths.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [MockFrameInfo("file.py", 10, "func1")]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + # Don't collect anything in current + + data = diff._convert_to_flamegraph_format() + self.assertIn("name", data) + self.assertEqual(data["value"], 0) + # Differential metadata should still be populated + self.assertTrue(data["stats"]["is_differential"]) + # All baseline paths should be elided since current is empty + self.assertGreater(data["stats"]["elided_count"], 0) + + def test_diff_flamegraph_empty_baseline(self): + """Empty baseline with non-empty current uses scale=1.0 fallback.""" + diff = make_diff_collector_with_mock_baseline([]) + diff.collect([ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ]) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + self.assertEqual(data["stats"]["baseline_samples"], 0) + self.assertEqual(data["stats"]["current_samples"], 1) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 1.0) + self.assertEqual(data["stats"]["elided_count"], 0) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("func1", resolve_name(child, strings)) + self.assertEqual(child["self_time"], 1) + self.assertAlmostEqual(child["baseline"], 0.0) + self.assertAlmostEqual(child["diff"], 1.0) + self.assertAlmostEqual(child["diff_pct"], 100.0) + + def test_diff_flamegraph_export(self): + """DiffFlamegraphCollector export produces differential HTML.""" + test_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([test_frames]) + diff.collect(test_frames) + + flamegraph_out = tempfile.NamedTemporaryFile( + suffix=".html", delete=False + ) + self.addCleanup(close_and_unlink, flamegraph_out) + + with captured_stdout(), captured_stderr(): + diff.export(flamegraph_out.name) + + self.assertTrue(os.path.exists(flamegraph_out.name)) + self.assertGreater(os.path.getsize(flamegraph_out.name), 0) + + with open(flamegraph_out.name, "r", encoding="utf-8") as f: + content = f.read() + + self.assertIn("", content.lower()) + self.assertIn("Differential Flamegraph", content) + self.assertIn('"is_differential": true', content) + self.assertIn("d3-flame-graph", content) + self.assertIn('id="diff-legend-section"', content) + self.assertIn("Differential Colors", content) + + def test_diff_flamegraph_preserves_metadata(self): + """Differential mode preserves threads and opcodes metadata.""" + test_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [MockFrameInfo("a.py", 10, "func_a", opcode=100)]), + MockThreadInfo(2, [MockFrameInfo("b.py", 20, "func_b", opcode=200)]), + ]) + ] + + diff = make_diff_collector_with_mock_baseline([test_frames]) + diff.collect(test_frames) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + + self.assertIn("threads", data) + self.assertEqual(len(data["threads"]), 2) + + children = data.get("children", []) + self.assertEqual(len(children), 2) + + opcodes_found = set() + for child in children: + self.assertIn("diff", child) + self.assertIn("diff_pct", child) + self.assertIn("baseline", child) + self.assertIn("self_time", child) + self.assertIn("threads", child) + + if "opcodes" in child: + opcodes_found.update(child["opcodes"].keys()) + + self.assertIn(100, opcodes_found) + self.assertIn(200, opcodes_found) + + self.assertIn("per_thread_stats", data["stats"]) + per_thread_stats = data["stats"]["per_thread_stats"] + self.assertIn(1, per_thread_stats) + self.assertIn(2, per_thread_stats) + + def test_diff_flamegraph_elided_preserves_metadata(self): + """Elided flamegraph preserves thread_stats, per_thread_stats, and opcodes.""" + baseline_frames_1 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1", opcode=100), + MockFrameInfo("file.py", 20, "func2", opcode=101), + ], status=THREAD_STATUS_HAS_GIL) + ]) + ] + baseline_frames_2 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "old_func", opcode=200), + MockFrameInfo("file.py", 20, "func2", opcode=101), + ], status=THREAD_STATUS_HAS_GIL) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames_1, baseline_frames_2]) + for _ in range(2): + diff.collect(baseline_frames_1) + + data = diff._convert_to_flamegraph_format() + elided = data["stats"]["elided_flamegraph"] + + self.assertTrue(elided["stats"]["is_differential"]) + self.assertIn("thread_stats", elided["stats"]) + self.assertIn("per_thread_stats", elided["stats"]) + self.assertIn("baseline_samples", elided["stats"]) + self.assertIn("current_samples", elided["stats"]) + self.assertIn("strings", elided) + + elided_strings = elided.get("strings", []) + children = elided.get("children", []) + self.assertEqual(len(children), 1) + old_func_node = children[0] + if "opcodes" in old_func_node: + self.assertIn(200, old_func_node["opcodes"]) + self.assertEqual(old_func_node["self_time"], 0) + self.assertAlmostEqual(old_func_node["diff_pct"], -100.0) + + def test_diff_flamegraph_load_baseline(self): + """Diff annotations work when baseline is loaded from a binary file.""" + from profiling.sampling.binary_collector import BinaryCollector + from profiling.sampling.stack_collector import DiffFlamegraphCollector + from .test_binary_format import make_frame, make_thread, make_interpreter + + hot_sample = [make_interpreter(0, [make_thread(1, [ + make_frame("file.py", 10, "hot_leaf"), + make_frame("file.py", 20, "caller"), + ])])] + cold_sample = [make_interpreter(0, [make_thread(1, [ + make_frame("file.py", 30, "cold_leaf"), + make_frame("file.py", 20, "caller"), + ])])] + + # Baseline: 2 samples, current: 4, scale = 2.0 + bin_file = tempfile.NamedTemporaryFile(suffix=".bin", delete=False) + self.addCleanup(close_and_unlink, bin_file) + + writer = BinaryCollector( + bin_file.name, sample_interval_usec=1000, compression='none' + ) + writer.collect(hot_sample) + writer.collect(cold_sample) + writer.export(None) + + diff = DiffFlamegraphCollector( + 1000, baseline_binary_path=bin_file.name + ) + hot_mock = [MockInterpreterInfo(0, [MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "hot_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ])])] + cold_mock = [MockInterpreterInfo(0, [MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "cold_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ])])] + for _ in range(3): + diff.collect(hot_mock) + diff.collect(cold_mock) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 2.0) + + children = data.get("children", []) + hot_node = find_child_by_name(children, strings, "hot_leaf") + cold_node = find_child_by_name(children, strings, "cold_leaf") + self.assertIsNotNone(hot_node) + self.assertIsNotNone(cold_node) + + # hot_leaf regressed (+50%) + self.assertAlmostEqual(hot_node["baseline"], 2.0) + self.assertEqual(hot_node["self_time"], 3) + self.assertAlmostEqual(hot_node["diff"], 1.0) + self.assertAlmostEqual(hot_node["diff_pct"], 50.0) + + # cold_leaf improved (-50%) + self.assertAlmostEqual(cold_node["baseline"], 2.0) + self.assertEqual(cold_node["self_time"], 1) + self.assertAlmostEqual(cold_node["diff"], -1.0) + self.assertAlmostEqual(cold_node["diff_pct"], -50.0) + class TestRecursiveFunctionHandling(unittest.TestCase): """Tests for correct handling of recursive functions in cumulative stats.""" diff --git a/Misc/NEWS.d/next/Library/2026-03-10-19-50-59.gh-issue-138122.CsoBEo.rst b/Misc/NEWS.d/next/Library/2026-03-10-19-50-59.gh-issue-138122.CsoBEo.rst new file mode 100644 index 00000000000000..2059557e8bb92e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-10-19-50-59.gh-issue-138122.CsoBEo.rst @@ -0,0 +1,4 @@ +The ``profiling.sampling`` module now supports differential flamegraph +visualization via ``--diff-flamegraph`` to compare two profiling runs. +Functions are colored red (regressions), blue (improvements), gray (neutral), +or purple (new). Elided stacks show code paths that disappeared between runs. From 8e10bd77ea0b674b47f20b0e80df504b0b55fe5c Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Mon, 30 Mar 2026 18:07:38 +0530 Subject: [PATCH 2/6] gh-146587: fix type slot assignment incase of multiple slots for same name (#146593) --- Lib/test/test_descr.py | 25 +++++++++++++++++++ ...-03-29-11-39-05.gh-issue-146587.YJicXt.rst | 1 + Objects/typeobject.c | 23 ++++++++++++----- Tools/c-analyzer/cpython/ignored.tsv | 2 +- 4 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index d6e3719479a214..1d7669e4fa5c96 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -5361,6 +5361,31 @@ def foo(self): with self.assertRaisesRegex(NotImplementedError, "BAR"): B().foo + def test_gh146587(self): + # See https://github.com/python/cpython/issues/146587 + + class A: + def __radd__(self, other): ... + + class B(tuple): ... + + self.assertIsNone(() + A()) + self.assertIsNone(B() + A()) + + from typing import NamedTuple + + class T(NamedTuple): + x: int + + class A: + def __init__(self, *args): + self.lst = list(args) + def __radd__(self, other): + return A(*self.lst, other) + + self.assertEqual(((1,)+A()).lst, [(1,)]) + self.assertEqual((T(x=1)+A()).lst, [T(x=1)]) + class DictProxyTests(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst new file mode 100644 index 00000000000000..a33dee5c875389 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst @@ -0,0 +1 @@ +Fix type slot assignment incase of multiple slots for same name in type object implementation. Patch by Kumar Aditya. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 3374051c42af8a..6ceeb7dda08e9f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -11601,7 +11601,7 @@ static pytype_slotdef slotdefs[] = { /* Stores the number of times where slotdefs has elements with same name. This counter precalculated by _PyType_InitSlotDefs() when the main interpreter starts. */ -static uint8_t slotdefs_name_counts[Py_ARRAY_LENGTH(slotdefs)]; +static uint8_t slotdefs_dups[Py_ARRAY_LENGTH(slotdefs)][1 + MAX_EQUIV]; /* Given a type pointer and an offset gotten from a slotdef entry, return a pointer to the actual slot. This is not quite the same as simply adding @@ -11768,11 +11768,22 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p, ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) { void **tptr; size_t index = (p - slotdefs); - if (slotdefs_name_counts[index] == 1) { - tptr = slotptr(type, p->offset); + if (slotdefs_dups[index][0] > 1) { + tptr = NULL; + for (size_t i = 1; i <= slotdefs_dups[index][0]; i++) { + pytype_slotdef *q = &slotdefs[slotdefs_dups[index][i]]; + void **qptr = slotptr(type, q->offset); + if (qptr == NULL || *qptr == NULL) + continue; + if (tptr != NULL) { + tptr = NULL; + break; + } + tptr = qptr; + } } else { - tptr = NULL; + tptr = slotptr(type, offset); } if (tptr == NULL || tptr == ptr) @@ -12034,7 +12045,7 @@ _PyType_InitSlotDefs(PyInterpreterState *interp) Py_CLEAR(bytearray); } - memset(slotdefs_name_counts, 0, sizeof(slotdefs_name_counts)); + memset(slotdefs_dups, -1, sizeof(slotdefs_dups)); Py_ssize_t pos = 0; PyObject *key = NULL; @@ -12044,7 +12055,7 @@ _PyType_InitSlotDefs(PyInterpreterState *interp) uint8_t n = data[0]; for (uint8_t i = 0; i < n; i++) { uint8_t idx = data[i + 1]; - slotdefs_name_counts[idx] = n; + memcpy(&slotdefs_dups[idx], data, sizeof(uint8_t) * (n + 1)); } } diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index cbec0bf262f0e0..d2489387f46caa 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -351,7 +351,7 @@ Objects/obmalloc.c - obmalloc_state_initialized - Objects/typeobject.c - name_op - Objects/typeobject.c - slotdefs - # It initialized only once when main interpeter starts -Objects/typeobject.c - slotdefs_name_counts - +Objects/typeobject.c - slotdefs_dups - Objects/unicodeobject.c - stripfuncnames - Objects/unicodeobject.c - utf7_category - Objects/unicodeobject.c unicode_decode_call_errorhandler_wchar argparse - From adf2c47911b35134cf108c24a3cc7794b7755aac Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 30 Mar 2026 14:48:18 +0200 Subject: [PATCH 3/6] gh-126835: Fix _PY_IS_SMALL_INT() macro (#146631) --- Include/internal/pycore_long.h | 3 ++- Objects/longobject.c | 2 +- Python/flowgraph.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index d545ba0c3abb52..4386e8bcad8841 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -64,7 +64,8 @@ PyAPI_FUNC(void) _PyLong_ExactDealloc(PyObject *self); # error "_PY_NSMALLPOSINTS must be greater than or equal to 257" #endif -#define _PY_IS_SMALL_INT(val) ((val) >= 0 && (val) < 256 && (val) < _PY_NSMALLPOSINTS) +#define _PY_IS_SMALL_INT(val) \ + (-_PY_NSMALLNEGINTS <= (val) && (val) < _PY_NSMALLPOSINTS) // Return a reference to the immortal zero singleton. // The function cannot return NULL. diff --git a/Objects/longobject.c b/Objects/longobject.c index f1971f0fca993c..0d3ea9bc46c321 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -26,7 +26,7 @@ class int "PyObject *" "&PyLong_Type" #define medium_value(x) ((stwodigits)_PyLong_CompactValue(x)) -#define IS_SMALL_INT(ival) (-_PY_NSMALLNEGINTS <= (ival) && (ival) < _PY_NSMALLPOSINTS) +#define IS_SMALL_INT(ival) _PY_IS_SMALL_INT(ival) #define IS_SMALL_UINT(ival) ((ival) < _PY_NSMALLPOSINTS) #define _MAX_STR_DIGITS_ERROR_FMT_TO_INT "Exceeds the limit (%d digits) for integer string conversion: value has %zd digits; use sys.set_int_max_str_digits() to increase the limit" diff --git a/Python/flowgraph.c b/Python/flowgraph.c index f446a87ee69432..e988f4451007fb 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -1411,7 +1411,7 @@ maybe_instr_make_load_smallint(cfg_instr *instr, PyObject *newconst, if (val == -1 && PyErr_Occurred()) { return -1; } - if (!overflow && _PY_IS_SMALL_INT(val)) { + if (!overflow && _PY_IS_SMALL_INT(val) && 0 <= val && val <= 255) { assert(_Py_IsImmortal(newconst)); INSTR_SET_OP1(instr, LOAD_SMALL_INT, (int)val); return 1; From 76c554bcdf53e84c79a53203fbf710e033eed839 Mon Sep 17 00:00:00 2001 From: Chris Eibl <138194463+chris-eibl@users.noreply.github.com> Date: Mon, 30 Mar 2026 15:55:44 +0200 Subject: [PATCH 4/6] gh-139922: always run MSVC 64-bit tail-calling CI (GH-146570) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- .github/workflows/build.yml | 8 ++++++ .github/workflows/reusable-windows.yml | 14 ++++++++--- .github/workflows/tail-call.yml | 35 -------------------------- 3 files changed, 19 insertions(+), 38 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f8ce2d684604e0..dd5ccf4b3a550c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -165,13 +165,21 @@ jobs: free-threading: - false - true + interpreter: + - switch-case exclude: # Skip Win32 on free-threaded builds - { arch: Win32, free-threading: true } + include: + # msvc::musttail is currently only supported on x64, + # and only supported on 3.15+. + - { arch: x64, free-threading: false, interpreter: tail-call } + - { arch: x64, free-threading: true, interpreter: tail-call } uses: ./.github/workflows/reusable-windows.yml with: arch: ${{ matrix.arch }} free-threading: ${{ matrix.free-threading }} + interpreter: ${{ matrix.interpreter }} build-windows-msi: # ${{ '' } is a hack to nest jobs under the same sidebar category. diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml index 2f667ace9194d7..8772a04d779127 100644 --- a/.github/workflows/reusable-windows.yml +++ b/.github/workflows/reusable-windows.yml @@ -12,6 +12,10 @@ on: required: false type: boolean default: false + interpreter: + description: Which interpreter to build (switch-case or tail-call) + required: true + type: string env: FORCE_COLOR: 1 @@ -20,7 +24,7 @@ env: jobs: build: - name: Build and test (${{ inputs.arch }}) + name: Build and test (${{ inputs.arch }}, ${{ inputs.interpreter }}) runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2025-vs2026' }} timeout-minutes: 60 env: @@ -33,9 +37,12 @@ jobs: if: inputs.arch != 'Win32' run: echo "::add-matcher::.github/problem-matchers/msvc.json" - name: Build CPython + # msvc::musttail is not supported for debug builds, so we have to + # switch to release. run: >- .\\PCbuild\\build.bat - -e -d -v + -e -v + ${{ inputs.interpreter == 'switch-case' && '-d' || '--tail-call-interp -c Release' }} -p "${ARCH}" ${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }} shell: bash @@ -45,6 +52,7 @@ jobs: run: >- .\\PCbuild\\rt.bat -p "${ARCH}" - -d -q --fast-ci + -q --fast-ci + ${{ inputs.interpreter == 'switch-case' && '-d' || '' }} ${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }} shell: bash diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml index 88833ea3bb2022..08bd986a64ac69 100644 --- a/.github/workflows/tail-call.yml +++ b/.github/workflows/tail-call.yml @@ -23,41 +23,6 @@ env: LLVM_VERSION: 21 jobs: - windows: - name: ${{ matrix.target }} - runs-on: ${{ matrix.runner }} - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - target: x86_64-pc-windows-msvc/msvc - architecture: x64 - runner: windows-2025-vs2026 - build_flags: "" - run_tests: true - - target: x86_64-pc-windows-msvc/msvc-free-threading - architecture: x64 - runner: windows-2025-vs2026 - build_flags: --disable-gil - run_tests: false - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - uses: actions/setup-python@v6 - with: - python-version: '3.11' - - name: Build - shell: pwsh - run: | - ./PCbuild/build.bat --tail-call-interp ${{ matrix.build_flags }} -c Release -p ${{ matrix.architecture }} - - name: Test - if: matrix.run_tests - shell: pwsh - run: | - ./PCbuild/rt.bat -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - macos: name: ${{ matrix.target }} runs-on: ${{ matrix.runner }} From 8e9d21c64b65edda99a0d38e8d23545b17f8455e Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Mon, 30 Mar 2026 19:53:29 +0530 Subject: [PATCH 5/6] gh-146558: JIT optimize dict access for objects with known hash (#146559) --- Include/internal/pycore_dict.h | 3 +- Include/internal/pycore_uop_ids.h | 2490 ++++++++++++------------ Include/internal/pycore_uop_metadata.h | 30 + Lib/test/test_capi/test_opt.py | 50 +- Objects/dictobject.c | 28 +- Python/bytecodes.c | 38 + Python/executor_cases.c.h | 95 + Python/optimizer_analysis.c | 27 + Python/optimizer_bytecodes.c | 10 + Python/optimizer_cases.c.h | 38 + 10 files changed, 1555 insertions(+), 1254 deletions(-) diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index a1d1e10ec5c022..d58539fa846563 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -138,13 +138,14 @@ extern PyObject *_PyDict_LoadBuiltinsFromGlobals(PyObject *globals); /* Consumes references to key and value */ PyAPI_FUNC(int) _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value); +PyAPI_FUNC(int) _PyDict_SetItem_Take2_KnownHash(PyDictObject *op, PyObject *key, PyObject *value, Py_hash_t hash); extern int _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value); // Export for '_asyncio' shared extension PyAPI_FUNC(int) _PyDict_SetItem_KnownHash_LockHeld(PyDictObject *mp, PyObject *key, PyObject *value, Py_hash_t hash); // Export for '_asyncio' shared extension PyAPI_FUNC(int) _PyDict_GetItemRef_KnownHash_LockHeld(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result); -extern int _PyDict_GetItemRef_KnownHash(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result); +PyAPI_FUNC(int) _PyDict_GetItemRef_KnownHash(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result); extern int _PyDict_GetItemRef_Unicode_LockHeld(PyDictObject *op, PyObject *key, PyObject **result); PyAPI_FUNC(int) _PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr, PyObject *name, PyObject *value); diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index f60859a05f995f..dbc7aaab7a7472 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -25,17 +25,18 @@ extern "C" { #define _BINARY_OP_MULTIPLY_INT 313 #define _BINARY_OP_SUBSCR_CHECK_FUNC 314 #define _BINARY_OP_SUBSCR_DICT 315 -#define _BINARY_OP_SUBSCR_INIT_CALL 316 -#define _BINARY_OP_SUBSCR_LIST_INT 317 -#define _BINARY_OP_SUBSCR_LIST_SLICE 318 -#define _BINARY_OP_SUBSCR_STR_INT 319 -#define _BINARY_OP_SUBSCR_TUPLE_INT 320 -#define _BINARY_OP_SUBSCR_USTR_INT 321 -#define _BINARY_OP_SUBTRACT_FLOAT 322 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE 323 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT 324 -#define _BINARY_OP_SUBTRACT_INT 325 -#define _BINARY_SLICE 326 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH 316 +#define _BINARY_OP_SUBSCR_INIT_CALL 317 +#define _BINARY_OP_SUBSCR_LIST_INT 318 +#define _BINARY_OP_SUBSCR_LIST_SLICE 319 +#define _BINARY_OP_SUBSCR_STR_INT 320 +#define _BINARY_OP_SUBSCR_TUPLE_INT 321 +#define _BINARY_OP_SUBSCR_USTR_INT 322 +#define _BINARY_OP_SUBTRACT_FLOAT 323 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE 324 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT 325 +#define _BINARY_OP_SUBTRACT_INT 326 +#define _BINARY_SLICE 327 #define _BUILD_INTERPOLATION BUILD_INTERPOLATION #define _BUILD_LIST BUILD_LIST #define _BUILD_MAP BUILD_MAP @@ -44,181 +45,181 @@ extern "C" { #define _BUILD_STRING BUILD_STRING #define _BUILD_TEMPLATE BUILD_TEMPLATE #define _BUILD_TUPLE BUILD_TUPLE -#define _CALL_BUILTIN_CLASS 327 -#define _CALL_BUILTIN_FAST 328 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 329 -#define _CALL_BUILTIN_O 330 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL 331 -#define _CALL_INTRINSIC_1 332 -#define _CALL_INTRINSIC_2 333 -#define _CALL_ISINSTANCE 334 -#define _CALL_KW_NON_PY 335 -#define _CALL_LEN 336 -#define _CALL_LIST_APPEND 337 -#define _CALL_METHOD_DESCRIPTOR_FAST 338 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 339 -#define _CALL_METHOD_DESCRIPTOR_NOARGS 340 -#define _CALL_METHOD_DESCRIPTOR_O 341 -#define _CALL_NON_PY_GENERAL 342 -#define _CALL_STR_1 343 -#define _CALL_TUPLE_1 344 -#define _CALL_TYPE_1 345 -#define _CHECK_AND_ALLOCATE_OBJECT 346 -#define _CHECK_ATTR_CLASS 347 -#define _CHECK_ATTR_METHOD_LAZY_DICT 348 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 349 +#define _CALL_BUILTIN_CLASS 328 +#define _CALL_BUILTIN_FAST 329 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 330 +#define _CALL_BUILTIN_O 331 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL 332 +#define _CALL_INTRINSIC_1 333 +#define _CALL_INTRINSIC_2 334 +#define _CALL_ISINSTANCE 335 +#define _CALL_KW_NON_PY 336 +#define _CALL_LEN 337 +#define _CALL_LIST_APPEND 338 +#define _CALL_METHOD_DESCRIPTOR_FAST 339 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 340 +#define _CALL_METHOD_DESCRIPTOR_NOARGS 341 +#define _CALL_METHOD_DESCRIPTOR_O 342 +#define _CALL_NON_PY_GENERAL 343 +#define _CALL_STR_1 344 +#define _CALL_TUPLE_1 345 +#define _CALL_TYPE_1 346 +#define _CHECK_AND_ALLOCATE_OBJECT 347 +#define _CHECK_ATTR_CLASS 348 +#define _CHECK_ATTR_METHOD_LAZY_DICT 349 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 350 #define _CHECK_EG_MATCH CHECK_EG_MATCH #define _CHECK_EXC_MATCH CHECK_EXC_MATCH -#define _CHECK_FUNCTION_EXACT_ARGS 350 -#define _CHECK_FUNCTION_VERSION 351 -#define _CHECK_FUNCTION_VERSION_INLINE 352 -#define _CHECK_FUNCTION_VERSION_KW 353 -#define _CHECK_IS_NOT_PY_CALLABLE 354 -#define _CHECK_IS_NOT_PY_CALLABLE_EX 355 -#define _CHECK_IS_NOT_PY_CALLABLE_KW 356 -#define _CHECK_IS_PY_CALLABLE_EX 357 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES 358 -#define _CHECK_METHOD_VERSION 359 -#define _CHECK_METHOD_VERSION_KW 360 -#define _CHECK_PEP_523 361 -#define _CHECK_PERIODIC 362 -#define _CHECK_PERIODIC_AT_END 363 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 364 -#define _CHECK_RECURSION_REMAINING 365 -#define _CHECK_STACK_SPACE 366 -#define _CHECK_STACK_SPACE_OPERAND 367 -#define _CHECK_VALIDITY 368 -#define _COLD_DYNAMIC_EXIT 369 -#define _COLD_EXIT 370 -#define _COMPARE_OP 371 -#define _COMPARE_OP_FLOAT 372 -#define _COMPARE_OP_INT 373 -#define _COMPARE_OP_STR 374 -#define _CONTAINS_OP 375 -#define _CONTAINS_OP_DICT 376 -#define _CONTAINS_OP_SET 377 +#define _CHECK_FUNCTION_EXACT_ARGS 351 +#define _CHECK_FUNCTION_VERSION 352 +#define _CHECK_FUNCTION_VERSION_INLINE 353 +#define _CHECK_FUNCTION_VERSION_KW 354 +#define _CHECK_IS_NOT_PY_CALLABLE 355 +#define _CHECK_IS_NOT_PY_CALLABLE_EX 356 +#define _CHECK_IS_NOT_PY_CALLABLE_KW 357 +#define _CHECK_IS_PY_CALLABLE_EX 358 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES 359 +#define _CHECK_METHOD_VERSION 360 +#define _CHECK_METHOD_VERSION_KW 361 +#define _CHECK_PEP_523 362 +#define _CHECK_PERIODIC 363 +#define _CHECK_PERIODIC_AT_END 364 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 365 +#define _CHECK_RECURSION_REMAINING 366 +#define _CHECK_STACK_SPACE 367 +#define _CHECK_STACK_SPACE_OPERAND 368 +#define _CHECK_VALIDITY 369 +#define _COLD_DYNAMIC_EXIT 370 +#define _COLD_EXIT 371 +#define _COMPARE_OP 372 +#define _COMPARE_OP_FLOAT 373 +#define _COMPARE_OP_INT 374 +#define _COMPARE_OP_STR 375 +#define _CONTAINS_OP 376 +#define _CONTAINS_OP_DICT 377 +#define _CONTAINS_OP_SET 378 #define _CONVERT_VALUE CONVERT_VALUE -#define _COPY 378 -#define _COPY_1 379 -#define _COPY_2 380 -#define _COPY_3 381 +#define _COPY 379 +#define _COPY_1 380 +#define _COPY_2 381 +#define _COPY_3 382 #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 382 +#define _CREATE_INIT_FRAME 383 #define _DELETE_ATTR DELETE_ATTR #define _DELETE_DEREF DELETE_DEREF #define _DELETE_FAST DELETE_FAST #define _DELETE_GLOBAL DELETE_GLOBAL #define _DELETE_NAME DELETE_NAME #define _DELETE_SUBSCR DELETE_SUBSCR -#define _DEOPT 383 -#define _DICT_MERGE 384 -#define _DICT_UPDATE 385 -#define _DO_CALL 386 -#define _DO_CALL_FUNCTION_EX 387 -#define _DO_CALL_KW 388 -#define _DYNAMIC_EXIT 389 +#define _DEOPT 384 +#define _DICT_MERGE 385 +#define _DICT_UPDATE 386 +#define _DO_CALL 387 +#define _DO_CALL_FUNCTION_EX 388 +#define _DO_CALL_KW 389 +#define _DYNAMIC_EXIT 390 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 390 +#define _ERROR_POP_N 391 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 391 -#define _EXPAND_METHOD_KW 392 -#define _FATAL_ERROR 393 +#define _EXPAND_METHOD 392 +#define _EXPAND_METHOD_KW 393 +#define _FATAL_ERROR 394 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 394 -#define _FOR_ITER_GEN_FRAME 395 -#define _FOR_ITER_TIER_TWO 396 +#define _FOR_ITER 395 +#define _FOR_ITER_GEN_FRAME 396 +#define _FOR_ITER_TIER_TWO 397 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE #define _GET_ITER GET_ITER #define _GET_LEN GET_LEN -#define _GUARD_BINARY_OP_EXTEND 397 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 398 -#define _GUARD_BIT_IS_SET_POP 399 -#define _GUARD_BIT_IS_SET_POP_4 400 -#define _GUARD_BIT_IS_SET_POP_5 401 -#define _GUARD_BIT_IS_SET_POP_6 402 -#define _GUARD_BIT_IS_SET_POP_7 403 -#define _GUARD_BIT_IS_UNSET_POP 404 -#define _GUARD_BIT_IS_UNSET_POP_4 405 -#define _GUARD_BIT_IS_UNSET_POP_5 406 -#define _GUARD_BIT_IS_UNSET_POP_6 407 -#define _GUARD_BIT_IS_UNSET_POP_7 408 -#define _GUARD_CALLABLE_BUILTIN_FAST 409 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 410 -#define _GUARD_CALLABLE_BUILTIN_O 411 -#define _GUARD_CALLABLE_ISINSTANCE 412 -#define _GUARD_CALLABLE_LEN 413 -#define _GUARD_CALLABLE_LIST_APPEND 414 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 415 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 416 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 417 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 418 -#define _GUARD_CALLABLE_STR_1 419 -#define _GUARD_CALLABLE_TUPLE_1 420 -#define _GUARD_CALLABLE_TYPE_1 421 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR 422 -#define _GUARD_CODE_VERSION_RETURN_VALUE 423 -#define _GUARD_CODE_VERSION_YIELD_VALUE 424 -#define _GUARD_CODE_VERSION__PUSH_FRAME 425 -#define _GUARD_DORV_NO_DICT 426 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 427 -#define _GUARD_GLOBALS_VERSION 428 -#define _GUARD_IP_RETURN_GENERATOR 429 -#define _GUARD_IP_RETURN_VALUE 430 -#define _GUARD_IP_YIELD_VALUE 431 -#define _GUARD_IP__PUSH_FRAME 432 -#define _GUARD_IS_FALSE_POP 433 -#define _GUARD_IS_NONE_POP 434 -#define _GUARD_IS_NOT_NONE_POP 435 -#define _GUARD_IS_TRUE_POP 436 -#define _GUARD_KEYS_VERSION 437 -#define _GUARD_NOS_ANY_DICT 438 -#define _GUARD_NOS_COMPACT_ASCII 439 -#define _GUARD_NOS_DICT 440 -#define _GUARD_NOS_FLOAT 441 -#define _GUARD_NOS_INT 442 -#define _GUARD_NOS_LIST 443 -#define _GUARD_NOS_NOT_NULL 444 -#define _GUARD_NOS_NULL 445 -#define _GUARD_NOS_OVERFLOWED 446 -#define _GUARD_NOS_TUPLE 447 -#define _GUARD_NOS_UNICODE 448 -#define _GUARD_NOT_EXHAUSTED_LIST 449 -#define _GUARD_NOT_EXHAUSTED_RANGE 450 -#define _GUARD_NOT_EXHAUSTED_TUPLE 451 -#define _GUARD_THIRD_NULL 452 -#define _GUARD_TOS_ANY_DICT 453 -#define _GUARD_TOS_ANY_SET 454 -#define _GUARD_TOS_DICT 455 -#define _GUARD_TOS_FLOAT 456 -#define _GUARD_TOS_FROZENDICT 457 -#define _GUARD_TOS_FROZENSET 458 -#define _GUARD_TOS_INT 459 -#define _GUARD_TOS_LIST 460 -#define _GUARD_TOS_OVERFLOWED 461 -#define _GUARD_TOS_SET 462 -#define _GUARD_TOS_SLICE 463 -#define _GUARD_TOS_TUPLE 464 -#define _GUARD_TOS_UNICODE 465 -#define _GUARD_TYPE_VERSION 466 -#define _GUARD_TYPE_VERSION_LOCKED 467 -#define _HANDLE_PENDING_AND_DEOPT 468 +#define _GUARD_BINARY_OP_EXTEND 398 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 399 +#define _GUARD_BIT_IS_SET_POP 400 +#define _GUARD_BIT_IS_SET_POP_4 401 +#define _GUARD_BIT_IS_SET_POP_5 402 +#define _GUARD_BIT_IS_SET_POP_6 403 +#define _GUARD_BIT_IS_SET_POP_7 404 +#define _GUARD_BIT_IS_UNSET_POP 405 +#define _GUARD_BIT_IS_UNSET_POP_4 406 +#define _GUARD_BIT_IS_UNSET_POP_5 407 +#define _GUARD_BIT_IS_UNSET_POP_6 408 +#define _GUARD_BIT_IS_UNSET_POP_7 409 +#define _GUARD_CALLABLE_BUILTIN_FAST 410 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 411 +#define _GUARD_CALLABLE_BUILTIN_O 412 +#define _GUARD_CALLABLE_ISINSTANCE 413 +#define _GUARD_CALLABLE_LEN 414 +#define _GUARD_CALLABLE_LIST_APPEND 415 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 416 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 417 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 418 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 419 +#define _GUARD_CALLABLE_STR_1 420 +#define _GUARD_CALLABLE_TUPLE_1 421 +#define _GUARD_CALLABLE_TYPE_1 422 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR 423 +#define _GUARD_CODE_VERSION_RETURN_VALUE 424 +#define _GUARD_CODE_VERSION_YIELD_VALUE 425 +#define _GUARD_CODE_VERSION__PUSH_FRAME 426 +#define _GUARD_DORV_NO_DICT 427 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 428 +#define _GUARD_GLOBALS_VERSION 429 +#define _GUARD_IP_RETURN_GENERATOR 430 +#define _GUARD_IP_RETURN_VALUE 431 +#define _GUARD_IP_YIELD_VALUE 432 +#define _GUARD_IP__PUSH_FRAME 433 +#define _GUARD_IS_FALSE_POP 434 +#define _GUARD_IS_NONE_POP 435 +#define _GUARD_IS_NOT_NONE_POP 436 +#define _GUARD_IS_TRUE_POP 437 +#define _GUARD_KEYS_VERSION 438 +#define _GUARD_NOS_ANY_DICT 439 +#define _GUARD_NOS_COMPACT_ASCII 440 +#define _GUARD_NOS_DICT 441 +#define _GUARD_NOS_FLOAT 442 +#define _GUARD_NOS_INT 443 +#define _GUARD_NOS_LIST 444 +#define _GUARD_NOS_NOT_NULL 445 +#define _GUARD_NOS_NULL 446 +#define _GUARD_NOS_OVERFLOWED 447 +#define _GUARD_NOS_TUPLE 448 +#define _GUARD_NOS_UNICODE 449 +#define _GUARD_NOT_EXHAUSTED_LIST 450 +#define _GUARD_NOT_EXHAUSTED_RANGE 451 +#define _GUARD_NOT_EXHAUSTED_TUPLE 452 +#define _GUARD_THIRD_NULL 453 +#define _GUARD_TOS_ANY_DICT 454 +#define _GUARD_TOS_ANY_SET 455 +#define _GUARD_TOS_DICT 456 +#define _GUARD_TOS_FLOAT 457 +#define _GUARD_TOS_FROZENDICT 458 +#define _GUARD_TOS_FROZENSET 459 +#define _GUARD_TOS_INT 460 +#define _GUARD_TOS_LIST 461 +#define _GUARD_TOS_OVERFLOWED 462 +#define _GUARD_TOS_SET 463 +#define _GUARD_TOS_SLICE 464 +#define _GUARD_TOS_TUPLE 465 +#define _GUARD_TOS_UNICODE 466 +#define _GUARD_TYPE_VERSION 467 +#define _GUARD_TYPE_VERSION_LOCKED 468 +#define _HANDLE_PENDING_AND_DEOPT 469 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 469 -#define _INIT_CALL_PY_EXACT_ARGS 470 -#define _INIT_CALL_PY_EXACT_ARGS_0 471 -#define _INIT_CALL_PY_EXACT_ARGS_1 472 -#define _INIT_CALL_PY_EXACT_ARGS_2 473 -#define _INIT_CALL_PY_EXACT_ARGS_3 474 -#define _INIT_CALL_PY_EXACT_ARGS_4 475 -#define _INSERT_1_LOAD_CONST_INLINE 476 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW 477 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW 478 -#define _INSERT_NULL 479 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 470 +#define _INIT_CALL_PY_EXACT_ARGS 471 +#define _INIT_CALL_PY_EXACT_ARGS_0 472 +#define _INIT_CALL_PY_EXACT_ARGS_1 473 +#define _INIT_CALL_PY_EXACT_ARGS_2 474 +#define _INIT_CALL_PY_EXACT_ARGS_3 475 +#define _INIT_CALL_PY_EXACT_ARGS_4 476 +#define _INSERT_1_LOAD_CONST_INLINE 477 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW 478 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW 479 +#define _INSERT_NULL 480 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -228,1125 +229,1128 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 480 -#define _IS_OP 481 -#define _ITER_CHECK_LIST 482 -#define _ITER_CHECK_RANGE 483 -#define _ITER_CHECK_TUPLE 484 -#define _ITER_JUMP_LIST 485 -#define _ITER_JUMP_RANGE 486 -#define _ITER_JUMP_TUPLE 487 -#define _ITER_NEXT_LIST 488 -#define _ITER_NEXT_LIST_TIER_TWO 489 -#define _ITER_NEXT_RANGE 490 -#define _ITER_NEXT_TUPLE 491 +#define _IS_NONE 481 +#define _IS_OP 482 +#define _ITER_CHECK_LIST 483 +#define _ITER_CHECK_RANGE 484 +#define _ITER_CHECK_TUPLE 485 +#define _ITER_JUMP_LIST 486 +#define _ITER_JUMP_RANGE 487 +#define _ITER_JUMP_TUPLE 488 +#define _ITER_NEXT_LIST 489 +#define _ITER_NEXT_LIST_TIER_TWO 490 +#define _ITER_NEXT_RANGE 491 +#define _ITER_NEXT_TUPLE 492 #define _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT -#define _JUMP_TO_TOP 492 +#define _JUMP_TO_TOP 493 #define _LIST_APPEND LIST_APPEND -#define _LIST_EXTEND 493 -#define _LOAD_ATTR 494 -#define _LOAD_ATTR_CLASS 495 +#define _LIST_EXTEND 494 +#define _LOAD_ATTR 495 +#define _LOAD_ATTR_CLASS 496 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 496 -#define _LOAD_ATTR_METHOD_LAZY_DICT 497 -#define _LOAD_ATTR_METHOD_NO_DICT 498 -#define _LOAD_ATTR_METHOD_WITH_VALUES 499 -#define _LOAD_ATTR_MODULE 500 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 501 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 502 -#define _LOAD_ATTR_PROPERTY_FRAME 503 -#define _LOAD_ATTR_SLOT 504 -#define _LOAD_ATTR_WITH_HINT 505 +#define _LOAD_ATTR_INSTANCE_VALUE 497 +#define _LOAD_ATTR_METHOD_LAZY_DICT 498 +#define _LOAD_ATTR_METHOD_NO_DICT 499 +#define _LOAD_ATTR_METHOD_WITH_VALUES 500 +#define _LOAD_ATTR_MODULE 501 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 502 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 503 +#define _LOAD_ATTR_PROPERTY_FRAME 504 +#define _LOAD_ATTR_SLOT 505 +#define _LOAD_ATTR_WITH_HINT 506 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 506 +#define _LOAD_BYTECODE 507 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 507 -#define _LOAD_CONST_INLINE_BORROW 508 -#define _LOAD_CONST_UNDER_INLINE 509 -#define _LOAD_CONST_UNDER_INLINE_BORROW 510 +#define _LOAD_CONST_INLINE 508 +#define _LOAD_CONST_INLINE_BORROW 509 +#define _LOAD_CONST_UNDER_INLINE 510 +#define _LOAD_CONST_UNDER_INLINE_BORROW 511 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 511 -#define _LOAD_FAST_0 512 -#define _LOAD_FAST_1 513 -#define _LOAD_FAST_2 514 -#define _LOAD_FAST_3 515 -#define _LOAD_FAST_4 516 -#define _LOAD_FAST_5 517 -#define _LOAD_FAST_6 518 -#define _LOAD_FAST_7 519 +#define _LOAD_FAST 512 +#define _LOAD_FAST_0 513 +#define _LOAD_FAST_1 514 +#define _LOAD_FAST_2 515 +#define _LOAD_FAST_3 516 +#define _LOAD_FAST_4 517 +#define _LOAD_FAST_5 518 +#define _LOAD_FAST_6 519 +#define _LOAD_FAST_7 520 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 520 -#define _LOAD_FAST_BORROW_0 521 -#define _LOAD_FAST_BORROW_1 522 -#define _LOAD_FAST_BORROW_2 523 -#define _LOAD_FAST_BORROW_3 524 -#define _LOAD_FAST_BORROW_4 525 -#define _LOAD_FAST_BORROW_5 526 -#define _LOAD_FAST_BORROW_6 527 -#define _LOAD_FAST_BORROW_7 528 +#define _LOAD_FAST_BORROW 521 +#define _LOAD_FAST_BORROW_0 522 +#define _LOAD_FAST_BORROW_1 523 +#define _LOAD_FAST_BORROW_2 524 +#define _LOAD_FAST_BORROW_3 525 +#define _LOAD_FAST_BORROW_4 526 +#define _LOAD_FAST_BORROW_5 527 +#define _LOAD_FAST_BORROW_6 528 +#define _LOAD_FAST_BORROW_7 529 #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 529 -#define _LOAD_GLOBAL_BUILTINS 530 -#define _LOAD_GLOBAL_MODULE 531 +#define _LOAD_GLOBAL 530 +#define _LOAD_GLOBAL_BUILTINS 531 +#define _LOAD_GLOBAL_MODULE 532 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 532 -#define _LOAD_SMALL_INT_0 533 -#define _LOAD_SMALL_INT_1 534 -#define _LOAD_SMALL_INT_2 535 -#define _LOAD_SMALL_INT_3 536 -#define _LOAD_SPECIAL 537 +#define _LOAD_SMALL_INT 533 +#define _LOAD_SMALL_INT_0 534 +#define _LOAD_SMALL_INT_1 535 +#define _LOAD_SMALL_INT_2 536 +#define _LOAD_SMALL_INT_3 537 +#define _LOAD_SPECIAL 538 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _LOCK_OBJECT 538 -#define _MAKE_CALLARGS_A_TUPLE 539 +#define _LOCK_OBJECT 539 +#define _MAKE_CALLARGS_A_TUPLE 540 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_HEAP_SAFE 540 -#define _MAKE_WARM 541 +#define _MAKE_HEAP_SAFE 541 +#define _MAKE_WARM 542 #define _MAP_ADD MAP_ADD -#define _MATCH_CLASS 542 +#define _MATCH_CLASS 543 #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 543 -#define _MAYBE_EXPAND_METHOD_KW 544 -#define _MONITOR_CALL 545 -#define _MONITOR_CALL_KW 546 -#define _MONITOR_JUMP_BACKWARD 547 -#define _MONITOR_RESUME 548 +#define _MAYBE_EXPAND_METHOD 544 +#define _MAYBE_EXPAND_METHOD_KW 545 +#define _MONITOR_CALL 546 +#define _MONITOR_CALL_KW 547 +#define _MONITOR_JUMP_BACKWARD 548 +#define _MONITOR_RESUME 549 #define _NOP NOP -#define _POP_CALL 549 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 550 -#define _POP_CALL_ONE 551 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 552 -#define _POP_CALL_TWO 553 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 554 +#define _POP_CALL 550 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 551 +#define _POP_CALL_ONE 552 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 553 +#define _POP_CALL_TWO 554 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 555 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 555 -#define _POP_JUMP_IF_TRUE 556 +#define _POP_JUMP_IF_FALSE 556 +#define _POP_JUMP_IF_TRUE 557 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 557 -#define _POP_TOP_INT 558 -#define _POP_TOP_LOAD_CONST_INLINE 559 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 560 -#define _POP_TOP_NOP 561 -#define _POP_TOP_UNICODE 562 -#define _POP_TWO 563 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 564 +#define _POP_TOP_FLOAT 558 +#define _POP_TOP_INT 559 +#define _POP_TOP_LOAD_CONST_INLINE 560 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 561 +#define _POP_TOP_NOP 562 +#define _POP_TOP_UNICODE 563 +#define _POP_TWO 564 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 565 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 565 +#define _PUSH_FRAME 566 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 566 -#define _PY_FRAME_EX 567 -#define _PY_FRAME_GENERAL 568 -#define _PY_FRAME_KW 569 -#define _RECORD_3OS_GEN_FUNC 570 -#define _RECORD_4OS 571 -#define _RECORD_BOUND_METHOD 572 -#define _RECORD_CALLABLE 573 -#define _RECORD_CODE 574 -#define _RECORD_NOS 575 -#define _RECORD_NOS_GEN_FUNC 576 -#define _RECORD_TOS 577 -#define _RECORD_TOS_TYPE 578 -#define _REPLACE_WITH_TRUE 579 -#define _RESUME_CHECK 580 +#define _PUSH_NULL_CONDITIONAL 567 +#define _PY_FRAME_EX 568 +#define _PY_FRAME_GENERAL 569 +#define _PY_FRAME_KW 570 +#define _RECORD_3OS_GEN_FUNC 571 +#define _RECORD_4OS 572 +#define _RECORD_BOUND_METHOD 573 +#define _RECORD_CALLABLE 574 +#define _RECORD_CODE 575 +#define _RECORD_NOS 576 +#define _RECORD_NOS_GEN_FUNC 577 +#define _RECORD_TOS 578 +#define _RECORD_TOS_TYPE 579 +#define _REPLACE_WITH_TRUE 580 +#define _RESUME_CHECK 581 #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE 581 -#define _SAVE_RETURN_OFFSET 582 -#define _SEND 583 -#define _SEND_GEN_FRAME 584 +#define _RETURN_VALUE 582 +#define _SAVE_RETURN_OFFSET 583 +#define _SEND 584 +#define _SEND_GEN_FRAME 585 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE -#define _SET_UPDATE 585 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 586 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 587 -#define _SPILL_OR_RELOAD 588 -#define _START_EXECUTOR 589 -#define _STORE_ATTR 590 -#define _STORE_ATTR_INSTANCE_VALUE 591 -#define _STORE_ATTR_SLOT 592 -#define _STORE_ATTR_WITH_HINT 593 +#define _SET_UPDATE 586 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 587 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 588 +#define _SPILL_OR_RELOAD 589 +#define _START_EXECUTOR 590 +#define _STORE_ATTR 591 +#define _STORE_ATTR_INSTANCE_VALUE 592 +#define _STORE_ATTR_SLOT 593 +#define _STORE_ATTR_WITH_HINT 594 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 594 -#define _STORE_SUBSCR 595 -#define _STORE_SUBSCR_DICT 596 -#define _STORE_SUBSCR_LIST_INT 597 -#define _SWAP 598 -#define _SWAP_2 599 -#define _SWAP_3 600 -#define _SWAP_FAST 601 -#define _SWAP_FAST_0 602 -#define _SWAP_FAST_1 603 -#define _SWAP_FAST_2 604 -#define _SWAP_FAST_3 605 -#define _SWAP_FAST_4 606 -#define _SWAP_FAST_5 607 -#define _SWAP_FAST_6 608 -#define _SWAP_FAST_7 609 -#define _TIER2_RESUME_CHECK 610 -#define _TO_BOOL 611 +#define _STORE_SLICE 595 +#define _STORE_SUBSCR 596 +#define _STORE_SUBSCR_DICT 597 +#define _STORE_SUBSCR_DICT_KNOWN_HASH 598 +#define _STORE_SUBSCR_LIST_INT 599 +#define _SWAP 600 +#define _SWAP_2 601 +#define _SWAP_3 602 +#define _SWAP_FAST 603 +#define _SWAP_FAST_0 604 +#define _SWAP_FAST_1 605 +#define _SWAP_FAST_2 606 +#define _SWAP_FAST_3 607 +#define _SWAP_FAST_4 608 +#define _SWAP_FAST_5 609 +#define _SWAP_FAST_6 610 +#define _SWAP_FAST_7 611 +#define _TIER2_RESUME_CHECK 612 +#define _TO_BOOL 613 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 612 -#define _TO_BOOL_LIST 613 +#define _TO_BOOL_INT 614 +#define _TO_BOOL_LIST 615 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 614 +#define _TO_BOOL_STR 616 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 615 -#define _UNARY_NEGATIVE 616 -#define _UNARY_NEGATIVE_FLOAT_INPLACE 617 +#define _UNARY_INVERT 617 +#define _UNARY_NEGATIVE 618 +#define _UNARY_NEGATIVE_FLOAT_INPLACE 619 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 618 -#define _UNPACK_SEQUENCE_LIST 619 -#define _UNPACK_SEQUENCE_TUPLE 620 -#define _UNPACK_SEQUENCE_TWO_TUPLE 621 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 622 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 623 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 624 +#define _UNPACK_SEQUENCE 620 +#define _UNPACK_SEQUENCE_LIST 621 +#define _UNPACK_SEQUENCE_TUPLE 622 +#define _UNPACK_SEQUENCE_TWO_TUPLE 623 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 624 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 625 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 626 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 625 -#define MAX_UOP_ID 625 -#define _BINARY_OP_r23 626 -#define _BINARY_OP_ADD_FLOAT_r03 627 -#define _BINARY_OP_ADD_FLOAT_r13 628 -#define _BINARY_OP_ADD_FLOAT_r23 629 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 630 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 631 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 632 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 633 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 634 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 635 -#define _BINARY_OP_ADD_INT_r03 636 -#define _BINARY_OP_ADD_INT_r13 637 -#define _BINARY_OP_ADD_INT_r23 638 -#define _BINARY_OP_ADD_UNICODE_r03 639 -#define _BINARY_OP_ADD_UNICODE_r13 640 -#define _BINARY_OP_ADD_UNICODE_r23 641 -#define _BINARY_OP_EXTEND_r23 642 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 643 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 644 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 645 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 646 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 647 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 648 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 649 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 650 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 651 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 652 -#define _BINARY_OP_MULTIPLY_INT_r03 653 -#define _BINARY_OP_MULTIPLY_INT_r13 654 -#define _BINARY_OP_MULTIPLY_INT_r23 655 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 656 -#define _BINARY_OP_SUBSCR_DICT_r23 657 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 658 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 659 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 660 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 661 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 662 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 663 -#define _BINARY_OP_SUBSCR_STR_INT_r23 664 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 665 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 666 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 667 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 668 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 669 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 670 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 671 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 672 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 673 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 674 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 675 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 676 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 677 -#define _BINARY_OP_SUBTRACT_INT_r03 678 -#define _BINARY_OP_SUBTRACT_INT_r13 679 -#define _BINARY_OP_SUBTRACT_INT_r23 680 -#define _BINARY_SLICE_r31 681 -#define _BUILD_INTERPOLATION_r01 682 -#define _BUILD_LIST_r01 683 -#define _BUILD_MAP_r01 684 -#define _BUILD_SET_r01 685 -#define _BUILD_SLICE_r01 686 -#define _BUILD_STRING_r01 687 -#define _BUILD_TEMPLATE_r21 688 -#define _BUILD_TUPLE_r01 689 -#define _CALL_BUILTIN_CLASS_r01 690 -#define _CALL_BUILTIN_FAST_r01 691 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 692 -#define _CALL_BUILTIN_O_r03 693 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 694 -#define _CALL_INTRINSIC_1_r12 695 -#define _CALL_INTRINSIC_2_r23 696 -#define _CALL_ISINSTANCE_r31 697 -#define _CALL_KW_NON_PY_r11 698 -#define _CALL_LEN_r33 699 -#define _CALL_LIST_APPEND_r03 700 -#define _CALL_LIST_APPEND_r13 701 -#define _CALL_LIST_APPEND_r23 702 -#define _CALL_LIST_APPEND_r33 703 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 704 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 705 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 706 -#define _CALL_METHOD_DESCRIPTOR_O_r03 707 -#define _CALL_NON_PY_GENERAL_r01 708 -#define _CALL_STR_1_r32 709 -#define _CALL_TUPLE_1_r32 710 -#define _CALL_TYPE_1_r02 711 -#define _CALL_TYPE_1_r12 712 -#define _CALL_TYPE_1_r22 713 -#define _CALL_TYPE_1_r32 714 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 715 -#define _CHECK_ATTR_CLASS_r01 716 -#define _CHECK_ATTR_CLASS_r11 717 -#define _CHECK_ATTR_CLASS_r22 718 -#define _CHECK_ATTR_CLASS_r33 719 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 720 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 721 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 722 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 723 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 724 -#define _CHECK_EG_MATCH_r22 725 -#define _CHECK_EXC_MATCH_r22 726 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 727 -#define _CHECK_FUNCTION_VERSION_r00 728 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 729 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 730 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 731 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 732 -#define _CHECK_FUNCTION_VERSION_KW_r11 733 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 734 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 735 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 736 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 737 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 738 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 739 -#define _CHECK_IS_PY_CALLABLE_EX_r03 740 -#define _CHECK_IS_PY_CALLABLE_EX_r13 741 -#define _CHECK_IS_PY_CALLABLE_EX_r23 742 -#define _CHECK_IS_PY_CALLABLE_EX_r33 743 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 744 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 745 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 746 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 747 -#define _CHECK_METHOD_VERSION_r00 748 -#define _CHECK_METHOD_VERSION_KW_r11 749 -#define _CHECK_PEP_523_r00 750 -#define _CHECK_PEP_523_r11 751 -#define _CHECK_PEP_523_r22 752 -#define _CHECK_PEP_523_r33 753 -#define _CHECK_PERIODIC_r00 754 -#define _CHECK_PERIODIC_AT_END_r00 755 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 756 -#define _CHECK_RECURSION_REMAINING_r00 757 -#define _CHECK_RECURSION_REMAINING_r11 758 -#define _CHECK_RECURSION_REMAINING_r22 759 -#define _CHECK_RECURSION_REMAINING_r33 760 -#define _CHECK_STACK_SPACE_r00 761 -#define _CHECK_STACK_SPACE_OPERAND_r00 762 -#define _CHECK_STACK_SPACE_OPERAND_r11 763 -#define _CHECK_STACK_SPACE_OPERAND_r22 764 -#define _CHECK_STACK_SPACE_OPERAND_r33 765 -#define _CHECK_VALIDITY_r00 766 -#define _CHECK_VALIDITY_r11 767 -#define _CHECK_VALIDITY_r22 768 -#define _CHECK_VALIDITY_r33 769 -#define _COLD_DYNAMIC_EXIT_r00 770 -#define _COLD_EXIT_r00 771 -#define _COMPARE_OP_r21 772 -#define _COMPARE_OP_FLOAT_r03 773 -#define _COMPARE_OP_FLOAT_r13 774 -#define _COMPARE_OP_FLOAT_r23 775 -#define _COMPARE_OP_INT_r23 776 -#define _COMPARE_OP_STR_r23 777 -#define _CONTAINS_OP_r23 778 -#define _CONTAINS_OP_DICT_r23 779 -#define _CONTAINS_OP_SET_r23 780 -#define _CONVERT_VALUE_r11 781 -#define _COPY_r01 782 -#define _COPY_1_r02 783 -#define _COPY_1_r12 784 -#define _COPY_1_r23 785 -#define _COPY_2_r03 786 -#define _COPY_2_r13 787 -#define _COPY_2_r23 788 -#define _COPY_3_r03 789 -#define _COPY_3_r13 790 -#define _COPY_3_r23 791 -#define _COPY_3_r33 792 -#define _COPY_FREE_VARS_r00 793 -#define _COPY_FREE_VARS_r11 794 -#define _COPY_FREE_VARS_r22 795 -#define _COPY_FREE_VARS_r33 796 -#define _CREATE_INIT_FRAME_r01 797 -#define _DELETE_ATTR_r10 798 -#define _DELETE_DEREF_r00 799 -#define _DELETE_FAST_r00 800 -#define _DELETE_GLOBAL_r00 801 -#define _DELETE_NAME_r00 802 -#define _DELETE_SUBSCR_r20 803 -#define _DEOPT_r00 804 -#define _DEOPT_r10 805 -#define _DEOPT_r20 806 -#define _DEOPT_r30 807 -#define _DICT_MERGE_r11 808 -#define _DICT_UPDATE_r11 809 -#define _DO_CALL_r01 810 -#define _DO_CALL_FUNCTION_EX_r31 811 -#define _DO_CALL_KW_r11 812 -#define _DYNAMIC_EXIT_r00 813 -#define _DYNAMIC_EXIT_r10 814 -#define _DYNAMIC_EXIT_r20 815 -#define _DYNAMIC_EXIT_r30 816 -#define _END_FOR_r10 817 -#define _END_SEND_r31 818 -#define _ERROR_POP_N_r00 819 -#define _EXIT_INIT_CHECK_r10 820 -#define _EXIT_TRACE_r00 821 -#define _EXIT_TRACE_r10 822 -#define _EXIT_TRACE_r20 823 -#define _EXIT_TRACE_r30 824 -#define _EXPAND_METHOD_r00 825 -#define _EXPAND_METHOD_KW_r11 826 -#define _FATAL_ERROR_r00 827 -#define _FATAL_ERROR_r11 828 -#define _FATAL_ERROR_r22 829 -#define _FATAL_ERROR_r33 830 -#define _FORMAT_SIMPLE_r11 831 -#define _FORMAT_WITH_SPEC_r21 832 -#define _FOR_ITER_r23 833 -#define _FOR_ITER_GEN_FRAME_r03 834 -#define _FOR_ITER_GEN_FRAME_r13 835 -#define _FOR_ITER_GEN_FRAME_r23 836 -#define _FOR_ITER_TIER_TWO_r23 837 -#define _GET_AITER_r11 838 -#define _GET_ANEXT_r12 839 -#define _GET_AWAITABLE_r11 840 -#define _GET_ITER_r12 841 -#define _GET_LEN_r12 842 -#define _GUARD_BINARY_OP_EXTEND_r22 843 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 844 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 845 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 846 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 847 -#define _GUARD_BIT_IS_SET_POP_r00 848 -#define _GUARD_BIT_IS_SET_POP_r10 849 -#define _GUARD_BIT_IS_SET_POP_r21 850 -#define _GUARD_BIT_IS_SET_POP_r32 851 -#define _GUARD_BIT_IS_SET_POP_4_r00 852 -#define _GUARD_BIT_IS_SET_POP_4_r10 853 -#define _GUARD_BIT_IS_SET_POP_4_r21 854 -#define _GUARD_BIT_IS_SET_POP_4_r32 855 -#define _GUARD_BIT_IS_SET_POP_5_r00 856 -#define _GUARD_BIT_IS_SET_POP_5_r10 857 -#define _GUARD_BIT_IS_SET_POP_5_r21 858 -#define _GUARD_BIT_IS_SET_POP_5_r32 859 -#define _GUARD_BIT_IS_SET_POP_6_r00 860 -#define _GUARD_BIT_IS_SET_POP_6_r10 861 -#define _GUARD_BIT_IS_SET_POP_6_r21 862 -#define _GUARD_BIT_IS_SET_POP_6_r32 863 -#define _GUARD_BIT_IS_SET_POP_7_r00 864 -#define _GUARD_BIT_IS_SET_POP_7_r10 865 -#define _GUARD_BIT_IS_SET_POP_7_r21 866 -#define _GUARD_BIT_IS_SET_POP_7_r32 867 -#define _GUARD_BIT_IS_UNSET_POP_r00 868 -#define _GUARD_BIT_IS_UNSET_POP_r10 869 -#define _GUARD_BIT_IS_UNSET_POP_r21 870 -#define _GUARD_BIT_IS_UNSET_POP_r32 871 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 872 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 873 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 874 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 875 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 876 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 877 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 878 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 879 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 880 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 881 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 882 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 883 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 884 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 885 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 886 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 887 -#define _GUARD_CALLABLE_BUILTIN_FAST_r00 888 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 889 -#define _GUARD_CALLABLE_BUILTIN_O_r00 890 -#define _GUARD_CALLABLE_ISINSTANCE_r03 891 -#define _GUARD_CALLABLE_ISINSTANCE_r13 892 -#define _GUARD_CALLABLE_ISINSTANCE_r23 893 -#define _GUARD_CALLABLE_ISINSTANCE_r33 894 -#define _GUARD_CALLABLE_LEN_r03 895 -#define _GUARD_CALLABLE_LEN_r13 896 -#define _GUARD_CALLABLE_LEN_r23 897 -#define _GUARD_CALLABLE_LEN_r33 898 -#define _GUARD_CALLABLE_LIST_APPEND_r03 899 -#define _GUARD_CALLABLE_LIST_APPEND_r13 900 -#define _GUARD_CALLABLE_LIST_APPEND_r23 901 -#define _GUARD_CALLABLE_LIST_APPEND_r33 902 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 903 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 904 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 905 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 906 -#define _GUARD_CALLABLE_STR_1_r03 907 -#define _GUARD_CALLABLE_STR_1_r13 908 -#define _GUARD_CALLABLE_STR_1_r23 909 -#define _GUARD_CALLABLE_STR_1_r33 910 -#define _GUARD_CALLABLE_TUPLE_1_r03 911 -#define _GUARD_CALLABLE_TUPLE_1_r13 912 -#define _GUARD_CALLABLE_TUPLE_1_r23 913 -#define _GUARD_CALLABLE_TUPLE_1_r33 914 -#define _GUARD_CALLABLE_TYPE_1_r03 915 -#define _GUARD_CALLABLE_TYPE_1_r13 916 -#define _GUARD_CALLABLE_TYPE_1_r23 917 -#define _GUARD_CALLABLE_TYPE_1_r33 918 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 919 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 920 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 921 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 922 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 923 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 924 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 925 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 926 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 927 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 928 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 929 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 930 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 931 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 932 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 933 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 934 -#define _GUARD_DORV_NO_DICT_r01 935 -#define _GUARD_DORV_NO_DICT_r11 936 -#define _GUARD_DORV_NO_DICT_r22 937 -#define _GUARD_DORV_NO_DICT_r33 938 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 939 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 940 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 941 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 942 -#define _GUARD_GLOBALS_VERSION_r00 943 -#define _GUARD_GLOBALS_VERSION_r11 944 -#define _GUARD_GLOBALS_VERSION_r22 945 -#define _GUARD_GLOBALS_VERSION_r33 946 -#define _GUARD_IP_RETURN_GENERATOR_r00 947 -#define _GUARD_IP_RETURN_GENERATOR_r11 948 -#define _GUARD_IP_RETURN_GENERATOR_r22 949 -#define _GUARD_IP_RETURN_GENERATOR_r33 950 -#define _GUARD_IP_RETURN_VALUE_r00 951 -#define _GUARD_IP_RETURN_VALUE_r11 952 -#define _GUARD_IP_RETURN_VALUE_r22 953 -#define _GUARD_IP_RETURN_VALUE_r33 954 -#define _GUARD_IP_YIELD_VALUE_r00 955 -#define _GUARD_IP_YIELD_VALUE_r11 956 -#define _GUARD_IP_YIELD_VALUE_r22 957 -#define _GUARD_IP_YIELD_VALUE_r33 958 -#define _GUARD_IP__PUSH_FRAME_r00 959 -#define _GUARD_IP__PUSH_FRAME_r11 960 -#define _GUARD_IP__PUSH_FRAME_r22 961 -#define _GUARD_IP__PUSH_FRAME_r33 962 -#define _GUARD_IS_FALSE_POP_r00 963 -#define _GUARD_IS_FALSE_POP_r10 964 -#define _GUARD_IS_FALSE_POP_r21 965 -#define _GUARD_IS_FALSE_POP_r32 966 -#define _GUARD_IS_NONE_POP_r00 967 -#define _GUARD_IS_NONE_POP_r10 968 -#define _GUARD_IS_NONE_POP_r21 969 -#define _GUARD_IS_NONE_POP_r32 970 -#define _GUARD_IS_NOT_NONE_POP_r10 971 -#define _GUARD_IS_TRUE_POP_r00 972 -#define _GUARD_IS_TRUE_POP_r10 973 -#define _GUARD_IS_TRUE_POP_r21 974 -#define _GUARD_IS_TRUE_POP_r32 975 -#define _GUARD_KEYS_VERSION_r01 976 -#define _GUARD_KEYS_VERSION_r11 977 -#define _GUARD_KEYS_VERSION_r22 978 -#define _GUARD_KEYS_VERSION_r33 979 -#define _GUARD_NOS_ANY_DICT_r02 980 -#define _GUARD_NOS_ANY_DICT_r12 981 -#define _GUARD_NOS_ANY_DICT_r22 982 -#define _GUARD_NOS_ANY_DICT_r33 983 -#define _GUARD_NOS_COMPACT_ASCII_r02 984 -#define _GUARD_NOS_COMPACT_ASCII_r12 985 -#define _GUARD_NOS_COMPACT_ASCII_r22 986 -#define _GUARD_NOS_COMPACT_ASCII_r33 987 -#define _GUARD_NOS_DICT_r02 988 -#define _GUARD_NOS_DICT_r12 989 -#define _GUARD_NOS_DICT_r22 990 -#define _GUARD_NOS_DICT_r33 991 -#define _GUARD_NOS_FLOAT_r02 992 -#define _GUARD_NOS_FLOAT_r12 993 -#define _GUARD_NOS_FLOAT_r22 994 -#define _GUARD_NOS_FLOAT_r33 995 -#define _GUARD_NOS_INT_r02 996 -#define _GUARD_NOS_INT_r12 997 -#define _GUARD_NOS_INT_r22 998 -#define _GUARD_NOS_INT_r33 999 -#define _GUARD_NOS_LIST_r02 1000 -#define _GUARD_NOS_LIST_r12 1001 -#define _GUARD_NOS_LIST_r22 1002 -#define _GUARD_NOS_LIST_r33 1003 -#define _GUARD_NOS_NOT_NULL_r02 1004 -#define _GUARD_NOS_NOT_NULL_r12 1005 -#define _GUARD_NOS_NOT_NULL_r22 1006 -#define _GUARD_NOS_NOT_NULL_r33 1007 -#define _GUARD_NOS_NULL_r02 1008 -#define _GUARD_NOS_NULL_r12 1009 -#define _GUARD_NOS_NULL_r22 1010 -#define _GUARD_NOS_NULL_r33 1011 -#define _GUARD_NOS_OVERFLOWED_r02 1012 -#define _GUARD_NOS_OVERFLOWED_r12 1013 -#define _GUARD_NOS_OVERFLOWED_r22 1014 -#define _GUARD_NOS_OVERFLOWED_r33 1015 -#define _GUARD_NOS_TUPLE_r02 1016 -#define _GUARD_NOS_TUPLE_r12 1017 -#define _GUARD_NOS_TUPLE_r22 1018 -#define _GUARD_NOS_TUPLE_r33 1019 -#define _GUARD_NOS_UNICODE_r02 1020 -#define _GUARD_NOS_UNICODE_r12 1021 -#define _GUARD_NOS_UNICODE_r22 1022 -#define _GUARD_NOS_UNICODE_r33 1023 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 1024 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 1025 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 1026 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 1027 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1028 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1029 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1030 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1031 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1032 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1033 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1034 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1035 -#define _GUARD_THIRD_NULL_r03 1036 -#define _GUARD_THIRD_NULL_r13 1037 -#define _GUARD_THIRD_NULL_r23 1038 -#define _GUARD_THIRD_NULL_r33 1039 -#define _GUARD_TOS_ANY_DICT_r01 1040 -#define _GUARD_TOS_ANY_DICT_r11 1041 -#define _GUARD_TOS_ANY_DICT_r22 1042 -#define _GUARD_TOS_ANY_DICT_r33 1043 -#define _GUARD_TOS_ANY_SET_r01 1044 -#define _GUARD_TOS_ANY_SET_r11 1045 -#define _GUARD_TOS_ANY_SET_r22 1046 -#define _GUARD_TOS_ANY_SET_r33 1047 -#define _GUARD_TOS_DICT_r01 1048 -#define _GUARD_TOS_DICT_r11 1049 -#define _GUARD_TOS_DICT_r22 1050 -#define _GUARD_TOS_DICT_r33 1051 -#define _GUARD_TOS_FLOAT_r01 1052 -#define _GUARD_TOS_FLOAT_r11 1053 -#define _GUARD_TOS_FLOAT_r22 1054 -#define _GUARD_TOS_FLOAT_r33 1055 -#define _GUARD_TOS_FROZENDICT_r01 1056 -#define _GUARD_TOS_FROZENDICT_r11 1057 -#define _GUARD_TOS_FROZENDICT_r22 1058 -#define _GUARD_TOS_FROZENDICT_r33 1059 -#define _GUARD_TOS_FROZENSET_r01 1060 -#define _GUARD_TOS_FROZENSET_r11 1061 -#define _GUARD_TOS_FROZENSET_r22 1062 -#define _GUARD_TOS_FROZENSET_r33 1063 -#define _GUARD_TOS_INT_r01 1064 -#define _GUARD_TOS_INT_r11 1065 -#define _GUARD_TOS_INT_r22 1066 -#define _GUARD_TOS_INT_r33 1067 -#define _GUARD_TOS_LIST_r01 1068 -#define _GUARD_TOS_LIST_r11 1069 -#define _GUARD_TOS_LIST_r22 1070 -#define _GUARD_TOS_LIST_r33 1071 -#define _GUARD_TOS_OVERFLOWED_r01 1072 -#define _GUARD_TOS_OVERFLOWED_r11 1073 -#define _GUARD_TOS_OVERFLOWED_r22 1074 -#define _GUARD_TOS_OVERFLOWED_r33 1075 -#define _GUARD_TOS_SET_r01 1076 -#define _GUARD_TOS_SET_r11 1077 -#define _GUARD_TOS_SET_r22 1078 -#define _GUARD_TOS_SET_r33 1079 -#define _GUARD_TOS_SLICE_r01 1080 -#define _GUARD_TOS_SLICE_r11 1081 -#define _GUARD_TOS_SLICE_r22 1082 -#define _GUARD_TOS_SLICE_r33 1083 -#define _GUARD_TOS_TUPLE_r01 1084 -#define _GUARD_TOS_TUPLE_r11 1085 -#define _GUARD_TOS_TUPLE_r22 1086 -#define _GUARD_TOS_TUPLE_r33 1087 -#define _GUARD_TOS_UNICODE_r01 1088 -#define _GUARD_TOS_UNICODE_r11 1089 -#define _GUARD_TOS_UNICODE_r22 1090 -#define _GUARD_TOS_UNICODE_r33 1091 -#define _GUARD_TYPE_VERSION_r01 1092 -#define _GUARD_TYPE_VERSION_r11 1093 -#define _GUARD_TYPE_VERSION_r22 1094 -#define _GUARD_TYPE_VERSION_r33 1095 -#define _GUARD_TYPE_VERSION_LOCKED_r01 1096 -#define _GUARD_TYPE_VERSION_LOCKED_r11 1097 -#define _GUARD_TYPE_VERSION_LOCKED_r22 1098 -#define _GUARD_TYPE_VERSION_LOCKED_r33 1099 -#define _HANDLE_PENDING_AND_DEOPT_r00 1100 -#define _HANDLE_PENDING_AND_DEOPT_r10 1101 -#define _HANDLE_PENDING_AND_DEOPT_r20 1102 -#define _HANDLE_PENDING_AND_DEOPT_r30 1103 -#define _IMPORT_FROM_r12 1104 -#define _IMPORT_NAME_r21 1105 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1106 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1107 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1108 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1109 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1110 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1111 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1112 -#define _INSERT_1_LOAD_CONST_INLINE_r02 1113 -#define _INSERT_1_LOAD_CONST_INLINE_r12 1114 -#define _INSERT_1_LOAD_CONST_INLINE_r23 1115 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1116 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1117 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1118 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1119 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1120 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1121 -#define _INSERT_NULL_r10 1122 -#define _INSTRUMENTED_FOR_ITER_r23 1123 -#define _INSTRUMENTED_INSTRUCTION_r00 1124 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1125 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1126 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1127 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1128 -#define _INSTRUMENTED_LINE_r00 1129 -#define _INSTRUMENTED_NOT_TAKEN_r00 1130 -#define _INSTRUMENTED_NOT_TAKEN_r11 1131 -#define _INSTRUMENTED_NOT_TAKEN_r22 1132 -#define _INSTRUMENTED_NOT_TAKEN_r33 1133 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1134 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1135 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1136 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1137 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1138 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1139 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1140 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1141 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1142 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1143 -#define _IS_NONE_r11 1144 -#define _IS_OP_r03 1145 -#define _IS_OP_r13 1146 -#define _IS_OP_r23 1147 -#define _ITER_CHECK_LIST_r02 1148 -#define _ITER_CHECK_LIST_r12 1149 -#define _ITER_CHECK_LIST_r22 1150 -#define _ITER_CHECK_LIST_r33 1151 -#define _ITER_CHECK_RANGE_r02 1152 -#define _ITER_CHECK_RANGE_r12 1153 -#define _ITER_CHECK_RANGE_r22 1154 -#define _ITER_CHECK_RANGE_r33 1155 -#define _ITER_CHECK_TUPLE_r02 1156 -#define _ITER_CHECK_TUPLE_r12 1157 -#define _ITER_CHECK_TUPLE_r22 1158 -#define _ITER_CHECK_TUPLE_r33 1159 -#define _ITER_JUMP_LIST_r02 1160 -#define _ITER_JUMP_LIST_r12 1161 -#define _ITER_JUMP_LIST_r22 1162 -#define _ITER_JUMP_LIST_r33 1163 -#define _ITER_JUMP_RANGE_r02 1164 -#define _ITER_JUMP_RANGE_r12 1165 -#define _ITER_JUMP_RANGE_r22 1166 -#define _ITER_JUMP_RANGE_r33 1167 -#define _ITER_JUMP_TUPLE_r02 1168 -#define _ITER_JUMP_TUPLE_r12 1169 -#define _ITER_JUMP_TUPLE_r22 1170 -#define _ITER_JUMP_TUPLE_r33 1171 -#define _ITER_NEXT_LIST_r23 1172 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1173 -#define _ITER_NEXT_RANGE_r03 1174 -#define _ITER_NEXT_RANGE_r13 1175 -#define _ITER_NEXT_RANGE_r23 1176 -#define _ITER_NEXT_TUPLE_r03 1177 -#define _ITER_NEXT_TUPLE_r13 1178 -#define _ITER_NEXT_TUPLE_r23 1179 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1180 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1181 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1182 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1183 -#define _JUMP_TO_TOP_r00 1184 -#define _LIST_APPEND_r10 1185 -#define _LIST_EXTEND_r11 1186 -#define _LOAD_ATTR_r10 1187 -#define _LOAD_ATTR_CLASS_r11 1188 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1189 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1190 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1191 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1192 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1193 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1194 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1195 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1196 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1197 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1198 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1199 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1200 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1201 -#define _LOAD_ATTR_MODULE_r12 1202 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1203 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1204 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1205 -#define _LOAD_ATTR_SLOT_r02 1206 -#define _LOAD_ATTR_SLOT_r12 1207 -#define _LOAD_ATTR_SLOT_r23 1208 -#define _LOAD_ATTR_WITH_HINT_r12 1209 -#define _LOAD_BUILD_CLASS_r01 1210 -#define _LOAD_BYTECODE_r00 1211 -#define _LOAD_COMMON_CONSTANT_r01 1212 -#define _LOAD_COMMON_CONSTANT_r12 1213 -#define _LOAD_COMMON_CONSTANT_r23 1214 -#define _LOAD_CONST_r01 1215 -#define _LOAD_CONST_r12 1216 -#define _LOAD_CONST_r23 1217 -#define _LOAD_CONST_INLINE_r01 1218 -#define _LOAD_CONST_INLINE_r12 1219 -#define _LOAD_CONST_INLINE_r23 1220 -#define _LOAD_CONST_INLINE_BORROW_r01 1221 -#define _LOAD_CONST_INLINE_BORROW_r12 1222 -#define _LOAD_CONST_INLINE_BORROW_r23 1223 -#define _LOAD_CONST_UNDER_INLINE_r02 1224 -#define _LOAD_CONST_UNDER_INLINE_r12 1225 -#define _LOAD_CONST_UNDER_INLINE_r23 1226 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1227 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1228 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1229 -#define _LOAD_DEREF_r01 1230 -#define _LOAD_FAST_r01 1231 -#define _LOAD_FAST_r12 1232 -#define _LOAD_FAST_r23 1233 -#define _LOAD_FAST_0_r01 1234 -#define _LOAD_FAST_0_r12 1235 -#define _LOAD_FAST_0_r23 1236 -#define _LOAD_FAST_1_r01 1237 -#define _LOAD_FAST_1_r12 1238 -#define _LOAD_FAST_1_r23 1239 -#define _LOAD_FAST_2_r01 1240 -#define _LOAD_FAST_2_r12 1241 -#define _LOAD_FAST_2_r23 1242 -#define _LOAD_FAST_3_r01 1243 -#define _LOAD_FAST_3_r12 1244 -#define _LOAD_FAST_3_r23 1245 -#define _LOAD_FAST_4_r01 1246 -#define _LOAD_FAST_4_r12 1247 -#define _LOAD_FAST_4_r23 1248 -#define _LOAD_FAST_5_r01 1249 -#define _LOAD_FAST_5_r12 1250 -#define _LOAD_FAST_5_r23 1251 -#define _LOAD_FAST_6_r01 1252 -#define _LOAD_FAST_6_r12 1253 -#define _LOAD_FAST_6_r23 1254 -#define _LOAD_FAST_7_r01 1255 -#define _LOAD_FAST_7_r12 1256 -#define _LOAD_FAST_7_r23 1257 -#define _LOAD_FAST_AND_CLEAR_r01 1258 -#define _LOAD_FAST_AND_CLEAR_r12 1259 -#define _LOAD_FAST_AND_CLEAR_r23 1260 -#define _LOAD_FAST_BORROW_r01 1261 -#define _LOAD_FAST_BORROW_r12 1262 -#define _LOAD_FAST_BORROW_r23 1263 -#define _LOAD_FAST_BORROW_0_r01 1264 -#define _LOAD_FAST_BORROW_0_r12 1265 -#define _LOAD_FAST_BORROW_0_r23 1266 -#define _LOAD_FAST_BORROW_1_r01 1267 -#define _LOAD_FAST_BORROW_1_r12 1268 -#define _LOAD_FAST_BORROW_1_r23 1269 -#define _LOAD_FAST_BORROW_2_r01 1270 -#define _LOAD_FAST_BORROW_2_r12 1271 -#define _LOAD_FAST_BORROW_2_r23 1272 -#define _LOAD_FAST_BORROW_3_r01 1273 -#define _LOAD_FAST_BORROW_3_r12 1274 -#define _LOAD_FAST_BORROW_3_r23 1275 -#define _LOAD_FAST_BORROW_4_r01 1276 -#define _LOAD_FAST_BORROW_4_r12 1277 -#define _LOAD_FAST_BORROW_4_r23 1278 -#define _LOAD_FAST_BORROW_5_r01 1279 -#define _LOAD_FAST_BORROW_5_r12 1280 -#define _LOAD_FAST_BORROW_5_r23 1281 -#define _LOAD_FAST_BORROW_6_r01 1282 -#define _LOAD_FAST_BORROW_6_r12 1283 -#define _LOAD_FAST_BORROW_6_r23 1284 -#define _LOAD_FAST_BORROW_7_r01 1285 -#define _LOAD_FAST_BORROW_7_r12 1286 -#define _LOAD_FAST_BORROW_7_r23 1287 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1288 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1289 -#define _LOAD_FAST_CHECK_r01 1290 -#define _LOAD_FAST_CHECK_r12 1291 -#define _LOAD_FAST_CHECK_r23 1292 -#define _LOAD_FAST_LOAD_FAST_r02 1293 -#define _LOAD_FAST_LOAD_FAST_r13 1294 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1295 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1296 -#define _LOAD_GLOBAL_r00 1297 -#define _LOAD_GLOBAL_BUILTINS_r01 1298 -#define _LOAD_GLOBAL_MODULE_r01 1299 -#define _LOAD_LOCALS_r01 1300 -#define _LOAD_LOCALS_r12 1301 -#define _LOAD_LOCALS_r23 1302 -#define _LOAD_NAME_r01 1303 -#define _LOAD_SMALL_INT_r01 1304 -#define _LOAD_SMALL_INT_r12 1305 -#define _LOAD_SMALL_INT_r23 1306 -#define _LOAD_SMALL_INT_0_r01 1307 -#define _LOAD_SMALL_INT_0_r12 1308 -#define _LOAD_SMALL_INT_0_r23 1309 -#define _LOAD_SMALL_INT_1_r01 1310 -#define _LOAD_SMALL_INT_1_r12 1311 -#define _LOAD_SMALL_INT_1_r23 1312 -#define _LOAD_SMALL_INT_2_r01 1313 -#define _LOAD_SMALL_INT_2_r12 1314 -#define _LOAD_SMALL_INT_2_r23 1315 -#define _LOAD_SMALL_INT_3_r01 1316 -#define _LOAD_SMALL_INT_3_r12 1317 -#define _LOAD_SMALL_INT_3_r23 1318 -#define _LOAD_SPECIAL_r00 1319 -#define _LOAD_SUPER_ATTR_ATTR_r31 1320 -#define _LOAD_SUPER_ATTR_METHOD_r32 1321 -#define _LOCK_OBJECT_r01 1322 -#define _LOCK_OBJECT_r11 1323 -#define _LOCK_OBJECT_r22 1324 -#define _LOCK_OBJECT_r33 1325 -#define _MAKE_CALLARGS_A_TUPLE_r33 1326 -#define _MAKE_CELL_r00 1327 -#define _MAKE_FUNCTION_r11 1328 -#define _MAKE_HEAP_SAFE_r01 1329 -#define _MAKE_HEAP_SAFE_r11 1330 -#define _MAKE_HEAP_SAFE_r22 1331 -#define _MAKE_HEAP_SAFE_r33 1332 -#define _MAKE_WARM_r00 1333 -#define _MAKE_WARM_r11 1334 -#define _MAKE_WARM_r22 1335 -#define _MAKE_WARM_r33 1336 -#define _MAP_ADD_r20 1337 -#define _MATCH_CLASS_r33 1338 -#define _MATCH_KEYS_r23 1339 -#define _MATCH_MAPPING_r02 1340 -#define _MATCH_MAPPING_r12 1341 -#define _MATCH_MAPPING_r23 1342 -#define _MATCH_SEQUENCE_r02 1343 -#define _MATCH_SEQUENCE_r12 1344 -#define _MATCH_SEQUENCE_r23 1345 -#define _MAYBE_EXPAND_METHOD_r00 1346 -#define _MAYBE_EXPAND_METHOD_KW_r11 1347 -#define _MONITOR_CALL_r00 1348 -#define _MONITOR_CALL_KW_r11 1349 -#define _MONITOR_JUMP_BACKWARD_r00 1350 -#define _MONITOR_JUMP_BACKWARD_r11 1351 -#define _MONITOR_JUMP_BACKWARD_r22 1352 -#define _MONITOR_JUMP_BACKWARD_r33 1353 -#define _MONITOR_RESUME_r00 1354 -#define _NOP_r00 1355 -#define _NOP_r11 1356 -#define _NOP_r22 1357 -#define _NOP_r33 1358 -#define _POP_CALL_r20 1359 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1360 -#define _POP_CALL_ONE_r30 1361 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1362 -#define _POP_CALL_TWO_r30 1363 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1364 -#define _POP_EXCEPT_r10 1365 -#define _POP_ITER_r20 1366 -#define _POP_JUMP_IF_FALSE_r00 1367 -#define _POP_JUMP_IF_FALSE_r10 1368 -#define _POP_JUMP_IF_FALSE_r21 1369 -#define _POP_JUMP_IF_FALSE_r32 1370 -#define _POP_JUMP_IF_TRUE_r00 1371 -#define _POP_JUMP_IF_TRUE_r10 1372 -#define _POP_JUMP_IF_TRUE_r21 1373 -#define _POP_JUMP_IF_TRUE_r32 1374 -#define _POP_TOP_r10 1375 -#define _POP_TOP_FLOAT_r00 1376 -#define _POP_TOP_FLOAT_r10 1377 -#define _POP_TOP_FLOAT_r21 1378 -#define _POP_TOP_FLOAT_r32 1379 -#define _POP_TOP_INT_r00 1380 -#define _POP_TOP_INT_r10 1381 -#define _POP_TOP_INT_r21 1382 -#define _POP_TOP_INT_r32 1383 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1384 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1385 -#define _POP_TOP_NOP_r00 1386 -#define _POP_TOP_NOP_r10 1387 -#define _POP_TOP_NOP_r21 1388 -#define _POP_TOP_NOP_r32 1389 -#define _POP_TOP_UNICODE_r00 1390 -#define _POP_TOP_UNICODE_r10 1391 -#define _POP_TOP_UNICODE_r21 1392 -#define _POP_TOP_UNICODE_r32 1393 -#define _POP_TWO_r20 1394 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1395 -#define _PUSH_EXC_INFO_r02 1396 -#define _PUSH_EXC_INFO_r12 1397 -#define _PUSH_EXC_INFO_r23 1398 -#define _PUSH_FRAME_r10 1399 -#define _PUSH_NULL_r01 1400 -#define _PUSH_NULL_r12 1401 -#define _PUSH_NULL_r23 1402 -#define _PUSH_NULL_CONDITIONAL_r00 1403 -#define _PY_FRAME_EX_r31 1404 -#define _PY_FRAME_GENERAL_r01 1405 -#define _PY_FRAME_KW_r11 1406 -#define _REPLACE_WITH_TRUE_r02 1407 -#define _REPLACE_WITH_TRUE_r12 1408 -#define _REPLACE_WITH_TRUE_r23 1409 -#define _RESUME_CHECK_r00 1410 -#define _RESUME_CHECK_r11 1411 -#define _RESUME_CHECK_r22 1412 -#define _RESUME_CHECK_r33 1413 -#define _RETURN_GENERATOR_r01 1414 -#define _RETURN_VALUE_r11 1415 -#define _SAVE_RETURN_OFFSET_r00 1416 -#define _SAVE_RETURN_OFFSET_r11 1417 -#define _SAVE_RETURN_OFFSET_r22 1418 -#define _SAVE_RETURN_OFFSET_r33 1419 -#define _SEND_r33 1420 -#define _SEND_GEN_FRAME_r33 1421 -#define _SETUP_ANNOTATIONS_r00 1422 -#define _SET_ADD_r10 1423 -#define _SET_FUNCTION_ATTRIBUTE_r01 1424 -#define _SET_FUNCTION_ATTRIBUTE_r11 1425 -#define _SET_FUNCTION_ATTRIBUTE_r21 1426 -#define _SET_FUNCTION_ATTRIBUTE_r32 1427 -#define _SET_IP_r00 1428 -#define _SET_IP_r11 1429 -#define _SET_IP_r22 1430 -#define _SET_IP_r33 1431 -#define _SET_UPDATE_r11 1432 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1433 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1434 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1435 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1436 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1437 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1438 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1439 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1440 -#define _SPILL_OR_RELOAD_r01 1441 -#define _SPILL_OR_RELOAD_r02 1442 -#define _SPILL_OR_RELOAD_r03 1443 -#define _SPILL_OR_RELOAD_r10 1444 -#define _SPILL_OR_RELOAD_r12 1445 -#define _SPILL_OR_RELOAD_r13 1446 -#define _SPILL_OR_RELOAD_r20 1447 -#define _SPILL_OR_RELOAD_r21 1448 -#define _SPILL_OR_RELOAD_r23 1449 -#define _SPILL_OR_RELOAD_r30 1450 -#define _SPILL_OR_RELOAD_r31 1451 -#define _SPILL_OR_RELOAD_r32 1452 -#define _START_EXECUTOR_r00 1453 -#define _STORE_ATTR_r20 1454 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1455 -#define _STORE_ATTR_SLOT_r21 1456 -#define _STORE_ATTR_WITH_HINT_r21 1457 -#define _STORE_DEREF_r10 1458 -#define _STORE_FAST_LOAD_FAST_r11 1459 -#define _STORE_FAST_STORE_FAST_r20 1460 -#define _STORE_GLOBAL_r10 1461 -#define _STORE_NAME_r10 1462 -#define _STORE_SLICE_r30 1463 -#define _STORE_SUBSCR_r30 1464 -#define _STORE_SUBSCR_DICT_r31 1465 -#define _STORE_SUBSCR_LIST_INT_r32 1466 -#define _SWAP_r11 1467 -#define _SWAP_2_r02 1468 -#define _SWAP_2_r12 1469 -#define _SWAP_2_r22 1470 -#define _SWAP_2_r33 1471 -#define _SWAP_3_r03 1472 -#define _SWAP_3_r13 1473 -#define _SWAP_3_r23 1474 -#define _SWAP_3_r33 1475 -#define _SWAP_FAST_r01 1476 -#define _SWAP_FAST_r11 1477 -#define _SWAP_FAST_r22 1478 -#define _SWAP_FAST_r33 1479 -#define _SWAP_FAST_0_r01 1480 -#define _SWAP_FAST_0_r11 1481 -#define _SWAP_FAST_0_r22 1482 -#define _SWAP_FAST_0_r33 1483 -#define _SWAP_FAST_1_r01 1484 -#define _SWAP_FAST_1_r11 1485 -#define _SWAP_FAST_1_r22 1486 -#define _SWAP_FAST_1_r33 1487 -#define _SWAP_FAST_2_r01 1488 -#define _SWAP_FAST_2_r11 1489 -#define _SWAP_FAST_2_r22 1490 -#define _SWAP_FAST_2_r33 1491 -#define _SWAP_FAST_3_r01 1492 -#define _SWAP_FAST_3_r11 1493 -#define _SWAP_FAST_3_r22 1494 -#define _SWAP_FAST_3_r33 1495 -#define _SWAP_FAST_4_r01 1496 -#define _SWAP_FAST_4_r11 1497 -#define _SWAP_FAST_4_r22 1498 -#define _SWAP_FAST_4_r33 1499 -#define _SWAP_FAST_5_r01 1500 -#define _SWAP_FAST_5_r11 1501 -#define _SWAP_FAST_5_r22 1502 -#define _SWAP_FAST_5_r33 1503 -#define _SWAP_FAST_6_r01 1504 -#define _SWAP_FAST_6_r11 1505 -#define _SWAP_FAST_6_r22 1506 -#define _SWAP_FAST_6_r33 1507 -#define _SWAP_FAST_7_r01 1508 -#define _SWAP_FAST_7_r11 1509 -#define _SWAP_FAST_7_r22 1510 -#define _SWAP_FAST_7_r33 1511 -#define _TIER2_RESUME_CHECK_r00 1512 -#define _TIER2_RESUME_CHECK_r11 1513 -#define _TIER2_RESUME_CHECK_r22 1514 -#define _TIER2_RESUME_CHECK_r33 1515 -#define _TO_BOOL_r11 1516 -#define _TO_BOOL_BOOL_r01 1517 -#define _TO_BOOL_BOOL_r11 1518 -#define _TO_BOOL_BOOL_r22 1519 -#define _TO_BOOL_BOOL_r33 1520 -#define _TO_BOOL_INT_r02 1521 -#define _TO_BOOL_INT_r12 1522 -#define _TO_BOOL_INT_r23 1523 -#define _TO_BOOL_LIST_r02 1524 -#define _TO_BOOL_LIST_r12 1525 -#define _TO_BOOL_LIST_r23 1526 -#define _TO_BOOL_NONE_r01 1527 -#define _TO_BOOL_NONE_r11 1528 -#define _TO_BOOL_NONE_r22 1529 -#define _TO_BOOL_NONE_r33 1530 -#define _TO_BOOL_STR_r02 1531 -#define _TO_BOOL_STR_r12 1532 -#define _TO_BOOL_STR_r23 1533 -#define _TRACE_RECORD_r00 1534 -#define _UNARY_INVERT_r12 1535 -#define _UNARY_NEGATIVE_r12 1536 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1537 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1538 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1539 -#define _UNARY_NOT_r01 1540 -#define _UNARY_NOT_r11 1541 -#define _UNARY_NOT_r22 1542 -#define _UNARY_NOT_r33 1543 -#define _UNPACK_EX_r10 1544 -#define _UNPACK_SEQUENCE_r10 1545 -#define _UNPACK_SEQUENCE_LIST_r10 1546 -#define _UNPACK_SEQUENCE_TUPLE_r10 1547 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1548 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1549 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1550 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1551 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1552 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1553 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1554 -#define _WITH_EXCEPT_START_r33 1555 -#define _YIELD_VALUE_r11 1556 -#define MAX_UOP_REGS_ID 1556 +#define _YIELD_VALUE 627 +#define MAX_UOP_ID 627 +#define _BINARY_OP_r23 628 +#define _BINARY_OP_ADD_FLOAT_r03 629 +#define _BINARY_OP_ADD_FLOAT_r13 630 +#define _BINARY_OP_ADD_FLOAT_r23 631 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 632 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 633 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 634 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 635 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 636 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 637 +#define _BINARY_OP_ADD_INT_r03 638 +#define _BINARY_OP_ADD_INT_r13 639 +#define _BINARY_OP_ADD_INT_r23 640 +#define _BINARY_OP_ADD_UNICODE_r03 641 +#define _BINARY_OP_ADD_UNICODE_r13 642 +#define _BINARY_OP_ADD_UNICODE_r23 643 +#define _BINARY_OP_EXTEND_r23 644 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 645 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 646 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 647 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 648 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 649 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 650 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 651 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 652 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 653 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 654 +#define _BINARY_OP_MULTIPLY_INT_r03 655 +#define _BINARY_OP_MULTIPLY_INT_r13 656 +#define _BINARY_OP_MULTIPLY_INT_r23 657 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 658 +#define _BINARY_OP_SUBSCR_DICT_r23 659 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 660 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 661 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 662 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 663 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 664 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 665 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 666 +#define _BINARY_OP_SUBSCR_STR_INT_r23 667 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 668 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 669 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 670 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 671 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 672 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 673 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 674 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 675 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 676 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 677 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 678 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 679 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 680 +#define _BINARY_OP_SUBTRACT_INT_r03 681 +#define _BINARY_OP_SUBTRACT_INT_r13 682 +#define _BINARY_OP_SUBTRACT_INT_r23 683 +#define _BINARY_SLICE_r31 684 +#define _BUILD_INTERPOLATION_r01 685 +#define _BUILD_LIST_r01 686 +#define _BUILD_MAP_r01 687 +#define _BUILD_SET_r01 688 +#define _BUILD_SLICE_r01 689 +#define _BUILD_STRING_r01 690 +#define _BUILD_TEMPLATE_r21 691 +#define _BUILD_TUPLE_r01 692 +#define _CALL_BUILTIN_CLASS_r01 693 +#define _CALL_BUILTIN_FAST_r01 694 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 695 +#define _CALL_BUILTIN_O_r03 696 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 697 +#define _CALL_INTRINSIC_1_r12 698 +#define _CALL_INTRINSIC_2_r23 699 +#define _CALL_ISINSTANCE_r31 700 +#define _CALL_KW_NON_PY_r11 701 +#define _CALL_LEN_r33 702 +#define _CALL_LIST_APPEND_r03 703 +#define _CALL_LIST_APPEND_r13 704 +#define _CALL_LIST_APPEND_r23 705 +#define _CALL_LIST_APPEND_r33 706 +#define _CALL_METHOD_DESCRIPTOR_FAST_r01 707 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 708 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 709 +#define _CALL_METHOD_DESCRIPTOR_O_r03 710 +#define _CALL_NON_PY_GENERAL_r01 711 +#define _CALL_STR_1_r32 712 +#define _CALL_TUPLE_1_r32 713 +#define _CALL_TYPE_1_r02 714 +#define _CALL_TYPE_1_r12 715 +#define _CALL_TYPE_1_r22 716 +#define _CALL_TYPE_1_r32 717 +#define _CHECK_AND_ALLOCATE_OBJECT_r00 718 +#define _CHECK_ATTR_CLASS_r01 719 +#define _CHECK_ATTR_CLASS_r11 720 +#define _CHECK_ATTR_CLASS_r22 721 +#define _CHECK_ATTR_CLASS_r33 722 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 723 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 724 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 725 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 726 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 727 +#define _CHECK_EG_MATCH_r22 728 +#define _CHECK_EXC_MATCH_r22 729 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 730 +#define _CHECK_FUNCTION_VERSION_r00 731 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 732 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 733 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 734 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 735 +#define _CHECK_FUNCTION_VERSION_KW_r11 736 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 737 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 738 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 739 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 740 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 741 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 742 +#define _CHECK_IS_PY_CALLABLE_EX_r03 743 +#define _CHECK_IS_PY_CALLABLE_EX_r13 744 +#define _CHECK_IS_PY_CALLABLE_EX_r23 745 +#define _CHECK_IS_PY_CALLABLE_EX_r33 746 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 747 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 748 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 749 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 750 +#define _CHECK_METHOD_VERSION_r00 751 +#define _CHECK_METHOD_VERSION_KW_r11 752 +#define _CHECK_PEP_523_r00 753 +#define _CHECK_PEP_523_r11 754 +#define _CHECK_PEP_523_r22 755 +#define _CHECK_PEP_523_r33 756 +#define _CHECK_PERIODIC_r00 757 +#define _CHECK_PERIODIC_AT_END_r00 758 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 759 +#define _CHECK_RECURSION_REMAINING_r00 760 +#define _CHECK_RECURSION_REMAINING_r11 761 +#define _CHECK_RECURSION_REMAINING_r22 762 +#define _CHECK_RECURSION_REMAINING_r33 763 +#define _CHECK_STACK_SPACE_r00 764 +#define _CHECK_STACK_SPACE_OPERAND_r00 765 +#define _CHECK_STACK_SPACE_OPERAND_r11 766 +#define _CHECK_STACK_SPACE_OPERAND_r22 767 +#define _CHECK_STACK_SPACE_OPERAND_r33 768 +#define _CHECK_VALIDITY_r00 769 +#define _CHECK_VALIDITY_r11 770 +#define _CHECK_VALIDITY_r22 771 +#define _CHECK_VALIDITY_r33 772 +#define _COLD_DYNAMIC_EXIT_r00 773 +#define _COLD_EXIT_r00 774 +#define _COMPARE_OP_r21 775 +#define _COMPARE_OP_FLOAT_r03 776 +#define _COMPARE_OP_FLOAT_r13 777 +#define _COMPARE_OP_FLOAT_r23 778 +#define _COMPARE_OP_INT_r23 779 +#define _COMPARE_OP_STR_r23 780 +#define _CONTAINS_OP_r23 781 +#define _CONTAINS_OP_DICT_r23 782 +#define _CONTAINS_OP_SET_r23 783 +#define _CONVERT_VALUE_r11 784 +#define _COPY_r01 785 +#define _COPY_1_r02 786 +#define _COPY_1_r12 787 +#define _COPY_1_r23 788 +#define _COPY_2_r03 789 +#define _COPY_2_r13 790 +#define _COPY_2_r23 791 +#define _COPY_3_r03 792 +#define _COPY_3_r13 793 +#define _COPY_3_r23 794 +#define _COPY_3_r33 795 +#define _COPY_FREE_VARS_r00 796 +#define _COPY_FREE_VARS_r11 797 +#define _COPY_FREE_VARS_r22 798 +#define _COPY_FREE_VARS_r33 799 +#define _CREATE_INIT_FRAME_r01 800 +#define _DELETE_ATTR_r10 801 +#define _DELETE_DEREF_r00 802 +#define _DELETE_FAST_r00 803 +#define _DELETE_GLOBAL_r00 804 +#define _DELETE_NAME_r00 805 +#define _DELETE_SUBSCR_r20 806 +#define _DEOPT_r00 807 +#define _DEOPT_r10 808 +#define _DEOPT_r20 809 +#define _DEOPT_r30 810 +#define _DICT_MERGE_r11 811 +#define _DICT_UPDATE_r11 812 +#define _DO_CALL_r01 813 +#define _DO_CALL_FUNCTION_EX_r31 814 +#define _DO_CALL_KW_r11 815 +#define _DYNAMIC_EXIT_r00 816 +#define _DYNAMIC_EXIT_r10 817 +#define _DYNAMIC_EXIT_r20 818 +#define _DYNAMIC_EXIT_r30 819 +#define _END_FOR_r10 820 +#define _END_SEND_r31 821 +#define _ERROR_POP_N_r00 822 +#define _EXIT_INIT_CHECK_r10 823 +#define _EXIT_TRACE_r00 824 +#define _EXIT_TRACE_r10 825 +#define _EXIT_TRACE_r20 826 +#define _EXIT_TRACE_r30 827 +#define _EXPAND_METHOD_r00 828 +#define _EXPAND_METHOD_KW_r11 829 +#define _FATAL_ERROR_r00 830 +#define _FATAL_ERROR_r11 831 +#define _FATAL_ERROR_r22 832 +#define _FATAL_ERROR_r33 833 +#define _FORMAT_SIMPLE_r11 834 +#define _FORMAT_WITH_SPEC_r21 835 +#define _FOR_ITER_r23 836 +#define _FOR_ITER_GEN_FRAME_r03 837 +#define _FOR_ITER_GEN_FRAME_r13 838 +#define _FOR_ITER_GEN_FRAME_r23 839 +#define _FOR_ITER_TIER_TWO_r23 840 +#define _GET_AITER_r11 841 +#define _GET_ANEXT_r12 842 +#define _GET_AWAITABLE_r11 843 +#define _GET_ITER_r12 844 +#define _GET_LEN_r12 845 +#define _GUARD_BINARY_OP_EXTEND_r22 846 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 847 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 848 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 849 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 850 +#define _GUARD_BIT_IS_SET_POP_r00 851 +#define _GUARD_BIT_IS_SET_POP_r10 852 +#define _GUARD_BIT_IS_SET_POP_r21 853 +#define _GUARD_BIT_IS_SET_POP_r32 854 +#define _GUARD_BIT_IS_SET_POP_4_r00 855 +#define _GUARD_BIT_IS_SET_POP_4_r10 856 +#define _GUARD_BIT_IS_SET_POP_4_r21 857 +#define _GUARD_BIT_IS_SET_POP_4_r32 858 +#define _GUARD_BIT_IS_SET_POP_5_r00 859 +#define _GUARD_BIT_IS_SET_POP_5_r10 860 +#define _GUARD_BIT_IS_SET_POP_5_r21 861 +#define _GUARD_BIT_IS_SET_POP_5_r32 862 +#define _GUARD_BIT_IS_SET_POP_6_r00 863 +#define _GUARD_BIT_IS_SET_POP_6_r10 864 +#define _GUARD_BIT_IS_SET_POP_6_r21 865 +#define _GUARD_BIT_IS_SET_POP_6_r32 866 +#define _GUARD_BIT_IS_SET_POP_7_r00 867 +#define _GUARD_BIT_IS_SET_POP_7_r10 868 +#define _GUARD_BIT_IS_SET_POP_7_r21 869 +#define _GUARD_BIT_IS_SET_POP_7_r32 870 +#define _GUARD_BIT_IS_UNSET_POP_r00 871 +#define _GUARD_BIT_IS_UNSET_POP_r10 872 +#define _GUARD_BIT_IS_UNSET_POP_r21 873 +#define _GUARD_BIT_IS_UNSET_POP_r32 874 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 875 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 876 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 877 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 878 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 879 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 880 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 881 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 882 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 883 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 884 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 885 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 886 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 887 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 888 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 889 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 890 +#define _GUARD_CALLABLE_BUILTIN_FAST_r00 891 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 892 +#define _GUARD_CALLABLE_BUILTIN_O_r00 893 +#define _GUARD_CALLABLE_ISINSTANCE_r03 894 +#define _GUARD_CALLABLE_ISINSTANCE_r13 895 +#define _GUARD_CALLABLE_ISINSTANCE_r23 896 +#define _GUARD_CALLABLE_ISINSTANCE_r33 897 +#define _GUARD_CALLABLE_LEN_r03 898 +#define _GUARD_CALLABLE_LEN_r13 899 +#define _GUARD_CALLABLE_LEN_r23 900 +#define _GUARD_CALLABLE_LEN_r33 901 +#define _GUARD_CALLABLE_LIST_APPEND_r03 902 +#define _GUARD_CALLABLE_LIST_APPEND_r13 903 +#define _GUARD_CALLABLE_LIST_APPEND_r23 904 +#define _GUARD_CALLABLE_LIST_APPEND_r33 905 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 906 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 907 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 908 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 909 +#define _GUARD_CALLABLE_STR_1_r03 910 +#define _GUARD_CALLABLE_STR_1_r13 911 +#define _GUARD_CALLABLE_STR_1_r23 912 +#define _GUARD_CALLABLE_STR_1_r33 913 +#define _GUARD_CALLABLE_TUPLE_1_r03 914 +#define _GUARD_CALLABLE_TUPLE_1_r13 915 +#define _GUARD_CALLABLE_TUPLE_1_r23 916 +#define _GUARD_CALLABLE_TUPLE_1_r33 917 +#define _GUARD_CALLABLE_TYPE_1_r03 918 +#define _GUARD_CALLABLE_TYPE_1_r13 919 +#define _GUARD_CALLABLE_TYPE_1_r23 920 +#define _GUARD_CALLABLE_TYPE_1_r33 921 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 922 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 923 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 924 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 925 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 926 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 927 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 928 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 929 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 930 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 931 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 932 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 933 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 934 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 935 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 936 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 937 +#define _GUARD_DORV_NO_DICT_r01 938 +#define _GUARD_DORV_NO_DICT_r11 939 +#define _GUARD_DORV_NO_DICT_r22 940 +#define _GUARD_DORV_NO_DICT_r33 941 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 942 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 943 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 944 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 945 +#define _GUARD_GLOBALS_VERSION_r00 946 +#define _GUARD_GLOBALS_VERSION_r11 947 +#define _GUARD_GLOBALS_VERSION_r22 948 +#define _GUARD_GLOBALS_VERSION_r33 949 +#define _GUARD_IP_RETURN_GENERATOR_r00 950 +#define _GUARD_IP_RETURN_GENERATOR_r11 951 +#define _GUARD_IP_RETURN_GENERATOR_r22 952 +#define _GUARD_IP_RETURN_GENERATOR_r33 953 +#define _GUARD_IP_RETURN_VALUE_r00 954 +#define _GUARD_IP_RETURN_VALUE_r11 955 +#define _GUARD_IP_RETURN_VALUE_r22 956 +#define _GUARD_IP_RETURN_VALUE_r33 957 +#define _GUARD_IP_YIELD_VALUE_r00 958 +#define _GUARD_IP_YIELD_VALUE_r11 959 +#define _GUARD_IP_YIELD_VALUE_r22 960 +#define _GUARD_IP_YIELD_VALUE_r33 961 +#define _GUARD_IP__PUSH_FRAME_r00 962 +#define _GUARD_IP__PUSH_FRAME_r11 963 +#define _GUARD_IP__PUSH_FRAME_r22 964 +#define _GUARD_IP__PUSH_FRAME_r33 965 +#define _GUARD_IS_FALSE_POP_r00 966 +#define _GUARD_IS_FALSE_POP_r10 967 +#define _GUARD_IS_FALSE_POP_r21 968 +#define _GUARD_IS_FALSE_POP_r32 969 +#define _GUARD_IS_NONE_POP_r00 970 +#define _GUARD_IS_NONE_POP_r10 971 +#define _GUARD_IS_NONE_POP_r21 972 +#define _GUARD_IS_NONE_POP_r32 973 +#define _GUARD_IS_NOT_NONE_POP_r10 974 +#define _GUARD_IS_TRUE_POP_r00 975 +#define _GUARD_IS_TRUE_POP_r10 976 +#define _GUARD_IS_TRUE_POP_r21 977 +#define _GUARD_IS_TRUE_POP_r32 978 +#define _GUARD_KEYS_VERSION_r01 979 +#define _GUARD_KEYS_VERSION_r11 980 +#define _GUARD_KEYS_VERSION_r22 981 +#define _GUARD_KEYS_VERSION_r33 982 +#define _GUARD_NOS_ANY_DICT_r02 983 +#define _GUARD_NOS_ANY_DICT_r12 984 +#define _GUARD_NOS_ANY_DICT_r22 985 +#define _GUARD_NOS_ANY_DICT_r33 986 +#define _GUARD_NOS_COMPACT_ASCII_r02 987 +#define _GUARD_NOS_COMPACT_ASCII_r12 988 +#define _GUARD_NOS_COMPACT_ASCII_r22 989 +#define _GUARD_NOS_COMPACT_ASCII_r33 990 +#define _GUARD_NOS_DICT_r02 991 +#define _GUARD_NOS_DICT_r12 992 +#define _GUARD_NOS_DICT_r22 993 +#define _GUARD_NOS_DICT_r33 994 +#define _GUARD_NOS_FLOAT_r02 995 +#define _GUARD_NOS_FLOAT_r12 996 +#define _GUARD_NOS_FLOAT_r22 997 +#define _GUARD_NOS_FLOAT_r33 998 +#define _GUARD_NOS_INT_r02 999 +#define _GUARD_NOS_INT_r12 1000 +#define _GUARD_NOS_INT_r22 1001 +#define _GUARD_NOS_INT_r33 1002 +#define _GUARD_NOS_LIST_r02 1003 +#define _GUARD_NOS_LIST_r12 1004 +#define _GUARD_NOS_LIST_r22 1005 +#define _GUARD_NOS_LIST_r33 1006 +#define _GUARD_NOS_NOT_NULL_r02 1007 +#define _GUARD_NOS_NOT_NULL_r12 1008 +#define _GUARD_NOS_NOT_NULL_r22 1009 +#define _GUARD_NOS_NOT_NULL_r33 1010 +#define _GUARD_NOS_NULL_r02 1011 +#define _GUARD_NOS_NULL_r12 1012 +#define _GUARD_NOS_NULL_r22 1013 +#define _GUARD_NOS_NULL_r33 1014 +#define _GUARD_NOS_OVERFLOWED_r02 1015 +#define _GUARD_NOS_OVERFLOWED_r12 1016 +#define _GUARD_NOS_OVERFLOWED_r22 1017 +#define _GUARD_NOS_OVERFLOWED_r33 1018 +#define _GUARD_NOS_TUPLE_r02 1019 +#define _GUARD_NOS_TUPLE_r12 1020 +#define _GUARD_NOS_TUPLE_r22 1021 +#define _GUARD_NOS_TUPLE_r33 1022 +#define _GUARD_NOS_UNICODE_r02 1023 +#define _GUARD_NOS_UNICODE_r12 1024 +#define _GUARD_NOS_UNICODE_r22 1025 +#define _GUARD_NOS_UNICODE_r33 1026 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 1027 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 1028 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 1029 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 1030 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1031 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1032 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1033 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1034 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1035 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1036 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1037 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1038 +#define _GUARD_THIRD_NULL_r03 1039 +#define _GUARD_THIRD_NULL_r13 1040 +#define _GUARD_THIRD_NULL_r23 1041 +#define _GUARD_THIRD_NULL_r33 1042 +#define _GUARD_TOS_ANY_DICT_r01 1043 +#define _GUARD_TOS_ANY_DICT_r11 1044 +#define _GUARD_TOS_ANY_DICT_r22 1045 +#define _GUARD_TOS_ANY_DICT_r33 1046 +#define _GUARD_TOS_ANY_SET_r01 1047 +#define _GUARD_TOS_ANY_SET_r11 1048 +#define _GUARD_TOS_ANY_SET_r22 1049 +#define _GUARD_TOS_ANY_SET_r33 1050 +#define _GUARD_TOS_DICT_r01 1051 +#define _GUARD_TOS_DICT_r11 1052 +#define _GUARD_TOS_DICT_r22 1053 +#define _GUARD_TOS_DICT_r33 1054 +#define _GUARD_TOS_FLOAT_r01 1055 +#define _GUARD_TOS_FLOAT_r11 1056 +#define _GUARD_TOS_FLOAT_r22 1057 +#define _GUARD_TOS_FLOAT_r33 1058 +#define _GUARD_TOS_FROZENDICT_r01 1059 +#define _GUARD_TOS_FROZENDICT_r11 1060 +#define _GUARD_TOS_FROZENDICT_r22 1061 +#define _GUARD_TOS_FROZENDICT_r33 1062 +#define _GUARD_TOS_FROZENSET_r01 1063 +#define _GUARD_TOS_FROZENSET_r11 1064 +#define _GUARD_TOS_FROZENSET_r22 1065 +#define _GUARD_TOS_FROZENSET_r33 1066 +#define _GUARD_TOS_INT_r01 1067 +#define _GUARD_TOS_INT_r11 1068 +#define _GUARD_TOS_INT_r22 1069 +#define _GUARD_TOS_INT_r33 1070 +#define _GUARD_TOS_LIST_r01 1071 +#define _GUARD_TOS_LIST_r11 1072 +#define _GUARD_TOS_LIST_r22 1073 +#define _GUARD_TOS_LIST_r33 1074 +#define _GUARD_TOS_OVERFLOWED_r01 1075 +#define _GUARD_TOS_OVERFLOWED_r11 1076 +#define _GUARD_TOS_OVERFLOWED_r22 1077 +#define _GUARD_TOS_OVERFLOWED_r33 1078 +#define _GUARD_TOS_SET_r01 1079 +#define _GUARD_TOS_SET_r11 1080 +#define _GUARD_TOS_SET_r22 1081 +#define _GUARD_TOS_SET_r33 1082 +#define _GUARD_TOS_SLICE_r01 1083 +#define _GUARD_TOS_SLICE_r11 1084 +#define _GUARD_TOS_SLICE_r22 1085 +#define _GUARD_TOS_SLICE_r33 1086 +#define _GUARD_TOS_TUPLE_r01 1087 +#define _GUARD_TOS_TUPLE_r11 1088 +#define _GUARD_TOS_TUPLE_r22 1089 +#define _GUARD_TOS_TUPLE_r33 1090 +#define _GUARD_TOS_UNICODE_r01 1091 +#define _GUARD_TOS_UNICODE_r11 1092 +#define _GUARD_TOS_UNICODE_r22 1093 +#define _GUARD_TOS_UNICODE_r33 1094 +#define _GUARD_TYPE_VERSION_r01 1095 +#define _GUARD_TYPE_VERSION_r11 1096 +#define _GUARD_TYPE_VERSION_r22 1097 +#define _GUARD_TYPE_VERSION_r33 1098 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1099 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1100 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1101 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1102 +#define _HANDLE_PENDING_AND_DEOPT_r00 1103 +#define _HANDLE_PENDING_AND_DEOPT_r10 1104 +#define _HANDLE_PENDING_AND_DEOPT_r20 1105 +#define _HANDLE_PENDING_AND_DEOPT_r30 1106 +#define _IMPORT_FROM_r12 1107 +#define _IMPORT_NAME_r21 1108 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1109 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1110 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1111 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1112 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1113 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1114 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1115 +#define _INSERT_1_LOAD_CONST_INLINE_r02 1116 +#define _INSERT_1_LOAD_CONST_INLINE_r12 1117 +#define _INSERT_1_LOAD_CONST_INLINE_r23 1118 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1119 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1120 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1121 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1122 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1123 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1124 +#define _INSERT_NULL_r10 1125 +#define _INSTRUMENTED_FOR_ITER_r23 1126 +#define _INSTRUMENTED_INSTRUCTION_r00 1127 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1128 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1129 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1130 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1131 +#define _INSTRUMENTED_LINE_r00 1132 +#define _INSTRUMENTED_NOT_TAKEN_r00 1133 +#define _INSTRUMENTED_NOT_TAKEN_r11 1134 +#define _INSTRUMENTED_NOT_TAKEN_r22 1135 +#define _INSTRUMENTED_NOT_TAKEN_r33 1136 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1137 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1138 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1139 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1140 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1141 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1142 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1143 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1144 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1145 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1146 +#define _IS_NONE_r11 1147 +#define _IS_OP_r03 1148 +#define _IS_OP_r13 1149 +#define _IS_OP_r23 1150 +#define _ITER_CHECK_LIST_r02 1151 +#define _ITER_CHECK_LIST_r12 1152 +#define _ITER_CHECK_LIST_r22 1153 +#define _ITER_CHECK_LIST_r33 1154 +#define _ITER_CHECK_RANGE_r02 1155 +#define _ITER_CHECK_RANGE_r12 1156 +#define _ITER_CHECK_RANGE_r22 1157 +#define _ITER_CHECK_RANGE_r33 1158 +#define _ITER_CHECK_TUPLE_r02 1159 +#define _ITER_CHECK_TUPLE_r12 1160 +#define _ITER_CHECK_TUPLE_r22 1161 +#define _ITER_CHECK_TUPLE_r33 1162 +#define _ITER_JUMP_LIST_r02 1163 +#define _ITER_JUMP_LIST_r12 1164 +#define _ITER_JUMP_LIST_r22 1165 +#define _ITER_JUMP_LIST_r33 1166 +#define _ITER_JUMP_RANGE_r02 1167 +#define _ITER_JUMP_RANGE_r12 1168 +#define _ITER_JUMP_RANGE_r22 1169 +#define _ITER_JUMP_RANGE_r33 1170 +#define _ITER_JUMP_TUPLE_r02 1171 +#define _ITER_JUMP_TUPLE_r12 1172 +#define _ITER_JUMP_TUPLE_r22 1173 +#define _ITER_JUMP_TUPLE_r33 1174 +#define _ITER_NEXT_LIST_r23 1175 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1176 +#define _ITER_NEXT_RANGE_r03 1177 +#define _ITER_NEXT_RANGE_r13 1178 +#define _ITER_NEXT_RANGE_r23 1179 +#define _ITER_NEXT_TUPLE_r03 1180 +#define _ITER_NEXT_TUPLE_r13 1181 +#define _ITER_NEXT_TUPLE_r23 1182 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1183 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1184 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1185 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1186 +#define _JUMP_TO_TOP_r00 1187 +#define _LIST_APPEND_r10 1188 +#define _LIST_EXTEND_r11 1189 +#define _LOAD_ATTR_r10 1190 +#define _LOAD_ATTR_CLASS_r11 1191 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1192 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1193 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1194 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1195 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1196 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1197 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1198 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1199 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1200 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1201 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1202 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1203 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1204 +#define _LOAD_ATTR_MODULE_r12 1205 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1206 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1207 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1208 +#define _LOAD_ATTR_SLOT_r02 1209 +#define _LOAD_ATTR_SLOT_r12 1210 +#define _LOAD_ATTR_SLOT_r23 1211 +#define _LOAD_ATTR_WITH_HINT_r12 1212 +#define _LOAD_BUILD_CLASS_r01 1213 +#define _LOAD_BYTECODE_r00 1214 +#define _LOAD_COMMON_CONSTANT_r01 1215 +#define _LOAD_COMMON_CONSTANT_r12 1216 +#define _LOAD_COMMON_CONSTANT_r23 1217 +#define _LOAD_CONST_r01 1218 +#define _LOAD_CONST_r12 1219 +#define _LOAD_CONST_r23 1220 +#define _LOAD_CONST_INLINE_r01 1221 +#define _LOAD_CONST_INLINE_r12 1222 +#define _LOAD_CONST_INLINE_r23 1223 +#define _LOAD_CONST_INLINE_BORROW_r01 1224 +#define _LOAD_CONST_INLINE_BORROW_r12 1225 +#define _LOAD_CONST_INLINE_BORROW_r23 1226 +#define _LOAD_CONST_UNDER_INLINE_r02 1227 +#define _LOAD_CONST_UNDER_INLINE_r12 1228 +#define _LOAD_CONST_UNDER_INLINE_r23 1229 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1230 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1231 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1232 +#define _LOAD_DEREF_r01 1233 +#define _LOAD_FAST_r01 1234 +#define _LOAD_FAST_r12 1235 +#define _LOAD_FAST_r23 1236 +#define _LOAD_FAST_0_r01 1237 +#define _LOAD_FAST_0_r12 1238 +#define _LOAD_FAST_0_r23 1239 +#define _LOAD_FAST_1_r01 1240 +#define _LOAD_FAST_1_r12 1241 +#define _LOAD_FAST_1_r23 1242 +#define _LOAD_FAST_2_r01 1243 +#define _LOAD_FAST_2_r12 1244 +#define _LOAD_FAST_2_r23 1245 +#define _LOAD_FAST_3_r01 1246 +#define _LOAD_FAST_3_r12 1247 +#define _LOAD_FAST_3_r23 1248 +#define _LOAD_FAST_4_r01 1249 +#define _LOAD_FAST_4_r12 1250 +#define _LOAD_FAST_4_r23 1251 +#define _LOAD_FAST_5_r01 1252 +#define _LOAD_FAST_5_r12 1253 +#define _LOAD_FAST_5_r23 1254 +#define _LOAD_FAST_6_r01 1255 +#define _LOAD_FAST_6_r12 1256 +#define _LOAD_FAST_6_r23 1257 +#define _LOAD_FAST_7_r01 1258 +#define _LOAD_FAST_7_r12 1259 +#define _LOAD_FAST_7_r23 1260 +#define _LOAD_FAST_AND_CLEAR_r01 1261 +#define _LOAD_FAST_AND_CLEAR_r12 1262 +#define _LOAD_FAST_AND_CLEAR_r23 1263 +#define _LOAD_FAST_BORROW_r01 1264 +#define _LOAD_FAST_BORROW_r12 1265 +#define _LOAD_FAST_BORROW_r23 1266 +#define _LOAD_FAST_BORROW_0_r01 1267 +#define _LOAD_FAST_BORROW_0_r12 1268 +#define _LOAD_FAST_BORROW_0_r23 1269 +#define _LOAD_FAST_BORROW_1_r01 1270 +#define _LOAD_FAST_BORROW_1_r12 1271 +#define _LOAD_FAST_BORROW_1_r23 1272 +#define _LOAD_FAST_BORROW_2_r01 1273 +#define _LOAD_FAST_BORROW_2_r12 1274 +#define _LOAD_FAST_BORROW_2_r23 1275 +#define _LOAD_FAST_BORROW_3_r01 1276 +#define _LOAD_FAST_BORROW_3_r12 1277 +#define _LOAD_FAST_BORROW_3_r23 1278 +#define _LOAD_FAST_BORROW_4_r01 1279 +#define _LOAD_FAST_BORROW_4_r12 1280 +#define _LOAD_FAST_BORROW_4_r23 1281 +#define _LOAD_FAST_BORROW_5_r01 1282 +#define _LOAD_FAST_BORROW_5_r12 1283 +#define _LOAD_FAST_BORROW_5_r23 1284 +#define _LOAD_FAST_BORROW_6_r01 1285 +#define _LOAD_FAST_BORROW_6_r12 1286 +#define _LOAD_FAST_BORROW_6_r23 1287 +#define _LOAD_FAST_BORROW_7_r01 1288 +#define _LOAD_FAST_BORROW_7_r12 1289 +#define _LOAD_FAST_BORROW_7_r23 1290 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1291 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1292 +#define _LOAD_FAST_CHECK_r01 1293 +#define _LOAD_FAST_CHECK_r12 1294 +#define _LOAD_FAST_CHECK_r23 1295 +#define _LOAD_FAST_LOAD_FAST_r02 1296 +#define _LOAD_FAST_LOAD_FAST_r13 1297 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1298 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1299 +#define _LOAD_GLOBAL_r00 1300 +#define _LOAD_GLOBAL_BUILTINS_r01 1301 +#define _LOAD_GLOBAL_MODULE_r01 1302 +#define _LOAD_LOCALS_r01 1303 +#define _LOAD_LOCALS_r12 1304 +#define _LOAD_LOCALS_r23 1305 +#define _LOAD_NAME_r01 1306 +#define _LOAD_SMALL_INT_r01 1307 +#define _LOAD_SMALL_INT_r12 1308 +#define _LOAD_SMALL_INT_r23 1309 +#define _LOAD_SMALL_INT_0_r01 1310 +#define _LOAD_SMALL_INT_0_r12 1311 +#define _LOAD_SMALL_INT_0_r23 1312 +#define _LOAD_SMALL_INT_1_r01 1313 +#define _LOAD_SMALL_INT_1_r12 1314 +#define _LOAD_SMALL_INT_1_r23 1315 +#define _LOAD_SMALL_INT_2_r01 1316 +#define _LOAD_SMALL_INT_2_r12 1317 +#define _LOAD_SMALL_INT_2_r23 1318 +#define _LOAD_SMALL_INT_3_r01 1319 +#define _LOAD_SMALL_INT_3_r12 1320 +#define _LOAD_SMALL_INT_3_r23 1321 +#define _LOAD_SPECIAL_r00 1322 +#define _LOAD_SUPER_ATTR_ATTR_r31 1323 +#define _LOAD_SUPER_ATTR_METHOD_r32 1324 +#define _LOCK_OBJECT_r01 1325 +#define _LOCK_OBJECT_r11 1326 +#define _LOCK_OBJECT_r22 1327 +#define _LOCK_OBJECT_r33 1328 +#define _MAKE_CALLARGS_A_TUPLE_r33 1329 +#define _MAKE_CELL_r00 1330 +#define _MAKE_FUNCTION_r11 1331 +#define _MAKE_HEAP_SAFE_r01 1332 +#define _MAKE_HEAP_SAFE_r11 1333 +#define _MAKE_HEAP_SAFE_r22 1334 +#define _MAKE_HEAP_SAFE_r33 1335 +#define _MAKE_WARM_r00 1336 +#define _MAKE_WARM_r11 1337 +#define _MAKE_WARM_r22 1338 +#define _MAKE_WARM_r33 1339 +#define _MAP_ADD_r20 1340 +#define _MATCH_CLASS_r33 1341 +#define _MATCH_KEYS_r23 1342 +#define _MATCH_MAPPING_r02 1343 +#define _MATCH_MAPPING_r12 1344 +#define _MATCH_MAPPING_r23 1345 +#define _MATCH_SEQUENCE_r02 1346 +#define _MATCH_SEQUENCE_r12 1347 +#define _MATCH_SEQUENCE_r23 1348 +#define _MAYBE_EXPAND_METHOD_r00 1349 +#define _MAYBE_EXPAND_METHOD_KW_r11 1350 +#define _MONITOR_CALL_r00 1351 +#define _MONITOR_CALL_KW_r11 1352 +#define _MONITOR_JUMP_BACKWARD_r00 1353 +#define _MONITOR_JUMP_BACKWARD_r11 1354 +#define _MONITOR_JUMP_BACKWARD_r22 1355 +#define _MONITOR_JUMP_BACKWARD_r33 1356 +#define _MONITOR_RESUME_r00 1357 +#define _NOP_r00 1358 +#define _NOP_r11 1359 +#define _NOP_r22 1360 +#define _NOP_r33 1361 +#define _POP_CALL_r20 1362 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1363 +#define _POP_CALL_ONE_r30 1364 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1365 +#define _POP_CALL_TWO_r30 1366 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1367 +#define _POP_EXCEPT_r10 1368 +#define _POP_ITER_r20 1369 +#define _POP_JUMP_IF_FALSE_r00 1370 +#define _POP_JUMP_IF_FALSE_r10 1371 +#define _POP_JUMP_IF_FALSE_r21 1372 +#define _POP_JUMP_IF_FALSE_r32 1373 +#define _POP_JUMP_IF_TRUE_r00 1374 +#define _POP_JUMP_IF_TRUE_r10 1375 +#define _POP_JUMP_IF_TRUE_r21 1376 +#define _POP_JUMP_IF_TRUE_r32 1377 +#define _POP_TOP_r10 1378 +#define _POP_TOP_FLOAT_r00 1379 +#define _POP_TOP_FLOAT_r10 1380 +#define _POP_TOP_FLOAT_r21 1381 +#define _POP_TOP_FLOAT_r32 1382 +#define _POP_TOP_INT_r00 1383 +#define _POP_TOP_INT_r10 1384 +#define _POP_TOP_INT_r21 1385 +#define _POP_TOP_INT_r32 1386 +#define _POP_TOP_LOAD_CONST_INLINE_r11 1387 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1388 +#define _POP_TOP_NOP_r00 1389 +#define _POP_TOP_NOP_r10 1390 +#define _POP_TOP_NOP_r21 1391 +#define _POP_TOP_NOP_r32 1392 +#define _POP_TOP_UNICODE_r00 1393 +#define _POP_TOP_UNICODE_r10 1394 +#define _POP_TOP_UNICODE_r21 1395 +#define _POP_TOP_UNICODE_r32 1396 +#define _POP_TWO_r20 1397 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1398 +#define _PUSH_EXC_INFO_r02 1399 +#define _PUSH_EXC_INFO_r12 1400 +#define _PUSH_EXC_INFO_r23 1401 +#define _PUSH_FRAME_r10 1402 +#define _PUSH_NULL_r01 1403 +#define _PUSH_NULL_r12 1404 +#define _PUSH_NULL_r23 1405 +#define _PUSH_NULL_CONDITIONAL_r00 1406 +#define _PY_FRAME_EX_r31 1407 +#define _PY_FRAME_GENERAL_r01 1408 +#define _PY_FRAME_KW_r11 1409 +#define _REPLACE_WITH_TRUE_r02 1410 +#define _REPLACE_WITH_TRUE_r12 1411 +#define _REPLACE_WITH_TRUE_r23 1412 +#define _RESUME_CHECK_r00 1413 +#define _RESUME_CHECK_r11 1414 +#define _RESUME_CHECK_r22 1415 +#define _RESUME_CHECK_r33 1416 +#define _RETURN_GENERATOR_r01 1417 +#define _RETURN_VALUE_r11 1418 +#define _SAVE_RETURN_OFFSET_r00 1419 +#define _SAVE_RETURN_OFFSET_r11 1420 +#define _SAVE_RETURN_OFFSET_r22 1421 +#define _SAVE_RETURN_OFFSET_r33 1422 +#define _SEND_r33 1423 +#define _SEND_GEN_FRAME_r33 1424 +#define _SETUP_ANNOTATIONS_r00 1425 +#define _SET_ADD_r10 1426 +#define _SET_FUNCTION_ATTRIBUTE_r01 1427 +#define _SET_FUNCTION_ATTRIBUTE_r11 1428 +#define _SET_FUNCTION_ATTRIBUTE_r21 1429 +#define _SET_FUNCTION_ATTRIBUTE_r32 1430 +#define _SET_IP_r00 1431 +#define _SET_IP_r11 1432 +#define _SET_IP_r22 1433 +#define _SET_IP_r33 1434 +#define _SET_UPDATE_r11 1435 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1436 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1437 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1438 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1439 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1440 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1441 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1442 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1443 +#define _SPILL_OR_RELOAD_r01 1444 +#define _SPILL_OR_RELOAD_r02 1445 +#define _SPILL_OR_RELOAD_r03 1446 +#define _SPILL_OR_RELOAD_r10 1447 +#define _SPILL_OR_RELOAD_r12 1448 +#define _SPILL_OR_RELOAD_r13 1449 +#define _SPILL_OR_RELOAD_r20 1450 +#define _SPILL_OR_RELOAD_r21 1451 +#define _SPILL_OR_RELOAD_r23 1452 +#define _SPILL_OR_RELOAD_r30 1453 +#define _SPILL_OR_RELOAD_r31 1454 +#define _SPILL_OR_RELOAD_r32 1455 +#define _START_EXECUTOR_r00 1456 +#define _STORE_ATTR_r20 1457 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1458 +#define _STORE_ATTR_SLOT_r21 1459 +#define _STORE_ATTR_WITH_HINT_r21 1460 +#define _STORE_DEREF_r10 1461 +#define _STORE_FAST_LOAD_FAST_r11 1462 +#define _STORE_FAST_STORE_FAST_r20 1463 +#define _STORE_GLOBAL_r10 1464 +#define _STORE_NAME_r10 1465 +#define _STORE_SLICE_r30 1466 +#define _STORE_SUBSCR_r30 1467 +#define _STORE_SUBSCR_DICT_r31 1468 +#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1469 +#define _STORE_SUBSCR_LIST_INT_r32 1470 +#define _SWAP_r11 1471 +#define _SWAP_2_r02 1472 +#define _SWAP_2_r12 1473 +#define _SWAP_2_r22 1474 +#define _SWAP_2_r33 1475 +#define _SWAP_3_r03 1476 +#define _SWAP_3_r13 1477 +#define _SWAP_3_r23 1478 +#define _SWAP_3_r33 1479 +#define _SWAP_FAST_r01 1480 +#define _SWAP_FAST_r11 1481 +#define _SWAP_FAST_r22 1482 +#define _SWAP_FAST_r33 1483 +#define _SWAP_FAST_0_r01 1484 +#define _SWAP_FAST_0_r11 1485 +#define _SWAP_FAST_0_r22 1486 +#define _SWAP_FAST_0_r33 1487 +#define _SWAP_FAST_1_r01 1488 +#define _SWAP_FAST_1_r11 1489 +#define _SWAP_FAST_1_r22 1490 +#define _SWAP_FAST_1_r33 1491 +#define _SWAP_FAST_2_r01 1492 +#define _SWAP_FAST_2_r11 1493 +#define _SWAP_FAST_2_r22 1494 +#define _SWAP_FAST_2_r33 1495 +#define _SWAP_FAST_3_r01 1496 +#define _SWAP_FAST_3_r11 1497 +#define _SWAP_FAST_3_r22 1498 +#define _SWAP_FAST_3_r33 1499 +#define _SWAP_FAST_4_r01 1500 +#define _SWAP_FAST_4_r11 1501 +#define _SWAP_FAST_4_r22 1502 +#define _SWAP_FAST_4_r33 1503 +#define _SWAP_FAST_5_r01 1504 +#define _SWAP_FAST_5_r11 1505 +#define _SWAP_FAST_5_r22 1506 +#define _SWAP_FAST_5_r33 1507 +#define _SWAP_FAST_6_r01 1508 +#define _SWAP_FAST_6_r11 1509 +#define _SWAP_FAST_6_r22 1510 +#define _SWAP_FAST_6_r33 1511 +#define _SWAP_FAST_7_r01 1512 +#define _SWAP_FAST_7_r11 1513 +#define _SWAP_FAST_7_r22 1514 +#define _SWAP_FAST_7_r33 1515 +#define _TIER2_RESUME_CHECK_r00 1516 +#define _TIER2_RESUME_CHECK_r11 1517 +#define _TIER2_RESUME_CHECK_r22 1518 +#define _TIER2_RESUME_CHECK_r33 1519 +#define _TO_BOOL_r11 1520 +#define _TO_BOOL_BOOL_r01 1521 +#define _TO_BOOL_BOOL_r11 1522 +#define _TO_BOOL_BOOL_r22 1523 +#define _TO_BOOL_BOOL_r33 1524 +#define _TO_BOOL_INT_r02 1525 +#define _TO_BOOL_INT_r12 1526 +#define _TO_BOOL_INT_r23 1527 +#define _TO_BOOL_LIST_r02 1528 +#define _TO_BOOL_LIST_r12 1529 +#define _TO_BOOL_LIST_r23 1530 +#define _TO_BOOL_NONE_r01 1531 +#define _TO_BOOL_NONE_r11 1532 +#define _TO_BOOL_NONE_r22 1533 +#define _TO_BOOL_NONE_r33 1534 +#define _TO_BOOL_STR_r02 1535 +#define _TO_BOOL_STR_r12 1536 +#define _TO_BOOL_STR_r23 1537 +#define _TRACE_RECORD_r00 1538 +#define _UNARY_INVERT_r12 1539 +#define _UNARY_NEGATIVE_r12 1540 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1541 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1542 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1543 +#define _UNARY_NOT_r01 1544 +#define _UNARY_NOT_r11 1545 +#define _UNARY_NOT_r22 1546 +#define _UNARY_NOT_r33 1547 +#define _UNPACK_EX_r10 1548 +#define _UNPACK_SEQUENCE_r10 1549 +#define _UNPACK_SEQUENCE_LIST_r10 1550 +#define _UNPACK_SEQUENCE_TUPLE_r10 1551 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1552 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1553 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1554 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1555 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1556 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1557 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1558 +#define _WITH_EXCEPT_START_r33 1559 +#define _YIELD_VALUE_r11 1560 +#define MAX_UOP_REGS_ID 1560 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 6e1883009b1d28..4e16c3040c7c92 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -138,6 +138,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_GUARD_TOS_ANY_DICT] = HAS_EXIT_FLAG, [_GUARD_TOS_DICT] = HAS_EXIT_FLAG, [_GUARD_TOS_FROZENDICT] = HAS_EXIT_FLAG, + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_SUBSCR_DICT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_SUBSCR_CHECK_FUNC] = HAS_EXIT_FLAG, [_BINARY_OP_SUBSCR_INIT_CALL] = 0, @@ -146,6 +147,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_STORE_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_STORE_SUBSCR_LIST_INT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_STORE_SUBSCR_DICT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_STORE_SUBSCR_DICT_KNOWN_HASH] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_DELETE_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_INTRINSIC_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CALL_INTRINSIC_2] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, @@ -1352,6 +1354,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _GUARD_TOS_FROZENDICT_r33 }, }, }, + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH] = { + .best = { 2, 2, 2, 2 }, + .entries = { + { -1, -1, -1 }, + { -1, -1, -1 }, + { 3, 2, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 }, + { -1, -1, -1 }, + }, + }, [_BINARY_OP_SUBSCR_DICT] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -1424,6 +1435,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 1, 3, _STORE_SUBSCR_DICT_r31 }, }, }, + [_STORE_SUBSCR_DICT_KNOWN_HASH] = { + .best = { 3, 3, 3, 3 }, + .entries = { + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { 1, 3, _STORE_SUBSCR_DICT_KNOWN_HASH_r31 }, + }, + }, [_DELETE_SUBSCR] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -4022,6 +4042,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_FROZENDICT_r11] = _GUARD_TOS_FROZENDICT, [_GUARD_TOS_FROZENDICT_r22] = _GUARD_TOS_FROZENDICT, [_GUARD_TOS_FROZENDICT_r33] = _GUARD_TOS_FROZENDICT, + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23] = _BINARY_OP_SUBSCR_DICT_KNOWN_HASH, [_BINARY_OP_SUBSCR_DICT_r23] = _BINARY_OP_SUBSCR_DICT, [_BINARY_OP_SUBSCR_CHECK_FUNC_r23] = _BINARY_OP_SUBSCR_CHECK_FUNC, [_BINARY_OP_SUBSCR_INIT_CALL_r01] = _BINARY_OP_SUBSCR_INIT_CALL, @@ -4033,6 +4054,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_STORE_SUBSCR_r30] = _STORE_SUBSCR, [_STORE_SUBSCR_LIST_INT_r32] = _STORE_SUBSCR_LIST_INT, [_STORE_SUBSCR_DICT_r31] = _STORE_SUBSCR_DICT, + [_STORE_SUBSCR_DICT_KNOWN_HASH_r31] = _STORE_SUBSCR_DICT_KNOWN_HASH, [_DELETE_SUBSCR_r20] = _DELETE_SUBSCR, [_CALL_INTRINSIC_1_r12] = _CALL_INTRINSIC_1, [_CALL_INTRINSIC_2_r23] = _CALL_INTRINSIC_2, @@ -4639,6 +4661,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBSCR_CHECK_FUNC_r23] = "_BINARY_OP_SUBSCR_CHECK_FUNC_r23", [_BINARY_OP_SUBSCR_DICT] = "_BINARY_OP_SUBSCR_DICT", [_BINARY_OP_SUBSCR_DICT_r23] = "_BINARY_OP_SUBSCR_DICT_r23", + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH] = "_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23] = "_BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23", [_BINARY_OP_SUBSCR_INIT_CALL] = "_BINARY_OP_SUBSCR_INIT_CALL", [_BINARY_OP_SUBSCR_INIT_CALL_r01] = "_BINARY_OP_SUBSCR_INIT_CALL_r01", [_BINARY_OP_SUBSCR_INIT_CALL_r11] = "_BINARY_OP_SUBSCR_INIT_CALL_r11", @@ -5706,6 +5730,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_STORE_SUBSCR_r30] = "_STORE_SUBSCR_r30", [_STORE_SUBSCR_DICT] = "_STORE_SUBSCR_DICT", [_STORE_SUBSCR_DICT_r31] = "_STORE_SUBSCR_DICT_r31", + [_STORE_SUBSCR_DICT_KNOWN_HASH] = "_STORE_SUBSCR_DICT_KNOWN_HASH", + [_STORE_SUBSCR_DICT_KNOWN_HASH_r31] = "_STORE_SUBSCR_DICT_KNOWN_HASH_r31", [_STORE_SUBSCR_LIST_INT] = "_STORE_SUBSCR_LIST_INT", [_STORE_SUBSCR_LIST_INT_r32] = "_STORE_SUBSCR_LIST_INT_r32", [_SWAP] = "_SWAP", @@ -6040,6 +6066,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _GUARD_TOS_FROZENDICT: return 0; + case _BINARY_OP_SUBSCR_DICT_KNOWN_HASH: + return 2; case _BINARY_OP_SUBSCR_DICT: return 2; case _BINARY_OP_SUBSCR_CHECK_FUNC: @@ -6056,6 +6084,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 3; case _STORE_SUBSCR_DICT: return 3; + case _STORE_SUBSCR_DICT_KNOWN_HASH: + return 3; case _DELETE_SUBSCR: return 2; case _CALL_INTRINSIC_1: diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 60f5cb6edbce43..2005dd9b0866bd 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -23,6 +23,11 @@ # For frozendict JIT tests FROZEN_DICT_CONST = frozendict(x=1, y=2) +class _GenericKey: + pass + +_GENERIC_KEY = _GenericKey() + @contextlib.contextmanager def clear_executors(func): @@ -2007,8 +2012,8 @@ def f(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertEqual(uops.count("_GUARD_NOS_DICT"), 0) - self.assertEqual(uops.count("_STORE_SUBSCR_DICT"), 1) - self.assertEqual(uops.count("_BINARY_OP_SUBSCR_DICT"), 1) + self.assertEqual(uops.count("_STORE_SUBSCR_DICT_KNOWN_HASH"), 1) + self.assertEqual(uops.count("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH"), 1) def test_remove_guard_for_known_type_list(self): def f(n): @@ -2312,9 +2317,46 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_BINARY_OP_SUBSCR_DICT", uops) + self.assertIn("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) + def test_binary_op_subscr_dict_known_hash(self): + # str, int, bytes, float, complex, tuple and any python object which has generic hash + def testfunc(n): + x = 0 + d = {'a': 1, 1: 2, b'b': 3, (1, 2): 4, _GENERIC_KEY: 5, 1.5: 6, 1+2j: 7} + for _ in range(n): + x += d['a'] + d[1] + d[b'b'] + d[(1, 2)] + d[_GENERIC_KEY] + d[1.5] + d[1+2j] + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 28 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", uops) + self.assertNotIn("_BINARY_OP_SUBSCR_DICT", uops) + + def test_store_subscr_dict_known_hash(self): + # str, int, bytes, float, complex, tuple and any python object which has generic hash + def testfunc(n): + d = {'a': 0, 1: 0, b'b': 0, (1, 2): 0, _GENERIC_KEY: 0, 1.5: 0, 1+2j: 0} + for _ in range(n): + d['a'] += 1 + d[1] += 2 + d[b'b'] += 3 + d[(1, 2)] += 4 + d[_GENERIC_KEY] += 5 + d[1.5] += 6 + d[1+2j] += 7 + return d['a'] + d[1] + d[b'b'] + d[(1, 2)] + d[_GENERIC_KEY] + d[1.5] + d[1+2j] + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 28 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_STORE_SUBSCR_DICT_KNOWN_HASH", uops) + self.assertNotIn("_STORE_SUBSCR_DICT", uops) + def test_contains_op(self): def testfunc(n): x = 0 @@ -3701,7 +3743,7 @@ def testfunc(n): self.assertEqual(res, 10) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_STORE_SUBSCR_DICT", uops) + self.assertIn("_STORE_SUBSCR_DICT_KNOWN_HASH", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 1) self.assertIn("_POP_TOP_NOP", uops) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index e392e44267e287..67bc4319e0bae2 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2727,13 +2727,23 @@ _PyDict_LoadBuiltinsFromGlobals(PyObject *globals) /* Consumes references to key and value */ static int -setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value) +setitem_take2_lock_held_known_hash(PyDictObject *mp, PyObject *key, PyObject *value, Py_hash_t hash) { assert(PyAnyDict_Check(mp)); assert(can_modify_dict(mp)); assert(key); assert(value); + if (mp->ma_keys == Py_EMPTY_KEYS) { + return insert_to_emptydict(mp, key, hash, value); + } + /* insertdict() handles any resizing that might be necessary */ + return insertdict(mp, key, hash, value); +} + +static int +setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value) +{ Py_hash_t hash = _PyObject_HashFast(key); if (hash == -1) { dict_unhashable_type((PyObject*)mp, key); @@ -2742,11 +2752,7 @@ setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value) return -1; } - if (mp->ma_keys == Py_EMPTY_KEYS) { - return insert_to_emptydict(mp, key, hash, value); - } - /* insertdict() handles any resizing that might be necessary */ - return insertdict(mp, key, hash, value); + return setitem_take2_lock_held_known_hash(mp, key, value, hash); } int @@ -2759,6 +2765,16 @@ _PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value) return res; } +int +_PyDict_SetItem_Take2_KnownHash(PyDictObject *mp, PyObject *key, PyObject *value, Py_hash_t hash) +{ + int res; + Py_BEGIN_CRITICAL_SECTION(mp); + res = setitem_take2_lock_held_known_hash(mp, key, value, hash); + Py_END_CRITICAL_SECTION(); + return res; +} + /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the * dictionary if it's merely replacing the value for an existing key. * This means that it's safe to loop over a dictionary with PyDict_Next() diff --git a/Python/bytecodes.c b/Python/bytecodes.c index ab128661096ea1..18fea9ae4a21f4 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1175,6 +1175,26 @@ dummy_func( macro(BINARY_OP_SUBSCR_DICT) = _GUARD_NOS_ANY_DICT + unused/5 + _BINARY_OP_SUBSCR_DICT + POP_TOP + POP_TOP; + tier2 op(_BINARY_OP_SUBSCR_DICT_KNOWN_HASH, (dict_st, sub_st, hash/4 -- res, ds, ss)) { + PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + + assert(PyAnyDict_CheckExact(dict)); + STAT_INC(BINARY_OP, hit); + PyObject *res_o; + int rc = _PyDict_GetItemRef_KnownHash((PyDictObject *)dict, sub, (Py_hash_t)hash, &res_o); + if (rc == 0) { + _PyErr_SetKeyError(sub); + } + if (rc <= 0) { + ERROR_NO_POP(); + } + res = PyStackRef_FromPyObjectSteal(res_o); + ds = dict_st; + ss = sub_st; + INPUTS_DEAD(); + } + op(_BINARY_OP_SUBSCR_DICT, (dict_st, sub_st -- res, ds, ss)) { PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); @@ -1319,6 +1339,24 @@ dummy_func( st = dict_st; } + tier2 op(_STORE_SUBSCR_DICT_KNOWN_HASH, (value, dict_st, sub, hash/4 -- st)) { + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + + assert(PyDict_CheckExact(dict)); + STAT_INC(STORE_SUBSCR, hit); + int err = _PyDict_SetItem_Take2_KnownHash((PyDictObject *)dict, + PyStackRef_AsPyObjectSteal(sub), + PyStackRef_AsPyObjectSteal(value), + (Py_hash_t)hash); + + if (err) { + PyStackRef_CLOSE(dict_st); + ERROR_IF(1); + } + DEAD(dict_st); + st = dict_st; + } + inst(DELETE_SUBSCR, (container, sub --)) { /* del container[sub] */ int err = PyObject_DelItem(PyStackRef_AsPyObjectBorrow(container), diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 93533e374fdf44..46740b3954ef9e 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -6906,6 +6906,53 @@ break; } + case _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef sub_st; + _PyStackRef dict_st; + _PyStackRef res; + _PyStackRef ds; + _PyStackRef ss; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + sub_st = _stack_item_1; + dict_st = _stack_item_0; + PyObject *hash = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + assert(PyAnyDict_CheckExact(dict)); + STAT_INC(BINARY_OP, hit); + PyObject *res_o; + stack_pointer[0] = dict_st; + stack_pointer[1] = sub_st; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + int rc = _PyDict_GetItemRef_KnownHash((PyDictObject *)dict, sub, (Py_hash_t)hash, &res_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (rc == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_SetKeyError(sub); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + if (rc <= 0) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = PyStackRef_FromPyObjectSteal(res_o); + ds = dict_st; + ss = sub_st; + _tos_cache2 = ss; + _tos_cache1 = ds; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _BINARY_OP_SUBSCR_DICT_r23: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -7315,6 +7362,54 @@ break; } + case _STORE_SUBSCR_DICT_KNOWN_HASH_r31: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef sub; + _PyStackRef dict_st; + _PyStackRef value; + _PyStackRef st; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + sub = _stack_item_2; + dict_st = _stack_item_1; + value = _stack_item_0; + PyObject *hash = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + assert(PyDict_CheckExact(dict)); + STAT_INC(STORE_SUBSCR, hit); + stack_pointer[0] = value; + stack_pointer[1] = dict_st; + stack_pointer[2] = sub; + stack_pointer += 3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _PyDict_SetItem_Take2_KnownHash((PyDictObject *)dict, + PyStackRef_AsPyObjectSteal(sub), + PyStackRef_AsPyObjectSteal(value), + (Py_hash_t)hash); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err) { + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(dict_st); + stack_pointer = _PyFrame_GetStackPointer(frame); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + st = dict_st; + _tos_cache0 = st; + _tos_cache1 = PyStackRef_ZERO_BITS; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _DELETE_SUBSCR_r20: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 0c25c0c9bc0d1c..4672a272fc9203 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -348,6 +348,33 @@ optimize_to_bool( return 0; } +static void +optimize_dict_known_hash( + JitOptContext *ctx, _PyBloomFilter *dependencies, _PyUOpInstruction *this_instr, + PyObject *sub, uint16_t opcode) +{ + if (PyUnicode_CheckExact(sub) || PyLong_CheckExact(sub) || PyBytes_CheckExact(sub) + || PyFloat_CheckExact(sub) || PyComplex_CheckExact(sub)) { + // PyObject_Hash can't fail on these types + ADD_OP(opcode, 0, PyObject_Hash(sub)); + } + else if (PyTuple_CheckExact(sub)) { + // only use known hash variant when hash of tuple is already computed + // since computing it can call arbitrary code + Py_hash_t hash = ((PyTupleObject *)sub)->ob_hash; + if (hash != -1) { + ADD_OP(opcode, 0, hash); + } + } + else if (Py_TYPE(sub)->tp_hash == PyBaseObject_Type.tp_hash) { + // for user-defined objects which don't override tp_hash + Py_hash_t hash = PyObject_Hash(sub); + ADD_OP(opcode, 0, hash); + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)Py_TYPE(sub)); + _Py_BloomFilter_Add(dependencies, Py_TYPE(sub)); + } +} + static void eliminate_pop_guard(_PyUOpInstruction *this_instr, JitOptContext *ctx, bool exit) { diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 6702f3c5665133..792f83cdbd2d3a 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -165,6 +165,11 @@ dummy_func(void) { } op(_STORE_SUBSCR_DICT, (value, dict_st, sub -- st)) { + PyObject *sub_o = sym_get_const(ctx, sub); + if (sub_o != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub_o, _STORE_SUBSCR_DICT_KNOWN_HASH); + } (void)value; st = dict_st; } @@ -482,6 +487,11 @@ dummy_func(void) { } op(_BINARY_OP_SUBSCR_DICT, (dict_st, sub_st -- res, ds, ss)) { + PyObject *sub = sym_get_const(ctx, sub_st); + if (sub != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH); + } res = sym_new_not_null(ctx); ds = dict_st; ss = sub_st; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index dd1d2813a215ca..7539133fb92096 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1316,6 +1316,22 @@ break; } + case _BINARY_OP_SUBSCR_DICT_KNOWN_HASH: { + JitOptRef res; + JitOptRef ds; + JitOptRef ss; + res = sym_new_not_null(ctx); + ds = sym_new_not_null(ctx); + ss = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = ds; + stack_pointer[0] = ss; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _BINARY_OP_SUBSCR_DICT: { JitOptRef sub_st; JitOptRef dict_st; @@ -1324,6 +1340,11 @@ JitOptRef ss; sub_st = stack_pointer[-1]; dict_st = stack_pointer[-2]; + PyObject *sub = sym_get_const(ctx, sub_st); + if (sub != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH); + } res = sym_new_not_null(ctx); ds = dict_st; ss = sub_st; @@ -1471,11 +1492,18 @@ } case _STORE_SUBSCR_DICT: { + JitOptRef sub; JitOptRef dict_st; JitOptRef value; JitOptRef st; + sub = stack_pointer[-1]; dict_st = stack_pointer[-2]; value = stack_pointer[-3]; + PyObject *sub_o = sym_get_const(ctx, sub); + if (sub_o != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub_o, _STORE_SUBSCR_DICT_KNOWN_HASH); + } (void)value; st = dict_st; CHECK_STACK_BOUNDS(-2); @@ -1485,6 +1513,16 @@ break; } + case _STORE_SUBSCR_DICT_KNOWN_HASH: { + JitOptRef st; + st = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-2); + stack_pointer[-3] = st; + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _DELETE_SUBSCR: { CHECK_STACK_BOUNDS(-2); stack_pointer += -2; From afd8113e9d7744e52ae82093628d373d6ecb9897 Mon Sep 17 00:00:00 2001 From: Neko Asakura Date: Tue, 31 Mar 2026 00:42:24 +0800 Subject: [PATCH 6/6] gh-144270: Make SubElement parent and tag positional-only (GH-144845) The C accelerator implementations use PyArg_ParseTuple, which inherently enforces positional-only parameters. The Python fallback allowed these as keyword arguments, creating a behavioral mismatch. Make the tag parameter of Element.__init__ and the parent and tag parameters of SubElement positional-only to align with the C accelerator. --- Doc/library/xml.etree.elementtree.rst | 10 ++++-- Lib/test/test_xml_etree.py | 35 +++++++++++++++++++ Lib/xml/etree/ElementTree.py | 4 +-- ...-02-19-16-34-18.gh-issue-144270.wJRtSr.rst | 3 ++ 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index 919d4c595bf793..bbb15ce5e758c6 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -691,7 +691,7 @@ Functions .. versionadded:: 3.2 -.. function:: SubElement(parent, tag, attrib={}, **extra) +.. function:: SubElement(parent, tag, /, attrib={}, **extra) Subelement factory. This function creates an element instance, and appends it to an existing element. @@ -705,6 +705,9 @@ Functions .. versionchanged:: 3.15 *attrib* can now be a :class:`frozendict`. + .. versionchanged:: next + *parent* and *tag* are now positional-only parameters. + .. function:: tostring(element, encoding="us-ascii", method="xml", *, \ xml_declaration=None, default_namespace=None, \ @@ -880,7 +883,7 @@ Element Objects :noindex: :no-index: -.. class:: Element(tag, attrib={}, **extra) +.. class:: Element(tag, /, attrib={}, **extra) Element class. This class defines the Element interface, and provides a reference implementation of this interface. @@ -893,6 +896,9 @@ Element Objects .. versionchanged:: 3.15 *attrib* can now be a :class:`frozendict`. + .. versionchanged:: next + *tag* is now a positional-only parameter. + .. attribute:: tag diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 5b06e422672b1d..b380d0276b0169 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -381,6 +381,19 @@ def test_simpleops(self): self.serialize_check(element, '') + def test_positional_only_parameter(self): + # Test Element positional-only parameters (gh-144846). + + # 'tag' is positional-only + with self.assertRaises(TypeError): + ET.Element(tag='fail') + + # 'tag' and 'attrib' as kwarg/attribute names + e = ET.Element('e', attrib={'attrib': 'foo'}, tag='bar') + self.assertEqual(e.tag, 'e') + self.assertEqual(e.get('attrib'), 'foo') + self.assertEqual(e.get('tag'), 'bar') + def test_cdata(self): # Test CDATA handling (etc). @@ -484,6 +497,28 @@ def test_attrib(self): self.assertEqual(ET.tostring(elem), b'') + def test_subelement_positional_only_parameter(self): + # Test SubElement positional-only parameters (gh-144270). + parent = ET.Element('parent') + + # 'parent' and 'tag' are positional-only + with self.assertRaises(TypeError): + ET.SubElement(parent=parent, tag='fail') + with self.assertRaises(TypeError): + ET.SubElement(parent, tag='fail') + + # 'attrib' can be passed as keyword + sub1 = ET.SubElement(parent, 'sub1', attrib={'key': 'value'}) + self.assertEqual(sub1.get('key'), 'value') + + # 'tag' and 'parent' as kwargs become XML attributes, not func params + sub2 = ET.SubElement(parent, 'sub2', attrib={'attrib': 'foo'}, + tag='bar', parent='baz') + self.assertEqual(sub2.tag, 'sub2') + self.assertEqual(sub2.get('attrib'), 'foo') + self.assertEqual(sub2.get('tag'), 'bar') + self.assertEqual(sub2.get('parent'), 'baz') + def test_makeelement(self): # Test makeelement handling. diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index 57c5b64ea3ba70..85766e02b531ce 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -164,7 +164,7 @@ class Element: """ - def __init__(self, tag, attrib={}, **extra): + def __init__(self, tag, /, attrib={}, **extra): if not isinstance(attrib, (dict, frozendict)): raise TypeError("attrib must be dict or frozendict, not %s" % ( attrib.__class__.__name__,)) @@ -416,7 +416,7 @@ def itertext(self): yield t -def SubElement(parent, tag, attrib={}, **extra): +def SubElement(parent, tag, /, attrib={}, **extra): """Subelement factory which creates an element instance, and appends it to an existing parent. diff --git a/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst b/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst new file mode 100644 index 00000000000000..b8a4374bc2d3ca --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst @@ -0,0 +1,3 @@ +Made the *tag* parameter of :class:`xml.etree.ElementTree.Element` and the +*parent* and *tag* parameters of :func:`xml.etree.ElementTree.SubElement` +positional-only, matching the behavior of the C accelerator.