Commit 2202f877 authored by Christian Heimes's avatar Christian Heimes

Merged revisions...

Merged revisions 60481,60485,60489-60492,60494-60496,60498-60499,60501-60503,60505-60506,60508-60509,60523-60524,60532,60543,60545,60547-60548,60552,60554,60556-60559,60561-60562,60568-60598,60600-60616 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r60568 | christian.heimes | 2008-02-04 19:48:38 +0100 (Mon, 04 Feb 2008) | 1 line

  Increase debugging to investige failing tests on some build bots
........
  r60570 | christian.heimes | 2008-02-04 20:30:05 +0100 (Mon, 04 Feb 2008) | 1 line

  Small adjustments for test compact freelist test. It's no passing on Windows as well.
........
  r60573 | amaury.forgeotdarc | 2008-02-04 21:53:14 +0100 (Mon, 04 Feb 2008) | 2 lines

  Correct quotes in NEWS file
........
  r60575 | amaury.forgeotdarc | 2008-02-04 22:45:05 +0100 (Mon, 04 Feb 2008) | 13 lines

  #1750076: Debugger did not step on every iteration of a while statement.

  The mapping between bytecode offsets and source lines (lnotab) did not contain
  an entry for the beginning of the loop.

  Now it does, and the lnotab can be a bit larger:
  in particular, several statements on the same line generate several entries.
  However, this does not bother the settrace function, which will trigger only
  one 'line' event.

  The lnotab seems to be exactly the same as with python2.4.
........
  r60584 | amaury.forgeotdarc | 2008-02-05 01:26:21 +0100 (Tue, 05 Feb 2008) | 3 lines

  Change r60575 broke test_compile:
  there is no need to emit co_lnotab item when both offsets are zeros.
........
  r60587 | skip.montanaro | 2008-02-05 03:32:16 +0100 (Tue, 05 Feb 2008) | 1 line

  sync with most recent version from python-mode sf project
........
  r60588 | lars.gustaebel | 2008-02-05 12:51:40 +0100 (Tue, 05 Feb 2008) | 5 lines

  Issue #2004: Use mode 0700 for temporary directories and default
  permissions for missing directories.

  (will backport to 2.5)
........
  r60590 | georg.brandl | 2008-02-05 13:01:24 +0100 (Tue, 05 Feb 2008) | 2 lines

  Convert external links to internal links. Fixes #2010.
........
  r60592 | marc-andre.lemburg | 2008-02-05 15:50:40 +0100 (Tue, 05 Feb 2008) | 3 lines

  Keep distutils Python 2.1 compatible (or even Python 2.4 in this case).
........
  r60593 | andrew.kuchling | 2008-02-05 17:06:57 +0100 (Tue, 05 Feb 2008) | 5 lines

  Update PEP URL.
  (This code is duplicated between pydoc and DocXMLRPCServer; maybe it
  should be refactored as a GHOP project.)

  2.5.2 backport candidate.
........
  r60596 | guido.van.rossum | 2008-02-05 18:32:15 +0100 (Tue, 05 Feb 2008) | 2 lines

  In the experimental 'Scanner' feature, the group count was set wrong.
........
  r60602 | facundo.batista | 2008-02-05 20:03:32 +0100 (Tue, 05 Feb 2008) | 3 lines


  Issue 1951. Converts wave test cases to unittest.
........
  r60603 | georg.brandl | 2008-02-05 20:07:10 +0100 (Tue, 05 Feb 2008) | 2 lines

  Actually run the test.
........
  r60604 | skip.montanaro | 2008-02-05 20:24:30 +0100 (Tue, 05 Feb 2008) | 2 lines

  correct object name
........
  r60605 | georg.brandl | 2008-02-05 20:58:17 +0100 (Tue, 05 Feb 2008) | 7 lines

  * Use the same code to profile for test_profile and test_cprofile.
  * Convert both to unittest.
  * Use the same unit testing code.
  * Include the expected output in both test files.
  * Make it possible to regenerate the expected output by running
    the file as a script with an '-r' argument.
........
  r60613 | raymond.hettinger | 2008-02-06 02:49:00 +0100 (Wed, 06 Feb 2008) | 1 line

  Sync-up with Py3k work.
........
  r60614 | christian.heimes | 2008-02-06 13:44:34 +0100 (Wed, 06 Feb 2008) | 1 line

  Limit free list of method and builtin function objects to 256 entries each.
........
  r60616 | christian.heimes | 2008-02-06 14:33:44 +0100 (Wed, 06 Feb 2008) | 7 lines

  Unified naming convention for free lists and their limits. All free lists
  in Object/ are named ``free_list``, the counter ``numfree`` and the upper
  limit is a macro ``PyName_MAXFREELIST`` inside an #ifndef block.

  The chances should make it easier to adjust Python for platforms with
  less memory, e.g. mobile phones.
