Skip to content

Commit 49a202c

Browse files
authored
Use a function call for doing decrefs instead of a macro (mypyc/mypyc#675)
When compiling mypy, this speeds up compile time with clang by 25%, decreases code size by 7%, and slows a self check down by 1%. Closes mypyc/mypyc#592.
1 parent 2e580d0 commit 49a202c

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

mypyc/emit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ def emit_dec_ref(self, dest: str, rtype: RType, is_xdec: bool = False) -> None:
255255
for i, item_type in enumerate(rtype.types):
256256
self.emit_dec_ref('{}.f{}'.format(dest, i), item_type, is_xdec)
257257
elif not rtype.is_unboxed:
258-
self.emit_line('CPy_%sDECREF(%s);' % (x, dest))
258+
self.emit_line('CPy_%sDecRef(%s);' % (x, dest))
259259
# Otherwise assume it's an unboxed, pointerless value and do nothing.
260260

261261
def pretty_name(self, typ: RType) -> str:

mypyc/lib-rt/CPy.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@ extern "C" {
1616
} // why isn't emacs smart enough to not indent this
1717
#endif
1818

19+
/* We use intentionally non-inlined decrefs since it pretty
20+
* substantially speeds up compile time while only causing a ~1%
21+
* performance degradation. We have our own copies both to avoid the
22+
* null check in Py_DecRef and to avoid making an indirect PIC
23+
* call. */
24+
CPy_NOINLINE
25+
static void CPy_DecRef(PyObject *p) {
26+
CPy_DECREF(p);
27+
}
28+
29+
CPy_NOINLINE
30+
static void CPy_XDecRef(PyObject *p) {
31+
CPy_XDECREF(p);
32+
}
33+
1934
// Naming conventions:
2035
//
2136
// Tagged: tagged int
@@ -369,19 +384,22 @@ static Py_ssize_t CPyTagged_AsSsize_t(CPyTagged x) {
369384
}
370385
}
371386

372-
static inline void CPyTagged_IncRef(CPyTagged x) {
387+
CPy_NOINLINE
388+
static void CPyTagged_IncRef(CPyTagged x) {
373389
if (CPyTagged_CheckLong(x)) {
374390
Py_INCREF(CPyTagged_LongAsObject(x));
375391
}
376392
}
377393

378-
static inline void CPyTagged_DecRef(CPyTagged x) {
394+
CPy_NOINLINE
395+
static void CPyTagged_DecRef(CPyTagged x) {
379396
if (CPyTagged_CheckLong(x)) {
380397
Py_DECREF(CPyTagged_LongAsObject(x));
381398
}
382399
}
383400

384-
static inline void CPyTagged_XDecRef(CPyTagged x) {
401+
CPy_NOINLINE
402+
static void CPyTagged_XDecRef(CPyTagged x) {
385403
if (CPyTagged_CheckLong(x)) {
386404
Py_XDECREF(CPyTagged_LongAsObject(x));
387405
}

mypyc/lib-rt/mypyc_util.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@
1515
#define CPy_Unreachable() abort()
1616
#endif
1717

18+
#if defined(__clang__) || defined(__GNUC__)
19+
#define CPy_NOINLINE __attribute__((noinline))
20+
#elif defined(_MSC_VER)
21+
#define CPy_NOINLINE __declspec(noinline)
22+
#else
23+
#define CPy_NOINLINE
24+
#endif
25+
1826
// INCREF and DECREF that assert the pointer is not NULL.
1927
// asserts are disabled in release builds so there shouldn't be a perf hit.
2028
// I'm honestly kind of surprised that this isn't done by default.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy