python-peps/pep-0611/index.html

475 lines
30 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 611 The one million limit | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0611/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 611 The one million limit | peps.python.org'>
<meta property="og:description" content="This PR proposes a soft limit of one million (1 000 000), and a larger hard limit for various aspects of Python code and its implementation.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0611/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PR proposes a soft limit of one million (1 000 000), and a larger hard limit for various aspects of Python code and its implementation.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 611</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 611 The one million limit</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Mark Shannon &lt;mark&#32;&#97;t&#32;hotpy.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">05-Dec-2019</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a><ul>
<li><a class="reference internal" href="#is-this-a-worthwhile-trade-off">Is this a worthwhile trade off?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#one-million">One million</a></li>
</ul>
</li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#recursion-depth">Recursion depth</a></li>
</ul>
</li>
<li><a class="reference internal" href="#soft-and-hard-limits">Soft and hard limits</a><ul>
<li><a class="reference internal" href="#introspecting-and-modifying-the-limits">Introspecting and modifying the limits</a></li>
<li><a class="reference internal" href="#inferred-limits">Inferred limits</a></li>
<li><a class="reference internal" href="#the-advantages-for-cpython-of-imposing-these-limits">The advantages for CPython of imposing these limits:</a><ul>
<li><a class="reference internal" href="#line-of-code-in-a-module-and-code-object-restrictions">Line of code in a module and code object restrictions.</a></li>
<li><a class="reference internal" href="#total-number-of-classes-in-a-running-interpreter">Total number of classes in a running interpreter</a></li>
</ul>
</li>
<li><a class="reference internal" href="#enforcement">Enforcement</a></li>
</ul>
</li>
<li><a class="reference internal" href="#hard-limits-in-cpython">Hard limits in CPython</a></li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
<li><a class="reference internal" href="#other-implementations">Other implementations</a><ul>
<li><a class="reference internal" href="#general-purpose-implementations">General purpose implementations</a></li>
<li><a class="reference internal" href="#special-purpose-implementations">Special purpose implementations</a></li>
</ul>
</li>
<li><a class="reference internal" href="#security-implications">Security Implications</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PR proposes a soft limit of one million (1 000 000), and a larger hard limit
for various aspects of Python code and its implementation.</p>
<p>The Python language does not specify limits for many of its features.
Not having any limit to these values seems to enhance programmer freedom,
at least superficially, but in practice the CPython VM and other Python virtual
machines have implicit limits or are forced to assume that the limits are
astronomical, which is expensive.</p>
<p>This PR lists a number of features which are to have a limit of one million.</p>
<p>For CPython the hard limit will be eight million (8 000 000).</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>There are many values that need to be represented in a virtual machine.
If no limit is specified for these values,
then the representation must either be inefficient or vulnerable to overflow.
The CPython virtual machine represents values like line numbers,
stack offsets and instruction offsets by 32 bit values. This is inefficient, and potentially unsafe.</p>
<p>It is inefficient as actual values rarely need more than a dozen or so bits to represent them.</p>
<p>It is unsafe as malicious or poorly generated code could cause values to exceed 2<sup>32</sup>.</p>
<p>For example, line numbers are represented by 32 bit values internally.
This is inefficient, given that modules almost never exceed a few thousand lines.
Despite being inefficient, it is still vulnerable to overflow as
it is easy for an attacker to created a module with billions of newline characters.</p>
<p>Memory access is usually a limiting factor in the performance of modern CPUs.
Better packing of data structures enhances locality and reduces memory bandwidth,
at a modest increase in ALU usage (for shifting and masking).
Being able to safely store important values in 20 bits would allow memory savings
in several data structures including, but not limited to:</p>
<ul class="simple">
<li>Frame objects</li>
<li>Object headers</li>
<li>Code objects</li>
</ul>
<p>There is also the potential for a more efficient instruction format, speeding up interpreter dispatch.</p>
<section id="is-this-a-worthwhile-trade-off">
<h3><a class="toc-backref" href="#is-this-a-worthwhile-trade-off" role="doc-backlink">Is this a worthwhile trade off?</a></h3>
<p>The downside of any form of limit is that it might potentially make someones job harder,
for example, it may be harder to write a code generator that keeps the size of modules to one million lines.
However, it is the authors opinion, having written many code generators,
that such a limit is extremely unlikely to be a problem in practice.</p>
<p>The upside of these limits is the freedom it grants implementers of runtimes, whether CPython,
PyPy, or any other implementation, to improve performance.
It is the authors belief, that the potential value of even a 0.1% reduction in the cost
of running Python programs globally will hugely exceed the cost of modifying a handful of code generators.</p>
</section>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>Imposing a limit on values such as lines of code in a module, and the number of local variables,
has significant advantages for ease of implementation and efficiency of virtual machines.
If the limit is sufficiently large, there is no adverse effect on users of the language.</p>
<p>By selecting a fixed but large limit for these values,
it is possible to have both safety and efficiency whilst causing no inconvenience to human programmers
and only very rare problems for code generators.</p>
<section id="one-million">
<h3><a class="toc-backref" href="#one-million" role="doc-backlink">One million</a></h3>
<p>The value “one million” is very easy to remember.</p>
<p>The one million limit is mostly a limit on human generated code, not runtime sizes.</p>
<p>One million lines in a single module is a ridiculous concentration of code;
the entire Python standard library is about 2/3rd of a million lines, spread over 1600 files.</p>
<p>The Java Virtual Machine (JVM) <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a> specifies a limit of 2<sup>16</sup>-1 (65535) for many program
elements similar to those covered here.
This limit enables limited values to fit in 16 bits, which is a very efficient machine representation.
However, this limit is quite easily exceeded in practice by code generators and
the author is aware of existing Python code that already exceeds 2<sup>16</sup> lines of code.</p>
<p>The hard limit of eight million fits into 23 bits which, although not as convenient for machine representation,
is still reasonably compact.
A limit of eight million is small enough for efficiency advantages (only 23 bits),
but large enough not to impact users (no one has ever written a module that large).</p>
<p>While it is possible that generated code could exceed the limit,
it is easy for a code generator to modify its output to conform.
The author has hit the 64K limit in the JVM on at least two occasions when generating Java code.
The workarounds were relatively straightforward and wouldnt
have been necessary with a limit of one million bytecodes or lines of code.</p>
<p>Where necessary, the soft limit can increased for those programs that exceed the one million limit.</p>
<p>Having a soft limit of one million provides a warning of problematic code, without causing an error and forcing an immediate fix.
It also allows dynamic optimizers to use more compact formats without inline checks.</p>
</section>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>This PR proposes that the following language features and runtime values have a soft limit of one million.</p>
<ul class="simple">
<li>The number of source code lines in a module</li>
<li>The number of bytecode instructions in a code object.</li>
<li>The sum of local variables and stack usage for a code object.</li>
<li>The number of classes in a running interpreter.</li>
<li>The recursion depth of Python code.</li>
</ul>
<p>It is likely that memory constraints would be a limiting factor before the number of classes reaches one million.</p>
<section id="recursion-depth">
<h3><a class="toc-backref" href="#recursion-depth" role="doc-backlink">Recursion depth</a></h3>
<p>The recursion depth limit only applies to pure Python code. Code written in a foreign language, such as C,
may consume hardware stack and thus be limited to a recursion depth of a few thousand.
It is expected that implementations will raise an exception should the hardware stack get close to its limit.
For code that mixes Python and C calls, it is most likely that the hardware limit will apply first.
The size of the hardware recursion may vary at runtime and will not be visible.</p>
</section>
</section>
<section id="soft-and-hard-limits">
<h2><a class="toc-backref" href="#soft-and-hard-limits" role="doc-backlink">Soft and hard limits</a></h2>
<p>Implementations should emit a warning whenever a soft limit is exceeded, unless the hard limit has the same value as the soft limit.
When a hard limit is exceeded, then an exception should be raised.</p>
<p>Depending on the implementation, different hard limits might apply. In some cases the hard limit might be below the soft limit.
For example, many micropython ports are unlikely to be able to support such large limits.</p>
<section id="introspecting-and-modifying-the-limits">
<h3><a class="toc-backref" href="#introspecting-and-modifying-the-limits" role="doc-backlink">Introspecting and modifying the limits</a></h3>
<p>One or more functions will be provided in the <code class="docutils literal notranslate"><span class="pre">sys</span></code> module to introspect or modify the soft limits at runtime,
but the limits may not be raised above the hard limit.</p>
</section>
<section id="inferred-limits">
<h3><a class="toc-backref" href="#inferred-limits" role="doc-backlink">Inferred limits</a></h3>
<p>These limits are not part of the specification, but a limit of less than one million
can be inferred from the limit on the number of bytecode instructions in a code object.
Because there would be insufficient instructions to load more than
one million constants or use more than one million names.</p>
<ul class="simple">
<li>The number of distinct names in a code object.</li>
<li>The number of constants in a code object.</li>
</ul>
</section>
<section id="the-advantages-for-cpython-of-imposing-these-limits">
<h3><a class="toc-backref" href="#the-advantages-for-cpython-of-imposing-these-limits" role="doc-backlink">The advantages for CPython of imposing these limits:</a></h3>
<section id="line-of-code-in-a-module-and-code-object-restrictions">
<h4><a class="toc-backref" href="#line-of-code-in-a-module-and-code-object-restrictions" role="doc-backlink">Line of code in a module and code object restrictions.</a></h4>
<p>When compiling source code to bytecode or modifying bytecode for profiling or debugging,
an intermediate form is required. By limiting operands to 23 bits,
instructions can be represented in a compact 64 bit form allowing
very fast passes over the instruction sequence.</p>
<p>Having 23 bit operands (24 bits for relative branches) allows instructions
to fit into 32 bits without needing additional <code class="docutils literal notranslate"><span class="pre">EXTENDED_ARG</span></code> instructions.
This improves dispatch, as the operand is strictly local to the instruction.
It is unclear whether this would help performance, it is merely an example of what is possible.</p>
<p>The benefit of restricting the number of lines in a module is primarily the implied limit on bytecodes.
It is more important for implementations that it is instructions per code object, not lines per module, that is limited to one million,
but it is much easier to explain a one million line limit. Having a consistent limit of one million is just easier to remember.
It is mostly likely, although not guaranteed, that the line limit will be hit first and thus provide a simpler to understand error message to the developer.</p>
</section>
<section id="total-number-of-classes-in-a-running-interpreter">
<h4><a class="toc-backref" href="#total-number-of-classes-in-a-running-interpreter" role="doc-backlink">Total number of classes in a running interpreter</a></h4>
<p>This limit has to the potential to reduce the size of object headers considerably.</p>
<p>Currently objects have a two word header, for objects without references
(int, float, str, etc.) or a four word header for objects with references.
By reducing the maximum number of classes, the space for the class reference
can be reduced from 64 bits to fewer than 32 bits allowing a much more compact header.</p>
<p>For example, a super-compact header format might look like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">struct</span> <span class="n">header</span> <span class="p">{</span>
<span class="n">uint32_t</span> <span class="n">gc_flags</span><span class="p">:</span><span class="mi">6</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Needs</span> <span class="n">finalisation</span><span class="p">,</span> <span class="n">might</span> <span class="n">be</span> <span class="n">part</span> <span class="n">of</span> <span class="n">a</span> <span class="n">cycle</span><span class="p">,</span> <span class="n">etc</span><span class="o">.</span> <span class="o">*/</span>
<span class="n">uint32_t</span> <span class="n">class_id</span><span class="p">:</span><span class="mi">26</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Can</span> <span class="n">be</span> <span class="n">efficiently</span> <span class="n">mapped</span> <span class="n">to</span> <span class="n">address</span> <span class="n">by</span> <span class="n">ensuring</span> <span class="n">suitable</span> <span class="n">alignment</span> <span class="n">of</span> <span class="n">classes</span> <span class="o">*/</span>
<span class="n">uint32_t</span> <span class="n">refcount</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Limited</span> <span class="n">memory</span> <span class="ow">or</span> <span class="n">saturating</span> <span class="o">*/</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This format would reduce the size of a Python object without slots, on a 64 bit machine, from 40 to 16 bytes.</p>
<p>Note that there are two ways to use a 32 bit refcount on a 64 bit machine.
One is to limit each sub-interpreter to 32Gb of memory.
The other is to use a saturating reference count, which would be a little bit slower, but allow unlimited memory allocation.</p>
</section>
</section>
<section id="enforcement">
<h3><a class="toc-backref" href="#enforcement" role="doc-backlink">Enforcement</a></h3>
<p>Python implementations are not obliged to enforce the limits.
However, if a limit can be enforced without hurting performance, then it should be.</p>
<p>It is anticipated that CPython will enforce the limits as follows:</p>
<ul class="simple">
<li>The number of source code lines in a module: version 3.9 onward.</li>
<li>The number of bytecode instructions in a code object: 3.9 onward.</li>
<li>The sum of local variables and stack usage for a code object: 3.9 onward.</li>
<li>The number of classes in a running interpreter: probably 3.10 onward, maybe warning in 3.9.</li>
</ul>
</section>
</section>
<section id="hard-limits-in-cpython">
<h2><a class="toc-backref" href="#hard-limits-in-cpython" role="doc-backlink">Hard limits in CPython</a></h2>
<p>CPython will enforce a hard limit on all the above values. The value of the hard limit will be 8 million.</p>
<p>It is hypothetically possible that some machine generated code exceeds one or more of the above limits.
The author believes that to be incredibly unlikely and easily fixed by modifying the output stage of the code generator.</p>
<p>We would like to gain the benefit from the above limits for performance as soon as possible.
To that end, CPython will start applying limits from version 3.9 onward.
To ease the transition and minimize breakage, the initial limits will be 16 million, reducing to 8 million in a later version.</p>
</section>
<section id="backwards-compatibility">
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2>
<p>The actual hard limits enforced by CPython will be:</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Version</th>
<th class="head">Hard limit</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>3.9</td>
<td>16 million</td>
</tr>
<tr class="row-odd"><td>3.10 onward</td>
<td>8 million</td>
</tr>
</tbody>
</table>
<p>Given the rarity of code generators that would exceed the one million limits,
and the environments in which they are typically used, it seems reasonable
to start issuing warnings in 3.9 if any limited quantity exceeds one million.</p>
<p>Historically the recursion limit has been set at 1000. To avoid breaking code that implicitly relies on the value being small,
the soft recursion limit will be increased gradually, as follows:</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Version</th>
<th class="head">Soft limit</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>3.9</td>
<td>4 000</td>
</tr>
<tr class="row-odd"><td>3.10</td>
<td>16 000</td>
</tr>
<tr class="row-even"><td>3.11</td>
<td>64 000</td>
</tr>
<tr class="row-odd"><td>3.12</td>
<td>125 000</td>
</tr>
<tr class="row-even"><td>3.13</td>
<td>1 million</td>
</tr>
</tbody>
</table>
<p>The hard limit will be set to 8 million immediately.</p>
</section>
<section id="other-implementations">
<h2><a class="toc-backref" href="#other-implementations" role="doc-backlink">Other implementations</a></h2>
<p>Implementations of Python other than CPython have different purposes, so different limits might be appropriate.
This is acceptable, provided the limits are clearly documented.</p>
<section id="general-purpose-implementations">
<h3><a class="toc-backref" href="#general-purpose-implementations" role="doc-backlink">General purpose implementations</a></h3>
<p>General purpose implementations, such as PyPy, should use the one million limit.
If maximum compatibility is a goal, then they should also follow CPythons behaviour for 3.9 to 3.11.</p>
</section>
<section id="special-purpose-implementations">
<h3><a class="toc-backref" href="#special-purpose-implementations" role="doc-backlink">Special purpose implementations</a></h3>
<p>Special purpose implementations may use lower limits, as long as they are clearly documented.
An implementation designed for embedded systems, for example MicroPython, might impose limits as low as a few thousand.</p>
</section>
</section>
<section id="security-implications">
<h2><a class="toc-backref" href="#security-implications" role="doc-backlink">Security Implications</a></h2>
<p>Minimal. This reduces the attack surface of any Python virtual machine by a small amount.</p>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>None, as yet. This will be implemented in CPython, once the PEP has been accepted.</p>
</section>
<section id="rejected-ideas">
<h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2>
<p>Being able to modify the hard limits upwards at compile time was suggested by Tal Einat.
This is rejected as the current limits of 2<sup>32</sup> have not been an issue, and the practical
advantages of allowing limits between 2<sup>20</sup> and 2<sup>32</sup> seem slight compared to the additional
code complexity of supporting such a feature.</p>
</section>
<section id="open-issues">
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
<p>None, as yet.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd>The Java Virtual Machine specification</aside>
</aside>
<p><a class="reference external" href="https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf">https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf</a></p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0611.rst">https://github.com/python/peps/blob/main/peps/pep-0611.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0611.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a><ul>
<li><a class="reference internal" href="#is-this-a-worthwhile-trade-off">Is this a worthwhile trade off?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#one-million">One million</a></li>
</ul>
</li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#recursion-depth">Recursion depth</a></li>
</ul>
</li>
<li><a class="reference internal" href="#soft-and-hard-limits">Soft and hard limits</a><ul>
<li><a class="reference internal" href="#introspecting-and-modifying-the-limits">Introspecting and modifying the limits</a></li>
<li><a class="reference internal" href="#inferred-limits">Inferred limits</a></li>
<li><a class="reference internal" href="#the-advantages-for-cpython-of-imposing-these-limits">The advantages for CPython of imposing these limits:</a><ul>
<li><a class="reference internal" href="#line-of-code-in-a-module-and-code-object-restrictions">Line of code in a module and code object restrictions.</a></li>
<li><a class="reference internal" href="#total-number-of-classes-in-a-running-interpreter">Total number of classes in a running interpreter</a></li>
</ul>
</li>
<li><a class="reference internal" href="#enforcement">Enforcement</a></li>
</ul>
</li>
<li><a class="reference internal" href="#hard-limits-in-cpython">Hard limits in CPython</a></li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
<li><a class="reference internal" href="#other-implementations">Other implementations</a><ul>
<li><a class="reference internal" href="#general-purpose-implementations">General purpose implementations</a></li>
<li><a class="reference internal" href="#special-purpose-implementations">Special purpose implementations</a></li>
</ul>
</li>
<li><a class="reference internal" href="#security-implications">Security Implications</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0611.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>