........
parent 8f2d0061
...@@ -265,7 +265,7 @@ the organizations that use Python. ...@@ -265,7 +265,7 @@ the organizations that use Python.
**What are the restrictions on Python's use?** **What are the restrictions on Python's use?**
They're practically nonexistent. Consult the :file:`Misc/COPYRIGHT` file in the They're practically nonexistent. Consult the :file:`Misc/COPYRIGHT` file in the
source distribution, or http://www.python.org/doc/Copyright.html for the full source distribution, or the section :ref:`history-and-license` for the full
language, but it boils down to three conditions. language, but it boils down to three conditions.
* You have to leave the copyright notice on the software; if you don't include * You have to leave the copyright notice on the software; if you don't include
......
.. _curses-howto:
********************************** **********************************
Curses Programming with Python Curses Programming with Python
********************************** **********************************
......
.. _regex-howto:
**************************** ****************************
Regular Expression HOWTO Regular Expression HOWTO
**************************** ****************************
......
...@@ -276,7 +276,7 @@ Unicode result). The following examples show the differences:: ...@@ -276,7 +276,7 @@ Unicode result). The following examples show the differences::
Encodings are specified as strings containing the encoding's name. Python Encodings are specified as strings containing the encoding's name. Python
comes with roughly 100 different encodings; see the Python Library Reference at comes with roughly 100 different encodings; see the Python Library Reference at
<http://docs.python.org/lib/standard-encodings.html> for a list. Some encodings :ref:`standard-encodings` for a list. Some encodings
have multiple names; for example, 'latin-1', 'iso_8859_1' and '8859' are all have multiple names; for example, 'latin-1', 'iso_8859_1' and '8859' are all
synonyms for the same encoding. synonyms for the same encoding.
......
...@@ -45,9 +45,9 @@ Linux and the BSD variants of Unix. ...@@ -45,9 +45,9 @@ Linux and the BSD variants of Unix.
Convenience function to ensure proper terminal setup and resetting on Convenience function to ensure proper terminal setup and resetting on
application entry and exit. application entry and exit.
`Curses Programming with Python <http://www.python.org/doc/howto/curses/curses.html>`_ :ref:`curses-howto`
Tutorial material on using curses with Python, by Andrew Kuchling and Eric Tutorial material on using curses with Python, by Andrew Kuchling and Eric
Raymond, is available on the Python Web site. Raymond.
The :file:`Demo/curses/` directory in the Python source distribution contains The :file:`Demo/curses/` directory in the Python source distribution contains
some example programs using the curses bindings provided by this module. some example programs using the curses bindings provided by this module.
......
...@@ -65,8 +65,7 @@ and implementation of regular expressions, consult the Friedl book referenced ...@@ -65,8 +65,7 @@ and implementation of regular expressions, consult the Friedl book referenced
above, or almost any textbook about compiler construction. above, or almost any textbook about compiler construction.
A brief explanation of the format of regular expressions follows. For further A brief explanation of the format of regular expressions follows. For further
information and a gentler presentation, consult the Regular Expression HOWTO, information and a gentler presentation, consult the :ref:`regex-howto`.
accessible from http://www.python.org/doc/howto/.
Regular expressions can contain both special and ordinary characters. Most Regular expressions can contain both special and ordinary characters. Most
ordinary characters, like ``'A'``, ``'a'``, or ``'0'``, are the simplest regular ordinary characters, like ``'A'``, ``'a'``, or ``'0'``, are the simplest regular
......
...@@ -30,7 +30,7 @@ class ServerHTMLDoc(pydoc.HTMLDoc): ...@@ -30,7 +30,7 @@ class ServerHTMLDoc(pydoc.HTMLDoc):
results = [] results = []
here = 0 here = 0
# XXX Note that this regular expressions does not allow for the # XXX Note that this regular expression does not allow for the
# hyperlinking of arbitrary strings being used as method # hyperlinking of arbitrary strings being used as method
# names. Only methods with names consisting of word characters # names. Only methods with names consisting of word characters
# and '.'s are hyperlinked. # and '.'s are hyperlinked.
...@@ -52,7 +52,7 @@ class ServerHTMLDoc(pydoc.HTMLDoc): ...@@ -52,7 +52,7 @@ class ServerHTMLDoc(pydoc.HTMLDoc):
url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc) url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
results.append('<a href="%s">%s</a>' % (url, escape(all))) results.append('<a href="%s">%s</a>' % (url, escape(all)))
elif pep: elif pep:
url = 'http://www.python.org/peps/pep-%04d.html' % int(pep) url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
results.append('<a href="%s">%s</a>' % (url, escape(all))) results.append('<a href="%s">%s</a>' % (url, escape(all)))
elif text[end:end+1] == '(': elif text[end:end+1] == '(':
results.append(self.namelink(name, methods, funcs, classes)) results.append(self.namelink(name, methods, funcs, classes))
......
...@@ -385,6 +385,7 @@ class Mapping(metaclass=ABCMeta): ...@@ -385,6 +385,7 @@ class Mapping(metaclass=ABCMeta):
def __ne__(self, other): def __ne__(self, other):
return not (self == other) return not (self == other)
class MappingView(metaclass=ABCMeta): class MappingView(metaclass=ABCMeta):
def __init__(self, mapping): def __init__(self, mapping):
......
...@@ -37,8 +37,12 @@ if os.name == "nt" and "\\pc\\v" in project_base[-10:].lower(): ...@@ -37,8 +37,12 @@ if os.name == "nt" and "\\pc\\v" in project_base[-10:].lower():
# different (hard-wired) directories. # different (hard-wired) directories.
# Setup.local is available for Makefile builds including VPATH builds, # Setup.local is available for Makefile builds including VPATH builds,
# Setup.dist is available on Windows # Setup.dist is available on Windows
python_build = any(os.path.isfile(os.path.join(project_base, "Modules", fn)) def _python_build():
for fn in ("Setup.dist", "Setup.local")) for fn in ("Setup.dist", "Setup.local"):
if os.path.isfile(os.path.join(project_base, "Modules", fn)):
return True
return False
python_build = _python_build()
def get_python_version(): def get_python_version():
"""Return a string containing the major and minor Python version, """Return a string containing the major and minor Python version,
......
...@@ -536,7 +536,7 @@ class HTMLDoc(Doc): ...@@ -536,7 +536,7 @@ class HTMLDoc(Doc):
url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc) url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
results.append('<a href="%s">%s</a>' % (url, escape(all))) results.append('<a href="%s">%s</a>' % (url, escape(all)))
elif pep: elif pep:
url = 'http://www.python.org/peps/pep-%04d' % int(pep) url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
results.append('<a href="%s">%s</a>' % (url, escape(all))) results.append('<a href="%s">%s</a>' % (url, escape(all)))
elif text[end:end+1] == '(': elif text[end:end+1] == '(':
results.append(self.namelink(name, methods, funcs, classes)) results.append(self.namelink(name, methods, funcs, classes))
......
...@@ -294,8 +294,8 @@ class Scanner: ...@@ -294,8 +294,8 @@ class Scanner:
p.append(sre_parse.SubPattern(s, [ p.append(sre_parse.SubPattern(s, [
(SUBPATTERN, (len(p)+1, sre_parse.parse(phrase, flags))), (SUBPATTERN, (len(p)+1, sre_parse.parse(phrase, flags))),
])) ]))
s.groups = len(p)+1
p = sre_parse.SubPattern(s, [(BRANCH, (None, p))]) p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])
s.groups = len(p)
self.scanner = sre_compile.compile(p) self.scanner = sre_compile.compile(p)
def scan(self, string): def scan(self, string):
result = [] result = []
......
...@@ -2005,15 +2005,11 @@ class TarFile(object): ...@@ -2005,15 +2005,11 @@ class TarFile(object):
for tarinfo in members: for tarinfo in members:
if tarinfo.isdir(): if tarinfo.isdir():
# Extract directory with a safe mode, so that # Extract directories with a safe mode.
# all files below can be extracted as well.
try:
os.makedirs(os.path.join(path, tarinfo.name), 0o700)
except EnvironmentError:
pass
directories.append(tarinfo) directories.append(tarinfo)
else: tarinfo = copy.copy(tarinfo)
self.extract(tarinfo, path) tarinfo.mode = 0o700
self.extract(tarinfo, path)
# Reverse sort directories. # Reverse sort directories.
directories.sort(key=lambda a: a.name) directories.sort(key=lambda a: a.name)
...@@ -2118,6 +2114,8 @@ class TarFile(object): ...@@ -2118,6 +2114,8 @@ class TarFile(object):
# Create all upper directories. # Create all upper directories.
upperdirs = os.path.dirname(targetpath) upperdirs = os.path.dirname(targetpath)
if upperdirs and not os.path.exists(upperdirs): if upperdirs and not os.path.exists(upperdirs):
# Create directories that are not part of the archive with
# default permissions.
os.makedirs(upperdirs) os.makedirs(upperdirs)
if tarinfo.islnk() or tarinfo.issym(): if tarinfo.islnk() or tarinfo.issym():
...@@ -2154,7 +2152,9 @@ class TarFile(object): ...@@ -2154,7 +2152,9 @@ class TarFile(object):
"""Make a directory called targetpath. """Make a directory called targetpath.
""" """
try: try:
os.mkdir(targetpath) # Use a safe mode for the directory, the real mode is set
# later in _extract_member().
os.mkdir(targetpath, 0o700)
except EnvironmentError as e: except EnvironmentError as e:
if e.errno != errno.EEXIST: if e.errno != errno.EEXIST:
raise raise
......
test_profile
125 function calls (105 primitive calls) in 1.000 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
4 0.000 0.000 0.000 0.000 :0(append)
4 0.000 0.000 0.000 0.000 :0(exc_info)
1 0.000 0.000 1.000 1.000 :0(exec)
12 0.000 0.000 0.012 0.001 :0(hasattr)
1 0.000 0.000 0.000 0.000 :0(setprofile)
1 0.000 0.000 1.000 1.000 <string>:1(<module>)
2 0.000 0.000 0.000 0.000 io.py:1213(flush)
1 0.000 0.000 0.000 0.000 io.py:269(flush)
1 0.000 0.000 0.000 0.000 io.py:656(closed)
1 0.000 0.000 0.000 0.000 io.py:874(flush)
0 0.000 0.000 profile:0(profiler)
1 0.000 0.000 1.000 1.000 profile:0(testfunc())
8 0.064 0.008 0.080 0.010 test_profile.py:103(subhelper)
28 0.028 0.001 0.028 0.001 test_profile.py:115(__getattr__)
1 0.270 0.270 1.000 1.000 test_profile.py:30(testfunc)
23/3 0.150 0.007 0.170 0.057 test_profile.py:40(factorial)
20 0.020 0.001 0.020 0.001 test_profile.py:53(mul)
2 0.040 0.020 0.600 0.300 test_profile.py:60(helper)
4 0.116 0.029 0.120 0.030 test_profile.py:78(helper1)
2 0.000 0.000 0.140 0.070 test_profile.py:89(helper2_indirect)
8 0.312 0.039 0.400 0.050 test_profile.py:93(helper2)
Ordered by: standard name
Function called...
:0(append) ->
:0(exc_info) ->
:0(exec) -> <string>:1(<module>)(1) 1.000
io.py:1213(flush)(2) 0.000
:0(hasattr) -> test_profile.py:115(__getattr__)(12) 0.028
:0(setprofile) ->
<string>:1(<module>) -> test_profile.py:30(testfunc)(1) 1.000
io.py:1213(flush) -> io.py:269(flush)(1) 0.000
io.py:874(flush)(1) 0.000
io.py:269(flush) ->
io.py:656(closed) ->
io.py:874(flush) -> io.py:656(closed)(1) 0.000
profile:0(profiler) -> profile:0(testfunc())(1) 1.000
profile:0(testfunc()) -> :0(exec)(1) 1.000
:0(setprofile)(1) 0.000
test_profile.py:103(subhelper) -> test_profile.py:115(__getattr__)(16) 0.028
test_profile.py:115(__getattr__) ->
test_profile.py:30(testfunc) -> test_profile.py:40(factorial)(1) 0.170
test_profile.py:60(helper)(2) 0.600
test_profile.py:40(factorial) -> test_profile.py:40(factorial)(20) 0.170
test_profile.py:53(mul)(20) 0.020
test_profile.py:53(mul) ->
test_profile.py:60(helper) -> test_profile.py:78(helper1)(4) 0.120
test_profile.py:89(helper2_indirect)(2) 0.140
test_profile.py:93(helper2)(6) 0.400
test_profile.py:78(helper1) -> :0(append)(4) 0.000
:0(exc_info)(4) 0.000
:0(hasattr)(4) 0.012
test_profile.py:89(helper2_indirect) -> test_profile.py:40(factorial)(2) 0.170
test_profile.py:93(helper2)(2) 0.400
test_profile.py:93(helper2) -> :0(hasattr)(8) 0.012
test_profile.py:103(subhelper)(8) 0.080
Ordered by: standard name
Function was called by...
:0(append) <- test_profile.py:78(helper1)(4) 0.120
:0(exc_info) <- test_profile.py:78(helper1)(4) 0.120
:0(exec) <- profile:0(testfunc())(1) 1.000
:0(hasattr) <- test_profile.py:78(helper1)(4) 0.120
test_profile.py:93(helper2)(8) 0.400
:0(setprofile) <- profile:0(testfunc())(1) 1.000
<string>:1(<module>) <- :0(exec)(1) 1.000
io.py:1213(flush) <- :0(exec)(2) 1.000
io.py:269(flush) <- io.py:1213(flush)(1) 0.000
io.py:656(closed) <- io.py:874(flush)(1) 0.000
io.py:874(flush) <- io.py:1213(flush)(1) 0.000
profile:0(profiler) <-
profile:0(testfunc()) <- profile:0(profiler)(1) 0.000
test_profile.py:103(subhelper) <- test_profile.py:93(helper2)(8) 0.400
test_profile.py:115(__getattr__) <- :0(hasattr)(12) 0.012
test_profile.py:103(subhelper)(16) 0.080
test_profile.py:30(testfunc) <- <string>:1(<module>)(1) 1.000
test_profile.py:40(factorial) <- test_profile.py:30(testfunc)(1) 1.000
test_profile.py:40(factorial)(20) 0.170
test_profile.py:89(helper2_indirect)(2) 0.140
test_profile.py:53(mul) <- test_profile.py:40(factorial)(20) 0.170
test_profile.py:60(helper) <- test_profile.py:30(testfunc)(2) 1.000
test_profile.py:78(helper1) <- test_profile.py:60(helper)(4) 0.600
test_profile.py:89(helper2_indirect) <- test_profile.py:60(helper)(2) 0.600
test_profile.py:93(helper2) <- test_profile.py:60(helper)(6) 0.600
test_profile.py:89(helper2_indirect)(2) 0.140
"""
Input for test_profile.py and test_cprofile.py.
IMPORTANT: This stuff is touchy. If you modify anything above the
test class you'll have to regenerate the stats by running the two
test files.
*ALL* NUMBERS in the expected output are relevant. If you change
the formatting of pstats, please don't just regenerate the expected
output without checking very carefully that not a single number has
changed.
"""
import sys
# In order to have reproducible time, we simulate a timer in the global
# variable 'TICKS', which represents simulated time in milliseconds.
# (We can't use a helper function increment the timer since it would be
# included in the profile and would appear to consume all the time.)
TICKS = 42000
def timer():
return TICKS
def testfunc():
# 1 call
# 1000 ticks total: 270 ticks local, 730 ticks in subfunctions
global TICKS
TICKS += 99
helper() # 300
helper() # 300
TICKS += 171
factorial(14) # 130
def factorial(n):
# 23 calls total
# 170 ticks total, 150 ticks local
# 3 primitive calls, 130, 20 and 20 ticks total
# including 116, 17, 17 ticks local
global TICKS
if n > 0:
TICKS += n
return mul(n, factorial(n-1))
else:
TICKS += 11
return 1
def mul(a, b):
# 20 calls
# 1 tick, local
global TICKS
TICKS += 1
return a * b
def helper():
# 2 calls
# 300 ticks total: 20 ticks local, 260 ticks in subfunctions
global TICKS
TICKS += 1
helper1() # 30
TICKS += 2
helper1() # 30
TICKS += 6
helper2() # 50
TICKS += 3
helper2() # 50
TICKS += 2
helper2() # 50
TICKS += 5
helper2_indirect() # 70
TICKS += 1
def helper1():
# 4 calls
# 30 ticks total: 29 ticks local, 1 tick in subfunctions
global TICKS
TICKS += 10
hasattr(C(), "foo") # 1
TICKS += 19
lst = []
lst.append(42) # 0
sys.exc_info() # 0
def helper2_indirect():
helper2() # 50
factorial(3) # 20
def helper2():
# 8 calls
# 50 ticks local: 39 ticks local, 11 ticks in subfunctions
global TICKS
TICKS += 11
hasattr(C(), "bar") # 1
TICKS += 13
subhelper() # 10
TICKS += 15
def subhelper():
# 8 calls
# 10 ticks total: 8 ticks local, 2 ticks in subfunctions
global TICKS
TICKS += 2
for i in range(2): # 0
try:
C().foo # 1 x 2
except AttributeError:
TICKS += 3 # 3 x 2
class C:
def __getattr__(self, name):
# 28 calls
# 1 tick, local
global TICKS
TICKS += 1
raise AttributeError
...@@ -117,11 +117,11 @@ b"""<dl><dt><a name="-&lt;lambda&gt;"><strong>&lt;lambda&gt;</strong></a>(x, y)< ...@@ -117,11 +117,11 @@ b"""<dl><dt><a name="-&lt;lambda&gt;"><strong>&lt;lambda&gt;</strong></a>(x, y)<
The documentation for the "add" method contains the test material. The documentation for the "add" method contains the test material.
""" """
self.client.request("GET", "/") self.client.request("GET", "/")
response = self.client.getresponse() response = self.client.getresponse().read()
self.assert_( # This is ugly ... how can it be made better? self.assert_( # This is ugly ... how can it be made better?
b"""<dl><dt><a name="-add"><strong>add</strong></a>(x, y)</dt><dd><tt>Add&nbsp;two&nbsp;instances&nbsp;together.&nbsp;This&nbsp;follows&nbsp;<a href="http://www.python.org/peps/pep-0008.html">PEP008</a>,&nbsp;but&nbsp;has&nbsp;nothing<br>\nto&nbsp;do&nbsp;with&nbsp;<a href="http://www.rfc-editor.org/rfc/rfc1952.txt">RFC1952</a>.&nbsp;Case&nbsp;should&nbsp;matter:&nbsp;pEp008&nbsp;and&nbsp;rFC1952.&nbsp;&nbsp;Things<br>\nthat&nbsp;start&nbsp;with&nbsp;http&nbsp;and&nbsp;ftp&nbsp;should&nbsp;be&nbsp;auto-linked,&nbsp;too:<br>\n<a href="http://google.com">http://google.com</a>.</tt></dd></dl>""" b"""<dl><dt><a name="-add"><strong>add</strong></a>(x, y)</dt><dd><tt>Add&nbsp;two&nbsp;instances&nbsp;together.&nbsp;This&nbsp;follows&nbsp;<a href="http://www.python.org/dev/peps/pep-0008/">PEP008</a>,&nbsp;but&nbsp;has&nbsp;nothing<br>\nto&nbsp;do&nbsp;with&nbsp;<a href="http://www.rfc-editor.org/rfc/rfc1952.txt">RFC1952</a>.&nbsp;Case&nbsp;should&nbsp;matter:&nbsp;pEp008&nbsp;and&nbsp;rFC1952.&nbsp;&nbsp;Things<br>\nthat&nbsp;start&nbsp;with&nbsp;http&nbsp;and&nbsp;ftp&nbsp;should&nbsp;be&nbsp;auto-linked,&nbsp;too:<br>\n<a href="http://google.com">http://google.com</a>.</tt></dd></dl>"""
in response.read()) in response, response)
def test_system_methods(self): def test_system_methods(self):
"""Test the precense of three consecutive system.* methods. """Test the precense of three consecutive system.* methods.
......
This diff is collapsed.
...@@ -339,11 +339,14 @@ class SysModuleTest(unittest.TestCase): ...@@ -339,11 +339,14 @@ class SysModuleTest(unittest.TestCase):
# freed blocks shouldn't change # freed blocks shouldn't change
self.assertEqual(r[0][2], 0) self.assertEqual(r[0][2], 0)
# fill freelists # fill freelists
floats = [float(i) for i in range(12000)] ints = list(range(10000))
floats = [float(i) for i in ints]
del ints
del floats del floats
# should free more than 200 blocks # should free more than 100 blocks
r = sys._compact_freelists() r = sys._compact_freelists()
self.assert_(r[0][2] > 200, r[0][2]) self.assert_(r[0][1] > 100, r[0][1])
self.assert_(r[0][2] > 100, r[0][2])
def test_main(): def test_main():
test.test_support.run_unittest(SysModuleTest) test.test_support.run_unittest(SysModuleTest)
......
...@@ -252,14 +252,16 @@ class TraceTestCase(unittest.TestCase): ...@@ -252,14 +252,16 @@ class TraceTestCase(unittest.TestCase):
"\n".join(difflib.ndiff([str(x) for x in expected_events], "\n".join(difflib.ndiff([str(x) for x in expected_events],
[str(x) for x in events]))) [str(x) for x in events])))
def run_and_compare(self, func, events):
def run_test(self, func):
tracer = Tracer() tracer = Tracer()
sys.settrace(tracer.trace) sys.settrace(tracer.trace)
func() func()
sys.settrace(None) sys.settrace(None)
self.compare_events(func.__code__.co_firstlineno, self.compare_events(func.__code__.co_firstlineno,
tracer.events, func.events) tracer.events, events)
def run_test(self, func):
self.run_and_compare(func, func.events)
def run_test2(self, func): def run_test2(self, func):
tracer = Tracer() tracer = Tracer()
...@@ -321,6 +323,59 @@ class TraceTestCase(unittest.TestCase): ...@@ -321,6 +323,59 @@ class TraceTestCase(unittest.TestCase):
self.compare_events(generator_example.__code__.co_firstlineno, self.compare_events(generator_example.__code__.co_firstlineno,
tracer.events, generator_example.events) tracer.events, generator_example.events)
def test_14_onliner_if(self):
def onliners():
if True: False
else: True
return 0
self.run_and_compare(
onliners,
[(0, 'call'),
(1, 'line'),
(3, 'line'),
(3, 'return')])
def test_15_loops(self):
# issue1750076: "while" expression is skipped by debugger
def for_example():
for x in range(2):
pass
self.run_and_compare(
for_example,
[(0, 'call'),
(1, 'line'),
(2, 'line'),
(1, 'line'),
(2, 'line'),
(1, 'line'),
(1, 'return')])
def while_example():
# While expression should be traced on every loop
x = 2
while x > 0:
x -= 1
self.run_and_compare(
while_example,
[(0, 'call'),
(2, 'line'),
(3, 'line'),
(4, 'line'),
(3, 'line'),
(4, 'line'),
(3, 'line'),
(3, 'return')])
def test_16_blank_lines(self):
namespace = {}
exec("def f():\n" + "\n" * 256 + " pass", namespace)
self.run_and_compare(
namespace["f"],
[(0, 'call'),
(257, 'line'),
(257, 'return')])
class RaisingTraceFuncTestCase(unittest.TestCase): class RaisingTraceFuncTestCase(unittest.TestCase):
def trace(self, frame, event, arg): def trace(self, frame, event, arg):
"""A trace function that raises an exception in response to a """A trace function that raises an exception in response to a
......
from test.test_support import TestFailed, TESTFN from test.test_support import TESTFN, run_unittest
import os import os
import wave import wave
import unittest
def check(t, msg=None):
if not t:
raise TestFailed(msg)
nchannels = 2 nchannels = 2
sampwidth = 2 sampwidth = 2
framerate = 8000 framerate = 8000
nframes = 100 nframes = 100
f = wave.open(TESTFN, 'wb') class TestWave(unittest.TestCase):
f.setnchannels(nchannels)
f.setsampwidth(sampwidth) def setUp(self):
f.setframerate(framerate) self.f = None
f.setnframes(nframes)
output = b'\0' * nframes * nchannels * sampwidth def tearDown(self):
f.writeframes(output) if self.f is not None:
f.close() self.f.close()
try:
f = wave.open(TESTFN, 'rb') os.remove(TESTFN)
check(nchannels == f.getnchannels(), "nchannels") except OSError:
check(sampwidth == f.getsampwidth(), "sampwidth") pass
check(framerate == f.getframerate(), "framerate")
check(nframes == f.getnframes(), "nframes") def test_it(self):
input = f.readframes(nframes) self.f = wave.open(TESTFN, 'wb')
check(input == output, "data") self.f.setnchannels(nchannels)
f.close() self.f.setsampwidth(sampwidth)
self.f.setframerate(framerate)
os.remove(TESTFN) self.f.setnframes(nframes)
output = b'\0' * nframes * nchannels * sampwidth
self.f.writeframes(output)
self.f.close()
self.f = wave.open(TESTFN, 'rb')
self.assertEqual(nchannels, self.f.getnchannels())
self.assertEqual(sampwidth, self.f.getsampwidth())
self.assertEqual(framerate, self.f.getframerate())
self.assertEqual(nframes, self.f.getnframes())
self.assertEqual(self.f.readframes(nframes), output)
def test_main():
run_unittest(TestWave)
if __name__ == '__main__':
test_main()
This diff is collapsed.
...@@ -5,6 +5,15 @@ ...@@ -5,6 +5,15 @@
#define TP_DESCR_GET(t) ((t)->tp_descr_get) #define TP_DESCR_GET(t) ((t)->tp_descr_get)
/* Free list for method objects to safe malloc/free overhead
* The im_self element is used to chain the elements.
*/
static PyMethodObject *free_list;
static int numfree = 0;
#ifndef PyMethod_MAXFREELIST
#define PyMethod_MAXFREELIST 256
#endif
PyObject * PyObject *
PyMethod_Function(PyObject *im) PyMethod_Function(PyObject *im)
{ {
...@@ -30,8 +39,6 @@ PyMethod_Self(PyObject *im) ...@@ -30,8 +39,6 @@ PyMethod_Self(PyObject *im)
function. function.
*/ */
static PyMethodObject *free_list;
PyObject * PyObject *
PyMethod_New(PyObject *func, PyObject *self) PyMethod_New(PyObject *func, PyObject *self)
{ {
...@@ -48,6 +55,7 @@ PyMethod_New(PyObject *func, PyObject *self) ...@@ -48,6 +55,7 @@ PyMethod_New(PyObject *func, PyObject *self)
if (im != NULL) { if (im != NULL) {
free_list = (PyMethodObject *)(im->im_self); free_list = (PyMethodObject *)(im->im_self);
PyObject_INIT(im, &PyMethod_Type); PyObject_INIT(im, &PyMethod_Type);
numfree--;
} }
else { else {
im = PyObject_GC_New(PyMethodObject, &PyMethod_Type); im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
...@@ -165,8 +173,14 @@ method_dealloc(register PyMethodObject *im) ...@@ -165,8 +173,14 @@ method_dealloc(register PyMethodObject *im)
PyObject_ClearWeakRefs((PyObject *)im); PyObject_ClearWeakRefs((PyObject *)im);
Py_DECREF(im->im_func); Py_DECREF(im->im_func);
Py_XDECREF(im->im_self); Py_XDECREF(im->im_self);
im->im_self = (PyObject *)free_list; if (numfree < PyMethod_MAXFREELIST) {
free_list = im; im->im_self = (PyObject *)free_list;
free_list = im;
numfree++;
}
else {
PyObject_GC_Del(im);
}
} }
static PyObject * static PyObject *
...@@ -375,7 +389,9 @@ PyMethod_Fini(void) ...@@ -375,7 +389,9 @@ PyMethod_Fini(void)
PyMethodObject *im = free_list; PyMethodObject *im = free_list;
free_list = (PyMethodObject *)(im->im_self); free_list = (PyMethodObject *)(im->im_self);
PyObject_GC_Del(im); PyObject_GC_Del(im);
numfree--;
} }
assert(numfree == 0);
} }
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
......
...@@ -184,9 +184,11 @@ show_counts(void) ...@@ -184,9 +184,11 @@ show_counts(void)
} while(0) } while(0)
/* Dictionary reuse scheme to save calls to malloc, free, and memset */ /* Dictionary reuse scheme to save calls to malloc, free, and memset */
#define MAXFREEDICTS 80 #ifndef PyDict_MAXFREELIST
static PyDictObject *free_dicts[MAXFREEDICTS]; #define PyDict_MAXFREELIST 80
static int num_free_dicts = 0; #endif
static PyDictObject *free_list[PyDict_MAXFREELIST];
static int numfree = 0;
PyObject * PyObject *
PyDict_New(void) PyDict_New(void)
...@@ -200,8 +202,8 @@ PyDict_New(void) ...@@ -200,8 +202,8 @@ PyDict_New(void)
Py_AtExit(show_counts); Py_AtExit(show_counts);
#endif #endif
} }
if (num_free_dicts) { if (numfree) {
mp = free_dicts[--num_free_dicts]; mp = free_list[--numfree];
assert (mp != NULL); assert (mp != NULL);
assert (Py_TYPE(mp) == &PyDict_Type); assert (Py_TYPE(mp) == &PyDict_Type);
_Py_NewReference((PyObject *)mp); _Py_NewReference((PyObject *)mp);
...@@ -897,8 +899,8 @@ dict_dealloc(register PyDictObject *mp) ...@@ -897,8 +899,8 @@ dict_dealloc(register PyDictObject *mp)
} }
if (mp->ma_table != mp->ma_smalltable) if (mp->ma_table != mp->ma_smalltable)
PyMem_DEL(mp->ma_table); PyMem_DEL(mp->ma_table);
if (num_free_dicts < MAXFREEDICTS && Py_TYPE(mp) == &PyDict_Type) if (numfree < PyDict_MAXFREELIST && Py_TYPE(mp) == &PyDict_Type)
free_dicts[num_free_dicts++] = mp; free_list[numfree++] = mp;
else else
Py_TYPE(mp)->tp_free((PyObject *)mp); Py_TYPE(mp)->tp_free((PyObject *)mp);
Py_TRASHCAN_SAFE_END(mp) Py_TRASHCAN_SAFE_END(mp)
......
...@@ -401,14 +401,15 @@ static PyGetSetDef frame_getsetlist[] = { ...@@ -401,14 +401,15 @@ static PyGetSetDef frame_getsetlist[] = {
call depth of more than 20 or 30 is probably already exceptional call depth of more than 20 or 30 is probably already exceptional
unless the program contains run-away recursion. I hope. unless the program contains run-away recursion. I hope.
Later, MAXFREELIST was added to bound the # of frames saved on Later, PyFrame_MAXFREELIST was added to bound the # of frames saved on
free_list. Else programs creating lots of cyclic trash involving free_list. Else programs creating lots of cyclic trash involving
frames could provoke free_list into growing without bound. frames could provoke free_list into growing without bound.
*/ */
static PyFrameObject *free_list = NULL; static PyFrameObject *free_list = NULL;
static int numfree = 0; /* number of frames currently in free_list */ static int numfree = 0; /* number of frames currently in free_list */
#define MAXFREELIST 200 /* max value for numfree */ /* max value for numfree */
#define PyFrame_MAXFREELIST 200
static void static void
frame_dealloc(PyFrameObject *f) frame_dealloc(PyFrameObject *f)
...@@ -441,7 +442,7 @@ frame_dealloc(PyFrameObject *f) ...@@ -441,7 +442,7 @@ frame_dealloc(PyFrameObject *f)
co = f->f_code; co = f->f_code;
if (co->co_zombieframe == NULL) if (co->co_zombieframe == NULL)
co->co_zombieframe = f; co->co_zombieframe = f;
else if (numfree < MAXFREELIST) { else if (numfree < PyFrame_MAXFREELIST) {
++numfree; ++numfree;
f->f_back = free_list; f->f_back = free_list;
free_list = f; free_list = f;
......
...@@ -64,18 +64,20 @@ list_resize(PyListObject *self, Py_ssize_t newsize) ...@@ -64,18 +64,20 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
} }
/* Empty list reuse scheme to save calls to malloc and free */ /* Empty list reuse scheme to save calls to malloc and free */
#define MAXFREELISTS 80 #ifndef PyList_MAXFREELIST
static PyListObject *free_lists[MAXFREELISTS]; #define PyList_MAXFREELIST 80
static int num_free_lists = 0; #endif
static PyListObject *free_list[PyList_MAXFREELIST];
static int numfree = 0;
void void
PyList_Fini(void) PyList_Fini(void)
{ {
PyListObject *op; PyListObject *op;
while (num_free_lists) { while (numfree) {
num_free_lists--; numfree--;
op = free_lists[num_free_lists]; op = free_list[numfree];
assert(PyList_CheckExact(op)); assert(PyList_CheckExact(op));
PyObject_GC_Del(op); PyObject_GC_Del(op);
} }
...@@ -95,9 +97,9 @@ PyList_New(Py_ssize_t size) ...@@ -95,9 +97,9 @@ PyList_New(Py_ssize_t size)
/* Check for overflow */ /* Check for overflow */
if (nbytes / sizeof(PyObject *) != (size_t)size) if (nbytes / sizeof(PyObject *) != (size_t)size)
return PyErr_NoMemory(); return PyErr_NoMemory();
if (num_free_lists) { if (numfree) {
num_free_lists--; numfree--;
op = free_lists[num_free_lists]; op = free_list[numfree];
_Py_NewReference((PyObject *)op); _Py_NewReference((PyObject *)op);
} else { } else {
op = PyObject_GC_New(PyListObject, &PyList_Type); op = PyObject_GC_New(PyListObject, &PyList_Type);
...@@ -265,8 +267,8 @@ list_dealloc(PyListObject *op) ...@@ -265,8 +267,8 @@ list_dealloc(PyListObject *op)
} }
PyMem_FREE(op->ob_item); PyMem_FREE(op->ob_item);
} }
if (num_free_lists < MAXFREELISTS && PyList_CheckExact(op)) if (numfree < PyList_MAXFREELIST && PyList_CheckExact(op))
free_lists[num_free_lists++] = op; free_list[numfree++] = op;
else else
Py_TYPE(op)->tp_free((PyObject *)op); Py_TYPE(op)->tp_free((PyObject *)op);
Py_TRASHCAN_SAFE_END(op) Py_TRASHCAN_SAFE_END(op)
......
...@@ -4,7 +4,14 @@ ...@@ -4,7 +4,14 @@
#include "Python.h" #include "Python.h"
#include "structmember.h" #include "structmember.h"
/* Free list for method objects to safe malloc/free overhead
* The m_self element is used to chain the objects.
*/
static PyCFunctionObject *free_list = NULL; static PyCFunctionObject *free_list = NULL;
static int numfree = 0;
#ifndef PyCFunction_MAXFREELIST
#define PyCFunction_MAXFREELIST 256
#endif
PyObject * PyObject *
PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
...@@ -14,6 +21,7 @@ PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) ...@@ -14,6 +21,7 @@ PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
if (op != NULL) { if (op != NULL) {
free_list = (PyCFunctionObject *)(op->m_self); free_list = (PyCFunctionObject *)(op->m_self);
PyObject_INIT(op, &PyCFunction_Type); PyObject_INIT(op, &PyCFunction_Type);
numfree--;
} }
else { else {
op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type); op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
...@@ -116,8 +124,14 @@ meth_dealloc(PyCFunctionObject *m) ...@@ -116,8 +124,14 @@ meth_dealloc(PyCFunctionObject *m)
_PyObject_GC_UNTRACK(m); _PyObject_GC_UNTRACK(m);
Py_XDECREF(m->m_self); Py_XDECREF(m->m_self);
Py_XDECREF(m->m_module); Py_XDECREF(m->m_module);
m->m_self = (PyObject *)free_list; if (numfree < PyCFunction_MAXFREELIST) {
free_list = m; m->m_self = (PyObject *)free_list;
free_list = m;
numfree++;
}
else {
PyObject_GC_Del(m);
}
} }
static PyObject * static PyObject *
...@@ -312,14 +326,16 @@ PyCFunction_Fini(void) ...@@ -312,14 +326,16 @@ PyCFunction_Fini(void)
PyCFunctionObject *v = free_list; PyCFunctionObject *v = free_list;
free_list = (PyCFunctionObject *)(v->m_self); free_list = (PyCFunctionObject *)(v->m_self);
PyObject_GC_Del(v); PyObject_GC_Del(v);
numfree--;
} }
assert(numfree == 0);
} }
/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(), /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
but it's part of the API so we need to keep a function around that but it's part of the API so we need to keep a function around that
existing C extensions can call. existing C extensions can call.
*/ */
#undef PyCFunction_New #undef PyCFunction_New
PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *); PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);
......
...@@ -52,9 +52,11 @@ _PySet_Dummy(void) ...@@ -52,9 +52,11 @@ _PySet_Dummy(void)
} while(0) } while(0)
/* Reuse scheme to save calls to malloc, free, and memset */ /* Reuse scheme to save calls to malloc, free, and memset */
#define MAXFREESETS 80 #ifndef PySet_MAXFREELIST
static PySetObject *free_sets[MAXFREESETS]; #define PySet_MAXFREELIST 80
static int num_free_sets = 0; #endif
static PySetObject *free_list[PySet_MAXFREELIST];
static int numfree = 0;
/* /*
...@@ -561,8 +563,8 @@ set_dealloc(PySetObject *so) ...@@ -561,8 +563,8 @@ set_dealloc(PySetObject *so)
} }
if (so->table != so->smalltable) if (so->table != so->smalltable)
PyMem_DEL(so->table); PyMem_DEL(so->table);
if (num_free_sets < MAXFREESETS && PyAnySet_CheckExact(so)) if (numfree < PySet_MAXFREELIST && PyAnySet_CheckExact(so))
free_sets[num_free_sets++] = so; free_list[numfree++] = so;
else else
Py_TYPE(so)->tp_free(so); Py_TYPE(so)->tp_free(so);
Py_TRASHCAN_SAFE_END(so) Py_TRASHCAN_SAFE_END(so)
...@@ -975,9 +977,9 @@ make_new_set(PyTypeObject *type, PyObject *iterable) ...@@ -975,9 +977,9 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
} }
/* create PySetObject structure */ /* create PySetObject structure */
if (num_free_sets && if (numfree &&
(type == &PySet_Type || type == &PyFrozenSet_Type)) { (type == &PySet_Type || type == &PyFrozenSet_Type)) {
so = free_sets[--num_free_sets]; so = free_list[--numfree];
assert (so != NULL && PyAnySet_CheckExact(so)); assert (so != NULL && PyAnySet_CheckExact(so));
Py_TYPE(so) = type; Py_TYPE(so) = type;
_Py_NewReference((PyObject *)so); _Py_NewReference((PyObject *)so);
...@@ -1045,9 +1047,9 @@ PySet_Fini(void) ...@@ -1045,9 +1047,9 @@ PySet_Fini(void)
{ {
PySetObject *so; PySetObject *so;
while (num_free_sets) { while (numfree) {
num_free_sets--; numfree--;
so = free_sets[num_free_sets]; so = free_list[numfree];
PyObject_GC_Del(so); PyObject_GC_Del(so);
} }
Py_CLEAR(dummy); Py_CLEAR(dummy);
......
...@@ -4,19 +4,19 @@ ...@@ -4,19 +4,19 @@
#include "Python.h" #include "Python.h"
/* Speed optimization to avoid frequent malloc/free of small tuples */ /* Speed optimization to avoid frequent malloc/free of small tuples */
#ifndef MAXSAVESIZE #ifndef PyTuple_MAXSAVESIZE
#define MAXSAVESIZE 20 /* Largest tuple to save on free list */ #define PyTuple_MAXSAVESIZE 20 /* Largest tuple to save on free list */
#endif #endif
#ifndef MAXSAVEDTUPLES #ifndef PyTuple_MAXFREELIST
#define MAXSAVEDTUPLES 2000 /* Maximum number of tuples of each size to save */ #define PyTuple_MAXFREELIST 2000 /* Maximum number of tuples of each size to save */
#endif #endif
#if MAXSAVESIZE > 0 #if PyTuple_MAXSAVESIZE > 0
/* Entries 1 up to MAXSAVESIZE are free lists, entry 0 is the empty /* Entries 1 up to PyTuple_MAXSAVESIZE are free lists, entry 0 is the empty
tuple () of which at most one instance will be allocated. tuple () of which at most one instance will be allocated.
*/ */
static PyTupleObject *free_tuples[MAXSAVESIZE]; static PyTupleObject *free_list[PyTuple_MAXSAVESIZE];
static int num_free_tuples[MAXSAVESIZE]; static int numfree[PyTuple_MAXSAVESIZE];
#endif #endif
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
int fast_tuple_allocs; int fast_tuple_allocs;
...@@ -32,18 +32,18 @@ PyTuple_New(register Py_ssize_t size) ...@@ -32,18 +32,18 @@ PyTuple_New(register Py_ssize_t size)
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return NULL; return NULL;
} }
#if MAXSAVESIZE > 0 #if PyTuple_MAXSAVESIZE > 0
if (size == 0 && free_tuples[0]) { if (size == 0 && free_list[0]) {
op = free_tuples[0]; op = free_list[0];
Py_INCREF(op); Py_INCREF(op);
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
tuple_zero_allocs++; tuple_zero_allocs++;
#endif #endif
return (PyObject *) op; return (PyObject *) op;
} }
if (size < MAXSAVESIZE && (op = free_tuples[size]) != NULL) { if (size < PyTuple_MAXSAVESIZE && (op = free_list[size]) != NULL) {
free_tuples[size] = (PyTupleObject *) op->ob_item[0]; free_list[size] = (PyTupleObject *) op->ob_item[0];
num_free_tuples[size]--; numfree[size]--;
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
fast_tuple_allocs++; fast_tuple_allocs++;
#endif #endif
...@@ -71,10 +71,10 @@ PyTuple_New(register Py_ssize_t size) ...@@ -71,10 +71,10 @@ PyTuple_New(register Py_ssize_t size)
} }
for (i=0; i < size; i++) for (i=0; i < size; i++)
op->ob_item[i] = NULL; op->ob_item[i] = NULL;
#if MAXSAVESIZE > 0 #if PyTuple_MAXSAVESIZE > 0
if (size == 0) { if (size == 0) {
free_tuples[0] = op; free_list[0] = op;
++num_free_tuples[0]; ++numfree[0];
Py_INCREF(op); /* extra INCREF so that this is never freed */ Py_INCREF(op); /* extra INCREF so that this is never freed */
} }
#endif #endif
...@@ -167,14 +167,14 @@ tupledealloc(register PyTupleObject *op) ...@@ -167,14 +167,14 @@ tupledealloc(register PyTupleObject *op)
i = len; i = len;
while (--i >= 0) while (--i >= 0)
Py_XDECREF(op->ob_item[i]); Py_XDECREF(op->ob_item[i]);
#if MAXSAVESIZE > 0 #if PyTuple_MAXSAVESIZE > 0
if (len < MAXSAVESIZE && if (len < PyTuple_MAXSAVESIZE &&
num_free_tuples[len] < MAXSAVEDTUPLES && numfree[len] < PyTuple_MAXFREELIST &&
Py_TYPE(op) == &PyTuple_Type) Py_TYPE(op) == &PyTuple_Type)
{ {
op->ob_item[0] = (PyObject *) free_tuples[len]; op->ob_item[0] = (PyObject *) free_list[len];
num_free_tuples[len]++; numfree[len]++;
free_tuples[len] = op; free_list[len] = op;
goto done; /* return */ goto done; /* return */
} }
#endif #endif
...@@ -756,16 +756,16 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize) ...@@ -756,16 +756,16 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
void void
PyTuple_Fini(void) PyTuple_Fini(void)
{ {
#if MAXSAVESIZE > 0 #if PyTuple_MAXSAVESIZE > 0
int i; int i;
Py_XDECREF(free_tuples[0]); Py_XDECREF(free_list[0]);
free_tuples[0] = NULL; free_list[0] = NULL;
for (i = 1; i < MAXSAVESIZE; i++) { for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {
PyTupleObject *p, *q; PyTupleObject *p, *q;
p = free_tuples[i]; p = free_list[i];
free_tuples[i] = NULL; free_list[i] = NULL;
while (p) { while (p) {
q = p; q = p;
p = (PyTupleObject *)(p->ob_item[0]); p = (PyTupleObject *)(p->ob_item[0]);
......
...@@ -54,7 +54,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ...@@ -54,7 +54,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Limit for the Unicode object free list */ /* Limit for the Unicode object free list */
#define MAX_UNICODE_FREELIST_SIZE 1024 #define PyUnicode_MAXFREELIST 1024
/* Limit for the Unicode object free list stay alive optimization. /* Limit for the Unicode object free list stay alive optimization.
...@@ -62,7 +62,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ...@@ -62,7 +62,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
all objects on the free list having a size less than this all objects on the free list having a size less than this
limit. This reduces malloc() overhead for small Unicode objects. limit. This reduces malloc() overhead for small Unicode objects.
At worst this will result in MAX_UNICODE_FREELIST_SIZE * At worst this will result in PyUnicode_MAXFREELIST *
(sizeof(PyUnicodeObject) + KEEPALIVE_SIZE_LIMIT + (sizeof(PyUnicodeObject) + KEEPALIVE_SIZE_LIMIT +
malloc()-overhead) bytes of unused garbage. malloc()-overhead) bytes of unused garbage.
...@@ -106,8 +106,8 @@ extern "C" { ...@@ -106,8 +106,8 @@ extern "C" {
static PyObject *interned; static PyObject *interned;
/* Free list for Unicode objects */ /* Free list for Unicode objects */
static PyUnicodeObject *unicode_freelist; static PyUnicodeObject *free_list;
static int unicode_freelist_size; static int numfree;
/* The empty Unicode object is shared to improve performance. */ /* The empty Unicode object is shared to improve performance. */
static PyUnicodeObject *unicode_empty; static PyUnicodeObject *unicode_empty;
...@@ -313,10 +313,10 @@ PyUnicodeObject *_PyUnicode_New(Py_ssize_t length) ...@@ -313,10 +313,10 @@ PyUnicodeObject *_PyUnicode_New(Py_ssize_t length)
} }
/* Unicode freelist & memory allocation */ /* Unicode freelist & memory allocation */
if (unicode_freelist) { if (free_list) {
unicode = unicode_freelist; unicode = free_list;
unicode_freelist = *(PyUnicodeObject **)unicode; free_list = *(PyUnicodeObject **)unicode;
unicode_freelist_size--; numfree--;
if (unicode->str) { if (unicode->str) {
/* Keep-Alive optimization: we only upsize the buffer, /* Keep-Alive optimization: we only upsize the buffer,
never downsize it. */ never downsize it. */
...@@ -386,7 +386,7 @@ void unicode_dealloc(register PyUnicodeObject *unicode) ...@@ -386,7 +386,7 @@ void unicode_dealloc(register PyUnicodeObject *unicode)
} }
if (PyUnicode_CheckExact(unicode) && if (PyUnicode_CheckExact(unicode) &&
unicode_freelist_size < MAX_UNICODE_FREELIST_SIZE) { numfree < PyUnicode_MAXFREELIST) {
/* Keep-Alive optimization */ /* Keep-Alive optimization */
if (unicode->length >= KEEPALIVE_SIZE_LIMIT) { if (unicode->length >= KEEPALIVE_SIZE_LIMIT) {
PyMem_DEL(unicode->str); PyMem_DEL(unicode->str);
...@@ -398,9 +398,9 @@ void unicode_dealloc(register PyUnicodeObject *unicode) ...@@ -398,9 +398,9 @@ void unicode_dealloc(register PyUnicodeObject *unicode)
unicode->defenc = NULL; unicode->defenc = NULL;
} }
/* Add to free list */ /* Add to free list */
*(PyUnicodeObject **)unicode = unicode_freelist; *(PyUnicodeObject **)unicode = free_list;
unicode_freelist = unicode; free_list = unicode;
unicode_freelist_size++; numfree++;
} }
else { else {
PyMem_DEL(unicode->str); PyMem_DEL(unicode->str);
...@@ -8033,7 +8033,7 @@ unicode_zfill(PyUnicodeObject *self, PyObject *args) ...@@ -8033,7 +8033,7 @@ unicode_zfill(PyUnicodeObject *self, PyObject *args)
static PyObject* static PyObject*
unicode_freelistsize(PyUnicodeObject *self) unicode_freelistsize(PyUnicodeObject *self)
{ {
return PyLong_FromLong(unicode_freelist_size); return PyLong_FromLong(numfree);
} }
#endif #endif
...@@ -9090,8 +9090,8 @@ void _PyUnicode_Init(void) ...@@ -9090,8 +9090,8 @@ void _PyUnicode_Init(void)
}; };
/* Init the implementation */ /* Init the implementation */
unicode_freelist = NULL; free_list = NULL;
unicode_freelist_size = 0; numfree = 0;
unicode_empty = _PyUnicode_New(0); unicode_empty = _PyUnicode_New(0);
if (!unicode_empty) if (!unicode_empty)
return; return;
...@@ -9127,7 +9127,7 @@ _PyUnicode_Fini(void) ...@@ -9127,7 +9127,7 @@ _PyUnicode_Fini(void)
} }
} }
for (u = unicode_freelist; u != NULL;) { for (u = free_list; u != NULL;) {
PyUnicodeObject *v = u; PyUnicodeObject *v = u;
u = *(PyUnicodeObject **)u; u = *(PyUnicodeObject **)u;
if (v->str) if (v->str)
...@@ -9135,8 +9135,8 @@ _PyUnicode_Fini(void) ...@@ -9135,8 +9135,8 @@ _PyUnicode_Fini(void)
Py_XDECREF(v->defenc); Py_XDECREF(v->defenc);
PyObject_Del(v); PyObject_Del(v);
} }
unicode_freelist = NULL; free_list = NULL;
unicode_freelist_size = 0; numfree = 0;
} }
void void
......
...@@ -652,11 +652,16 @@ compiler_next_instr(struct compiler *c, basicblock *b) ...@@ -652,11 +652,16 @@ compiler_next_instr(struct compiler *c, basicblock *b)
return b->b_iused++; return b->b_iused++;
} }
/* Set the i_lineno member of the instruction at offse off if the /* Set the i_lineno member of the instruction at offset off if the
line number for the current expression/statement (?) has not line number for the current expression/statement has not
already been set. If it has been set, the call has no effect. already been set. If it has been set, the call has no effect.
Every time a new node is b The line number is reset in the following cases:
- when entering a new scope
- on each statement
- on each expression that start a new line
- before the "except" clause
- before the "for" and "while" expressions
*/ */
static void static void
...@@ -1750,9 +1755,8 @@ compiler_for(struct compiler *c, stmt_ty s) ...@@ -1750,9 +1755,8 @@ compiler_for(struct compiler *c, stmt_ty s)
VISIT(c, expr, s->v.For.iter); VISIT(c, expr, s->v.For.iter);
ADDOP(c, GET_ITER); ADDOP(c, GET_ITER);
compiler_use_next_block(c, start); compiler_use_next_block(c, start);
/* XXX(nnorwitz): is there a better way to handle this? /* for expressions must be traced on each iteration,
for loops are special, we want to be able to trace them so we need to set an extra line number. */
each time around, so we need to set an extra line number. */
c->u->u_lineno_set = 0; c->u->u_lineno_set = 0;
ADDOP_JREL(c, FOR_ITER, cleanup); ADDOP_JREL(c, FOR_ITER, cleanup);
VISIT(c, expr, s->v.For.target); VISIT(c, expr, s->v.For.target);
...@@ -1799,6 +1803,9 @@ compiler_while(struct compiler *c, stmt_ty s) ...@@ -1799,6 +1803,9 @@ compiler_while(struct compiler *c, stmt_ty s)
if (!compiler_push_fblock(c, LOOP, loop)) if (!compiler_push_fblock(c, LOOP, loop))
return 0; return 0;
if (constant == -1) { if (constant == -1) {
/* while expressions must be traced on each iteration,
so we need to set an extra line number. */
c->u->u_lineno_set = 0;
VISIT(c, expr, s->v.While.test); VISIT(c, expr, s->v.While.test);
ADDOP_JREL(c, JUMP_IF_FALSE, anchor); ADDOP_JREL(c, JUMP_IF_FALSE, anchor);
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
...@@ -1979,8 +1986,8 @@ compiler_try_except(struct compiler *c, stmt_ty s) ...@@ -1979,8 +1986,8 @@ compiler_try_except(struct compiler *c, stmt_ty s)
s->v.TryExcept.handlers, i); s->v.TryExcept.handlers, i);
if (!handler->type && i < n-1) if (!handler->type && i < n-1)
return compiler_error(c, "default 'except:' must be last"); return compiler_error(c, "default 'except:' must be last");
c->u->u_lineno_set = 0; c->u->u_lineno_set = 0;
c->u->u_lineno = handler->lineno; c->u->u_lineno = handler->lineno;
except = compiler_new_block(c); except = compiler_new_block(c);
if (except == NULL) if (except == NULL)
return 0; return 0;
...@@ -3762,10 +3769,7 @@ assemble_lnotab(struct assembler *a, struct instr *i) ...@@ -3762,10 +3769,7 @@ assemble_lnotab(struct assembler *a, struct instr *i)
assert(d_bytecode >= 0); assert(d_bytecode >= 0);
assert(d_lineno >= 0); assert(d_lineno >= 0);
/* XXX(nnorwitz): is there a better way to handle this? if(d_bytecode == 0 && d_lineno == 0)
for loops are special, we want to be able to trace them
each time around, so we need to set an extra line number. */
if (d_lineno == 0 && i->i_opcode != FOR_ITER)
return 1; return 1;
if (d_bytecode > 255) { if (d_bytecode > 255) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment