Skip to content

Commit

Permalink
Merge branch 'main' into faster-uops
Browse files Browse the repository at this point in the history
  • Loading branch information
gvanrossum committed Nov 20, 2023
2 parents 0fae4e6 + 1995955 commit 9ea707b
Show file tree
Hide file tree
Showing 77 changed files with 1,835 additions and 769 deletions.
4 changes: 2 additions & 2 deletions Doc/library/profile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ the following::

The first line indicates that 214 calls were monitored. Of those calls, 207
were :dfn:`primitive`, meaning that the call was not induced via recursion. The
next line: ``Ordered by: cumulative time``, indicates that the text string in the
far right column was used to sort the output. The column headings include:
next line: ``Ordered by: cumulative time`` indicates the output is sorted
by the ``cumtime`` values. The column headings include:

ncalls
for the number of calls.
Expand Down
3 changes: 1 addition & 2 deletions Doc/tutorial/errors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,7 @@ The :keyword:`try` statement works as follows.

* If an exception occurs which does not match the exception named in the *except
clause*, it is passed on to outer :keyword:`try` statements; if no handler is
found, it is an *unhandled exception* and execution stops with a message as
shown above.
found, it is an *unhandled exception* and execution stops with an error message.

A :keyword:`try` statement may have more than one *except clause*, to specify
handlers for different exceptions. At most one handler will be executed.
Expand Down
5 changes: 5 additions & 0 deletions Grammar/python.gram
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ simple_stmt[stmt_ty] (memo):
| &'nonlocal' nonlocal_stmt

compound_stmt[stmt_ty]:
| invalid_compound_stmt
| &('def' | '@' | 'async') function_def
| &'if' if_stmt
| &('class' | '@') class_def
Expand Down Expand Up @@ -1298,6 +1299,10 @@ invalid_import_from_targets:
| import_from_as_names ',' NEWLINE {
RAISE_SYNTAX_ERROR("trailing comma not allowed without surrounding parentheses") }

invalid_compound_stmt:
| a='elif' named_expression ':' { RAISE_SYNTAX_ERROR_STARTING_FROM(a, "'elif' must match an if-statement here") }
| a='else' ':' { RAISE_SYNTAX_ERROR_STARTING_FROM(a, "'else' must match a valid statement here") }

