Skip to content

Commit 039d6c3

Browse files
committed
refactor(longobject): tighten _PyCompactLong_AddWide helpers; keep JIT-free
- Remove the dead `_BINARY_OP_ADD_INT` micro-op (no longer referenced by the macro); remove its abstract op from optimizer_bytecodes.c. - Annotate `_GUARD_TOS_INT_WIDE`, `_GUARD_NOS_INT_WIDE`, and `_BINARY_OP_ADD_INT_WIDE` as `tier1`-only so the JIT executor and optimizer generator skip them entirely. The JIT defers to tier 1 for any `BINARY_OP_ADD_INT` trace; no new JIT code paths are introduced. - Add a compact fast-path to `_PyCompactLong_AddWide` so compact-only int addition retains its original `medium_value` cost and avoids the int64-extraction overhead. - Use `__builtin_add_overflow` in `_Py_i64_add_overflow` on GCC/Clang (single instruction on x86-64 / ARM64). - Peel the last loop iteration in `_PyLong_TryAsInt64Exact` to hoist the max-digit overflow-guard out of the inner loop body.
1 parent a3277e4 commit 039d6c3

9 files changed

Lines changed: 1429 additions & 1913 deletions

File tree

Include/internal/pycore_long.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -422,16 +422,16 @@ _PyLong_TryAsInt64Exact(PyLongObject *v, int64_t *out)
422422
}
423423
#endif
424424
unsigned int shift = 0;
425-
for (Py_ssize_t i = 0; i < ndigits; i++) {
426-
uint64_t d = (uint64_t)v->long_value.ob_digit[i];
427-
if (ndigits == _PY_LONG_MAX_DIGITS_FOR_INT64 && i == ndigits - 1 &&
428-
shift != 0 && (d >> (64 - shift)) != 0)
429-
{
430-
return false;
431-
}
432-
abs_val |= d << shift;
425+
for (Py_ssize_t i = 0; i < ndigits - 1; i++) {
426+
abs_val |= (uint64_t)v->long_value.ob_digit[i] << shift;
433427
shift += PyLong_SHIFT;
434428
}
429+
uint64_t top = (uint64_t)v->long_value.ob_digit[ndigits - 1];
430+
/* Prevent UB from an oversized shift when at the maximum digit count. */
431+
if (ndigits == _PY_LONG_MAX_DIGITS_FOR_INT64 && (top >> (64 - shift)) != 0) {
432+
return false;
433+
}
434+
abs_val |= top << shift;
435435
if (abs_val <= (uint64_t)INT64_MAX) {
436436
*out = sign < 0 ? -(int64_t)abs_val : (int64_t)abs_val;
437437
return true;

Include/internal/pycore_opcode_metadata.h

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)