Skip to content

correct addition coercion and optimize pooled arithmetic - #61

Merged
theMackabu merged 2 commits into
masterfrom
fix/bigint-coercion-gc
Aug 2, 2026
Merged

correct addition coercion and optimize pooled arithmetic#61
theMackabu merged 2 commits into
masterfrom
fix/bigint-coercion-gc

Conversation

@theMackabu

@theMackabu theMackabu commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added BigInt garbage collection support for improved memory management.
    • Added BigInt.prototype.valueOf() support.
    • Improved BigInt arithmetic, string concatenation, boxed values, and mixed-type coercion.
    • Improved handling of BigInt constants retained by compiled code.
  • Bug Fixes

    • Preserved live BigInt values during garbage collection.
    • Improved validation and error handling for unsupported mixed-type additions.
  • Tests

    • Added BigInt garbage-collection stress tests and expanded coercion and arithmetic coverage.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 27d69037-3f75-4334-9e41-fe1ea0ac9834

📥 Commits

Reviewing files that changed from the base of the PR and between 9351aa4 and b0079be.

📒 Files selected for processing (6)
  • meson/ant.version
  • src/gc/gc.c
  • src/gc/objects.c
  • src/modules/bigint.c
  • src/silver/compiler.c
  • src/silver/engine.c
💤 Files with no reviewable changes (1)
  • src/gc/gc.c
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/silver/engine.c
  • src/gc/objects.c
  • src/silver/compiler.c
  • src/modules/bigint.c

📝 Walkthrough

Walkthrough

BigInt arithmetic now reduces intermediate allocations, supports boxed coercion methods and revised addition semantics, and integrates BigInt pool memory with garbage collection. Compiler constant tracking and tests cover coercion, arithmetic correctness, retention, and pool cleanup.

Changes

BigInt runtime

Layer / File(s) Summary
BigInt storage and arithmetic
src/modules/bigint.c
BigInt limb operations use caller-provided buffers, stack storage for small results, payload allocation for large results, and finalized sign and limb metadata.
Addition coercion and BigInt methods
src/silver/ops/arithmetic.h, src/silver/engine.c, src/modules/bigint.c, examples/spec/bigint.js
Addition performs primitive conversion and BigInt-specific validation. Boxed BigInt valueOf() and toString() behavior is implemented and tested.
BigInt garbage collection
include/gc/bigints.h, src/gc/bigints.c, src/gc/gc.c, src/gc/objects.c, tests/test_bigint_gc.cjs
BigInt blocks and slots are indexed, marked from values and stack words, swept into pool freelists, and validated through churn and large-value tests.
BigInt constant retention and release metadata
src/silver/compiler.c, meson/ant.version
BigInt constants are added to the compiler-generated GC constant slot table. The project version changes to 13.0.0.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant gc_run
  participant gc_objects
  participant gc_bigints
  gc_run->>gc_bigints: gc_bigints_begin(js)
  gc_objects->>gc_bigints: gc_bigints_mark(payload)
  gc_run->>gc_bigints: gc_bigints_sweep(js)
Loading

Possibly related PRs

  • theMackabu/ant#12: BigInt and object coercion paths share Symbol.toPrimitive and addition semantics.
  • theMackabu/ant#27: Both changes modify garbage-collection behavior in src/gc/gc.c.
  • theMackabu/ant#60: Both changes modify compiler garbage-collection constant-table handling.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes to addition coercion and pooled arithmetic optimization.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/bigint-coercion-gc

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (3)
src/modules/bigint.c (2)

347-414: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Make the output-buffer capacity contract explicit.

These helpers moved from "allocate and return" to "write into a caller buffer", and the required capacity is now implicit: bigint_add_abs_limbs always writes result[maxlen] (needs max(alen,blen)+1), bigint_sub_abs_limbs needs alen, and bigint_mul_abs_limbs needs alen+blen+1. All current call sites satisfy this, but an under-sized caller would silently overrun a 32-limb stack buffer. Also, bigint_add_u32_inplace silently drops the carry when count == capacity instead of signalling — currently unreachable, but a quiet wrong-result path.

Suggest documenting the minimum capacity on each helper and adding assert()s (or passing capacity consistently as bigint_add_u32_inplace already does).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/bigint.c` around lines 347 - 414, Make the caller-buffer capacity
contract explicit for bigint_add_abs_limbs, bigint_sub_abs_limbs, and
bigint_mul_abs_limbs by documenting each helper’s minimum required capacity and
asserting it at entry or otherwise validating it consistently. Update
bigint_add_u32_inplace so a carry remaining when count reaches capacity is
detected and signalled rather than silently discarded, while preserving existing
behavior for valid-capacity callers.

1141-1182: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Consider extracting the "stack buffer vs. payload" scaffold.

The stack_limbs / capacity > BIGINT_STACK_LIMBS / allocate / re-fetch limb pointers / bigint_finish_payload-or-js_mkbigint_limbs block is now repeated in bigint_add, bigint_sub, bigint_mul, bigint_bitwise_binary, bigint_bitnot, bigint_shift_left, and bigint_shift_right. Correct in every instance here, but the mandatory post-allocation re-fetch of ad/bd/limbs is exactly the kind of step that gets dropped in a future edit, and the failure mode is a silent use-after-GC.

A small bigint_result_buf_t holding { ant_value_t out; bigint_payload_t *payload; uint32_t *limbs; uint32_t stack[BIGINT_STACK_LIMBS]; } with bigint_result_reserve() / bigint_result_finish() would centralize both the capacity decision and the re-fetch requirement.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/bigint.c` around lines 1141 - 1182, Extract the repeated
result-buffer setup and completion logic from bigint_add, bigint_sub,
bigint_mul, bigint_bitwise_binary, bigint_bitnot, bigint_shift_left, and
bigint_shift_right into a bigint_result_buf_t with bigint_result_reserve() and
bigint_result_finish(). Centralize stack-versus-payload allocation, ensure
reserve re-fetches all input limb pointers after allocation, and use the finish
helper for both payload and stack-backed results while preserving each
operation’s existing capacity, length, and sign behavior.
examples/spec/bigint.js (1)