invalid_with_stmt:
| ['async'] 'with' ','.(expression ['as' star_target])+ NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
| ['async'] 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
Expand Down
2 changes: 1 addition & 1 deletion Include/cpython/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ struct _ts {

/* Tagged pointer to top-most critical section, or zero if there is no
* active critical section. Critical sections are only used in
* `--disable-gil` builds (i.e., when Py_NOGIL is defined to 1). In the
* `--disable-gil` builds (i.e., when Py_GIL_DISABLED is defined to 1). In the
* default build, this field is always zero.
*/
uintptr_t critical_section;
Expand Down
6 changes: 3 additions & 3 deletions Include/internal/pycore_critical_section.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ extern "C" {
#define _Py_CRITICAL_SECTION_TWO_MUTEXES 0x2
#define _Py_CRITICAL_SECTION_MASK 0x3

#ifdef Py_NOGIL
#ifdef Py_GIL_DISABLED
# define Py_BEGIN_CRITICAL_SECTION(op) \
{ \
_PyCriticalSection _cs; \
Expand All @@ -104,13 +104,13 @@ extern "C" {
# define Py_END_CRITICAL_SECTION2() \
_PyCriticalSection2_End(&_cs2); \
}
#else /* !Py_NOGIL */
#else /* !Py_GIL_DISABLED */
// The critical section APIs are no-ops with the GIL.
# define Py_BEGIN_CRITICAL_SECTION(op)
# define Py_END_CRITICAL_SECTION()
# define Py_BEGIN_CRITICAL_SECTION2(a, b)
# define Py_END_CRITICAL_SECTION2()
#endif /* !Py_NOGIL */
#endif /* !Py_GIL_DISABLED */

typedef struct {
// Tagged pointer to an outer active critical section (or 0).
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_importdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ typedef FARPROC dl_funcptr;
# define PYD_DEBUG_SUFFIX ""
#endif

#ifdef Py_NOGIL
#ifdef Py_GIL_DISABLED
# define PYD_THREADING_TAG "t"
#else
# define PYD_THREADING_TAG ""
Expand Down
6 changes: 3 additions & 3 deletions Include/internal/pycore_lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ extern "C" {
// ...
// PyMutex_Unlock(&m);

// NOTE: In Py_NOGIL builds, `struct _PyMutex` is defined in Include/object.h.
// The Py_NOGIL builds need the definition in Include/object.h for the
// NOTE: In Py_GIL_DISABLED builds, `struct _PyMutex` is defined in Include/object.h.
// The Py_GIL_DISABLED builds need the definition in Include/object.h for the
// `ob_mutex` field in PyObject. For the default (non-free-threaded) build,
// we define the struct here to avoid exposing it in the public API.
#ifndef Py_NOGIL
#ifndef Py_GIL_DISABLED
struct _PyMutex { uint8_t v; };
#endif

Expand Down
14 changes: 7 additions & 7 deletions Include/internal/pycore_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ PyAPI_FUNC(int) _PyObject_IsFreed(PyObject *);
Furthermore, we can't use designated initializers in Extensions since these
are not supported pre-C++20. Thus, keeping an internal copy here is the most
backwards compatible solution */
#if defined(Py_NOGIL)
#if defined(Py_GIL_DISABLED)
#define _PyObject_HEAD_INIT(type) \
{ \
.ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL, \
Expand Down Expand Up @@ -103,7 +103,7 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
#ifdef Py_REF_DEBUG
_Py_AddRefTotal(_PyInterpreterState_GET(), n);
#endif
#if !defined(Py_NOGIL)
#if !defined(Py_GIL_DISABLED)
op->ob_refcnt += n;
#else
if (_Py_IsOwnedByCurrentThread(op)) {
Expand All @@ -128,7 +128,7 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
static inline void _Py_SetImmortal(PyObject *op)
{
if (op) {
#ifdef Py_NOGIL
#ifdef Py_GIL_DISABLED
op->ob_tid = _Py_UNOWNED_TID;
op->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL;
op->ob_ref_shared = 0;
Expand All @@ -145,7 +145,7 @@ static inline void _Py_SetMortal(PyObject *op, Py_ssize_t refcnt)
{
if (op) {
assert(_Py_IsImmortal(op));
#ifdef Py_NOGIL
#ifdef Py_GIL_DISABLED
op->ob_tid = _Py_UNOWNED_TID;
op->ob_ref_local = 0;
op->ob_ref_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED);
Expand All @@ -169,7 +169,7 @@ static inline void _Py_ClearImmortal(PyObject *op)
op = NULL; \
} while (0)

#if !defined(Py_NOGIL)
#if !defined(Py_GIL_DISABLED)
static inline void
_Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct)
{
Expand Down Expand Up @@ -210,7 +210,7 @@ _Py_DECREF_NO_DEALLOC(PyObject *op)
}

#else
// TODO: implement Py_DECREF specializations for Py_NOGIL build
// TODO: implement Py_DECREF specializations for Py_GIL_DISABLED build
static inline void
_Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct)
{
Expand Down Expand Up @@ -238,7 +238,7 @@ _Py_REF_IS_QUEUED(Py_ssize_t ob_ref_shared)
// Merge the local and shared reference count fields and add `extra` to the
// refcount when merging.
Py_ssize_t _Py_ExplicitMergeRefcount(PyObject *op, Py_ssize_t extra);
#endif // !defined(Py_NOGIL)
#endif // !defined(Py_GIL_DISABLED)

#ifdef Py_REF_DEBUG
# undef _Py_DEC_REFTOTAL
Expand Down
15 changes: 11 additions & 4 deletions Include/internal/pycore_weakref.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif

#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION()

static inline PyObject* _PyWeakref_GET_REF(PyObject *ref_obj) {
assert(PyWeakref_Check(ref_obj));
PyWeakReference *ref = _Py_CAST(PyWeakReference*, ref_obj);
Expand Down Expand Up @@ -35,15 +37,20 @@ static inline PyObject* _PyWeakref_GET_REF(PyObject *ref_obj) {

static inline int _PyWeakref_IS_DEAD(PyObject *ref_obj) {
assert(PyWeakref_Check(ref_obj));
int is_dead;
Py_BEGIN_CRITICAL_SECTION(ref_obj);
PyWeakReference *ref = _Py_CAST(PyWeakReference*, ref_obj);
PyObject *obj = ref->wr_object;
if (obj == Py_None) {
// clear_weakref() was called
return 1;
is_dead = 1;
}

// See _PyWeakref_GET_REF() for the rationale of this test
return (Py_REFCNT(obj) == 0);
else {
// See _PyWeakref_GET_REF() for the rationale of this test
is_dead = (Py_REFCNT(obj) == 0);
}
Py_END_CRITICAL_SECTION();
return is_dead;
}

extern Py_ssize_t _PyWeakref_GetWeakrefCount(PyWeakReference *head);
Expand Down
26 changes: 13 additions & 13 deletions Include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ check by comparing the reference count field to the immortality reference count.
#define _Py_IMMORTAL_REFCNT (UINT_MAX >> 2)
#endif

// Py_NOGIL builds indicate immortal objects using `ob_ref_local`, which is
// Py_GIL_DISABLED builds indicate immortal objects using `ob_ref_local`, which is
// always 32-bits.
#ifdef Py_NOGIL
#ifdef Py_GIL_DISABLED
#define _Py_IMMORTAL_REFCNT_LOCAL UINT32_MAX
#endif

Expand All @@ -117,7 +117,7 @@ check by comparing the reference count field to the immortality reference count.

// Make all internal uses of PyObject_HEAD_INIT immortal while preserving the
// C-API expectation that the refcnt will be set to 1.
#if defined(Py_NOGIL)
#if defined(Py_GIL_DISABLED)
#define PyObject_HEAD_INIT(type) \
{ \
0, \
Expand Down Expand Up @@ -162,7 +162,7 @@ check by comparing the reference count field to the immortality reference count.
* by hand. Similarly every pointer to a variable-size Python object can,
* in addition, be cast to PyVarObject*.
*/
#ifndef Py_NOGIL
#ifndef Py_GIL_DISABLED
struct _object {
#if (defined(__GNUC__) || defined(__clang__)) \
&& !(defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L)
Expand Down Expand Up @@ -238,7 +238,7 @@ typedef struct {
PyAPI_FUNC(int) Py_Is(PyObject *x, PyObject *y);
#define Py_Is(x, y) ((x) == (y))

#if defined(Py_NOGIL) && !defined(Py_LIMITED_API)
#if defined(Py_GIL_DISABLED) && !defined(Py_LIMITED_API)
static inline uintptr_t
_Py_ThreadId(void)
{
Expand Down Expand Up @@ -275,7 +275,7 @@ _Py_IsOwnedByCurrentThread(PyObject *ob)
#endif

static inline Py_ssize_t Py_REFCNT(PyObject *ob) {
#if !defined(Py_NOGIL)
#if !defined(Py_GIL_DISABLED)
return ob->ob_refcnt;
#else
uint32_t local = _Py_atomic_load_uint32_relaxed(&ob->ob_ref_local);
Expand Down Expand Up @@ -316,7 +316,7 @@ static inline Py_ssize_t Py_SIZE(PyObject *ob) {

static inline Py_ALWAYS_INLINE int _Py_IsImmortal(PyObject *op)
{
#if defined(Py_NOGIL)
#if defined(Py_GIL_DISABLED)
return op->ob_ref_local == _Py_IMMORTAL_REFCNT_LOCAL;
#elif SIZEOF_VOID_P > 4
return _Py_CAST(PY_INT32_T, op->ob_refcnt) < 0;
Expand Down Expand Up @@ -350,7 +350,7 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
if (_Py_IsImmortal(ob)) {
return;
}
#ifndef Py_NOGIL
#ifndef Py_GIL_DISABLED
ob->ob_refcnt = refcnt;
#else
if (_Py_IsOwnedByCurrentThread(ob)) {
Expand All @@ -367,7 +367,7 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
ob->ob_ref_local = 0;
ob->ob_ref_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED);
}
#endif // Py_NOGIL
#endif // Py_GIL_DISABLED
#endif // Py_LIMITED_API+0 < 0x030d0000
}
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
Expand Down Expand Up @@ -746,7 +746,7 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
#else
// Non-limited C API and limited C API for Python 3.9 and older access
// directly PyObject.ob_refcnt.
#if defined(Py_NOGIL)
#if defined(Py_GIL_DISABLED)
uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local);
uint32_t new_local = local + 1;
if (new_local == 0) {
Expand Down Expand Up @@ -784,7 +784,7 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
#endif


#if !defined(Py_LIMITED_API) && defined(Py_NOGIL)
#if !defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED)
// Implements Py_DECREF on objects not owned by the current thread.
PyAPI_FUNC(void) _Py_DecRefShared(PyObject *);
PyAPI_FUNC(void) _Py_DecRefSharedDebug(PyObject *, const char *, int);
Expand All @@ -810,7 +810,7 @@ static inline void Py_DECREF(PyObject *op) {
}
#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op))

#elif defined(Py_NOGIL) && defined(Py_REF_DEBUG)
#elif defined(Py_GIL_DISABLED) && defined(Py_REF_DEBUG)
static inline void Py_DECREF(const char *filename, int lineno, PyObject *op)
{
uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local);
Expand All @@ -835,7 +835,7 @@ static inline void Py_DECREF(const char *filename, int lineno, PyObject *op)
}
#define Py_DECREF(op) Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op))

#elif defined(Py_NOGIL)
#elif defined(Py_GIL_DISABLED)
static inline void Py_DECREF(PyObject *op)
{
uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local);
Expand Down
12 changes: 10 additions & 2 deletions Lib/http/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,13 @@ def _encode(data, name='data'):
"if you want to send it encoded in UTF-8." %
(name.title(), data[err.start:err.end], name)) from None

def _strip_ipv6_iface(enc_name: bytes) -> bytes:
"""Remove interface scope from IPv6 address."""
enc_name, percent, _ = enc_name.partition(b"%")
if percent:
assert enc_name.startswith(b'['), enc_name
enc_name += b']'
return enc_name

class HTTPMessage(email.message.Message):
# XXX The only usage of this method is in
Expand Down Expand Up @@ -1194,7 +1201,7 @@ def putrequest(self, method, url, skip_host=False,
netloc_enc = netloc.encode("ascii")
except UnicodeEncodeError:
netloc_enc = netloc.encode("idna")
self.putheader('Host', netloc_enc)
self.putheader('Host', _strip_ipv6_iface(netloc_enc))
else:
if self._tunnel_host:
host = self._tunnel_host
Expand All @@ -1211,8 +1218,9 @@ def putrequest(self, method, url, skip_host=False,
# As per RFC 273, IPv6 address should be wrapped with []
# when used as Host header

if host.find(':') >= 0:
if ":" in host:
host_enc = b'[' + host_enc + b']'
host_enc = _strip_ipv6_iface(host_enc)

if port == self.default_port:
self.putheader('Host', host_enc)
Expand Down
Loading

0 comments on commit 9ea707b

Please sign in to comment.