Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Include/internal/pycore_global_objects_fini_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Include/internal/pycore_global_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(__bytes__)
STRUCT_FOR_ID(__call__)
STRUCT_FOR_ID(__cantrace__)
STRUCT_FOR_ID(__ceil__)
STRUCT_FOR_ID(__class__)
STRUCT_FOR_ID(__class_getitem__)
STRUCT_FOR_ID(__classcell__)
Expand All @@ -112,6 +113,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(__file__)
STRUCT_FOR_ID(__firstlineno__)
STRUCT_FOR_ID(__float__)
STRUCT_FOR_ID(__floor__)
STRUCT_FOR_ID(__floordiv__)
STRUCT_FOR_ID(__format__)
STRUCT_FOR_ID(__fspath__)
Expand Down Expand Up @@ -217,6 +219,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(__subclasscheck__)
STRUCT_FOR_ID(__subclasshook__)
STRUCT_FOR_ID(__truediv__)
STRUCT_FOR_ID(__trunc__)
STRUCT_FOR_ID(__type_params__)
STRUCT_FOR_ID(__typing_is_unpacked_typevartuple__)
STRUCT_FOR_ID(__typing_prepare_subst__)
Expand Down
10 changes: 10 additions & 0 deletions Include/internal/pycore_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,8 @@ extern bool _PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name,
PyObject **attr);
extern PyObject *_PyType_LookupRefAndVersion(PyTypeObject *, PyObject *,
unsigned int *);
extern unsigned int
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
extern unsigned int
extern uint32_t

int returns imply a very limited range of values, usually only 0/-1. Please use C99 int types when returning actual data, rather just an error code.

Should the comment explaining what it does go here, rather than on the implementation?
It seems to me that "what" comments go in headers, and "how" comments in the C code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved the comment to the header file. The return value is unsigned int because tp_version_tag (in PyTypeObject) is an unsigned int and all the other _PyType_Lookup variants store the version tag as an unsigned int.

_PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef *out);

// Cache the provided init method in the specialization cache of type if the
// provided type version matches the current version of the type.
Expand Down Expand Up @@ -946,6 +948,14 @@ extern int _PyObject_IsInstanceDictEmpty(PyObject *);
PyAPI_FUNC(PyObject*) _PyObject_LookupSpecial(PyObject *, PyObject *);
PyAPI_FUNC(PyObject*) _PyObject_LookupSpecialMethod(PyObject *self, PyObject *attr, PyObject **self_or_null);

// Calls the method named `attr` on `self`, but does not set an exception if
// the attribute does not exist.
PyAPI_FUNC(PyObject *)
_PyObject_MaybeCallSpecialNoArgs(PyObject *self, PyObject *attr);

PyAPI_FUNC(PyObject *)
_PyObject_MaybeCallSpecialOneArg(PyObject *self, PyObject *attr, PyObject *arg);

extern int _PyObject_IsAbstract(PyObject *);

PyAPI_FUNC(int) _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method);
Expand Down
3 changes: 3 additions & 0 deletions Include/internal/pycore_runtime_init_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 34 additions & 1 deletion Include/internal/pycore_stackref.h
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ PyStackRef_XCLOSE(_PyStackRef ref)

// Note: this is a macro because MSVC (Windows) has trouble inlining it.

#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_REFCNT)) == ((b).bits & (~Py_TAG_REFCNT)))
#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_BITS)) == ((b).bits & (~Py_TAG_BITS)))

#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)

Expand Down Expand Up @@ -640,6 +640,28 @@ PyStackRef_FunctionCheck(_PyStackRef stackref)
return PyFunction_Check(PyStackRef_AsPyObjectBorrow(stackref));
}

static inline void
_PyThreadState_PushCStackRef(PyThreadState *tstate, _PyCStackRef *ref)
{
#ifdef Py_GIL_DISABLED
_PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate;
ref->next = tstate_impl->c_stack_refs;
tstate_impl->c_stack_refs = ref;
#endif
ref->ref = PyStackRef_NULL;
}

static inline void
_PyThreadState_PopCStackRef(PyThreadState *tstate, _PyCStackRef *ref)
{
#ifdef Py_GIL_DISABLED
_PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate;
assert(tstate_impl->c_stack_refs == ref);
tstate_impl->c_stack_refs = ref->next;
#endif
PyStackRef_XCLOSE(ref->ref);
}

#ifdef Py_GIL_DISABLED

static inline int
Expand All @@ -656,6 +678,17 @@ _Py_TryIncrefCompareStackRef(PyObject **src, PyObject *op, _PyStackRef *out)
return 0;
}

static inline int
_Py_TryXGetStackRef(PyObject **src, _PyStackRef *out)
{
PyObject *op = _Py_atomic_load_ptr_relaxed(src);
if (op == NULL) {
*out = PyStackRef_NULL;
return 1;
}
return _Py_TryIncrefCompareStackRef(src, op, out);
}

#endif

#ifdef __cplusplus
Expand Down
10 changes: 10 additions & 0 deletions Include/internal/pycore_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ typedef union _PyStackRef {
#endif
} _PyStackRef;

// A stackref that can be stored in a regular C local variable and be visible
// to the GC in the free threading build.
// Used in combination with _PyThreadState_PushCStackRef().
typedef struct _PyCStackRef {
_PyStackRef ref;
#ifdef Py_GIL_DISABLED
struct _PyCStackRef *next;
#endif
} _PyCStackRef;


#ifdef __cplusplus
}
Expand Down
3 changes: 2 additions & 1 deletion Include/internal/pycore_tstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ typedef struct _PyThreadStateImpl {
struct _qsbr_thread_state *qsbr; // only used by free-threaded build
struct llist_node mem_free_queue; // delayed free queue


#ifdef Py_GIL_DISABLED
// Stack references for the current thread that exist on the C stack
struct _PyCStackRef *c_stack_refs;
struct _gc_thread_state gc;
struct _mimalloc_thread_state mimalloc;
struct _Py_freelists freelists;
Expand Down
12 changes: 12 additions & 0 deletions Include/internal/pycore_unicodeobject_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Lib/test/test_bool.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,10 @@ def __len__(self):
__bool__ = None
self.assertRaises(TypeError, bool, B())

class C:
__len__ = None
self.assertRaises(TypeError, bool, C())

def test_real_and_imag(self):
self.assertEqual(True.real, 1)
self.assertEqual(True.imag, 0)
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/test_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1746,6 +1746,11 @@ def test_repr(self):
a[0] = a
self.assertEqual(repr(a), '{0: {...}}')

def test_repr_blocked(self):
class C:
__repr__ = None
self.assertRaises(TypeError, repr, C())

def test_round(self):
self.assertEqual(round(0.0), 0.0)
self.assertEqual(type(round(0.0)), int)
Expand Down
3 changes: 3 additions & 0 deletions Lib/test/test_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,8 @@ def testFloor(self):
#self.assertEqual(math.ceil(NINF), NINF)
#self.assertTrue(math.isnan(math.floor(NAN)))

class TestFloorIsNone(float):
__floor__ = None
class TestFloor:
def __floor__(self):
return 42
Expand All @@ -588,6 +590,7 @@ class TestBadFloor:
self.assertEqual(math.floor(FloatLike(41.9)), 41)
self.assertRaises(TypeError, math.floor, TestNoFloor())
self.assertRaises(ValueError, math.floor, TestBadFloor())
self.assertRaises(TypeError, math.floor, TestFloorIsNone(3.5))

t = TestNoFloor()
t.__floor__ = lambda *args: args
Expand Down
Loading
Loading