18-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Good coverage of the coercion rules; two gaps worth closing.

  1. testThrows (examples/spec/helpers.js lines 64-73) accepts any thrown value, so these cases pass even though 1n + 1 currently throws a plain Error rather than TypeError (see src/silver/ops/arithmetic.h line 60). An error-type assertion would have caught it.
  2. Nothing here crosses the new BIGINT_STACK_LIMBS (32 limbs / 1024-bit) boundary in src/modules/bigint.c, which is where this PR switches from the stack buffer to a GC-allocated payload — the highest-risk path is untested. A (1n << 2000n)-scale add/sub/mul/shift round-trip would exercise it.
💚 Suggested additions
+const huge = 1n << 2000n;
+test('bigint payload add', (huge + huge) === (huge * 2n), true);
+test('bigint payload sub', (huge - huge) === 0n, true);
+test('bigint payload shift roundtrip', ((huge << 64n) >> 64n) === huge, true);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/spec/bigint.js` around lines 18 - 54, Strengthen the bigint tests by
extending testThrows in helpers.js to optionally assert the thrown error type,
then use that assertion for mixed bigint/number, boolean, null, undefined, and
symbol additions to require TypeError. Add coverage in the bigint specification
around BIGINT_STACK_LIMBS using values beyond 1024 bits, exercising addition,
subtraction, multiplication, and shifts with round-trip result checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/modules/bigint.c`:
- Around line 1696-1704: Update builtin_bigint_valueOf so the non-BigInt
receiver path throws a TypeError rather than a generic Error, matching the
behavior of the corresponding BigInt toString implementation while preserving
primitive unwrapping and successful BigInt returns.
- Around line 1651-1654: Update the non-BigInt receiver fallback in
BigInt.prototype.toString to call js_mkerr_typed with JS_ERR_TYPE instead of
js_mkerr, while preserving the existing unwrap_primitive validation and error
message.

In `@src/silver/engine.c`:
- Around line 395-407: Re-resolve the frame slot pointer after both
sv_add_to_primitive calls and before any slot write: update the builder append
path at src/silver/engine.c lines 395-407 and the snapshot path at
src/silver/engine.c lines 456-471 using sv_frame_slot_ptr(frame, slot_idx). This
ensures sv_slot_generic_add_store and feedback writes use current storage after
user-code re-entry.

In `@src/silver/ops/arithmetic.h`:
- Around line 59-60: Update the BigInt rejection paths to construct TypeError
instances via js_mkerr_typed(js, JS_ERR_TYPE, ...) instead of js_mkerr:
arithmetic.h lines 59-60 for mixed BigInt operations, bigint.c lines 1651-1654
for toString, and bigint.c lines 1696-1704 for valueOf. Preserve each existing
error message.

---

Nitpick comments:
In `@examples/spec/bigint.js`:
- Around line 18-54: Strengthen the bigint tests by extending testThrows in
helpers.js to optionally assert the thrown error type, then use that assertion
for mixed bigint/number, boolean, null, undefined, and symbol additions to
require TypeError. Add coverage in the bigint specification around
BIGINT_STACK_LIMBS using values beyond 1024 bits, exercising addition,
subtraction, multiplication, and shifts with round-trip result checks.

In `@src/modules/bigint.c`:
- Around line 347-414: Make the caller-buffer capacity contract explicit for
bigint_add_abs_limbs, bigint_sub_abs_limbs, and bigint_mul_abs_limbs by
documenting each helper’s minimum required capacity and asserting it at entry or
otherwise validating it consistently. Update bigint_add_u32_inplace so a carry
remaining when count reaches capacity is detected and signalled rather than
silently discarded, while preserving existing behavior for valid-capacity
callers.
- Around line 1141-1182: Extract the repeated result-buffer setup and completion
logic from bigint_add, bigint_sub, bigint_mul, bigint_bitwise_binary,
bigint_bitnot, bigint_shift_left, and bigint_shift_right into a
bigint_result_buf_t with bigint_result_reserve() and bigint_result_finish().
Centralize stack-versus-payload allocation, ensure reserve re-fetches all input
limb pointers after allocation, and use the finish helper for both payload and
stack-backed results while preserving each operation’s existing capacity,
length, and sign behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d07b9e66-97c3-4940-bb38-8c6b72062996

📥 Commits

Reviewing files that changed from the base of the PR and between 8ba31b9 and 9351aa4.

📒 Files selected for processing (11)
  • examples/spec/bigint.js
  • include/gc/bigints.h
  • meson/pgo/profiles/ant-darwin-aarch64.profdata
  • src/gc/bigints.c
  • src/gc/gc.c
  • src/gc/objects.c
  • src/modules/bigint.c
  • src/silver/compiler.c
  • src/silver/engine.c
  • src/silver/ops/arithmetic.h
  • tests/test_bigint_gc.cjs

Comment thread src/modules/bigint.c
Comment thread src/modules/bigint.c
Comment thread src/silver/engine.c
Comment thread src/silver/ops/arithmetic.h
# Conflicts:
#	src/gc/gc.c
#	src/modules/bigint.c
@theMackabu
theMackabu merged commit 15d0502 into master Aug 2, 2026
12 checks passed
@theMackabu
theMackabu deleted the fix/bigint-coercion-gc branch August 4, 2026 04:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant