Skip to content

GC: root binary operands across observable coercion #784

Description

@chrisbbreuer

Parents: #359, #473
Related: #782, #783

Problem

Interpreter.applyBinary keeps both operands in raw Value locals while observable ToPrimitive coercion runs left-to-right. A user-defined left-side valueOf, toString, or Symbol.toPrimitive can enter baseline native code and consume a requested moving-GC safepoint before the right operand has been published in a precise root. The same pattern can leave the completed left primitive stale while coercing the right operand.

This was found during the #783 relocation audit. It is broader than String.prototype.concat and affects arithmetic, relational, bitwise, and loose-equality paths that perform user code during coercion.

Scope

  • Publish both original operands before the first observable coercion.
  • Replace each root slot with its completed primitive before coercing the next operand.
  • Preserve exact ECMA-262 left-to-right ordering, abrupt completion, Symbol, BigInt, and string-concatenation behavior.
  • Exercise a requested moving compaction from an earlier operand conversion while a later movable operand remains live.
  • Cover tree-walker and VM-shaped entry paths where applicable.

No-workaround rules

  • No disabling compaction, pinning cells, conservative native-stack dependency, source recognition, reordered coercion, or duplicated conversion.
  • No stacks, queues, jobs, Promise or microtask, Worker lifecycle, or Map or Set iterator changes.

Acceptance

  • Original operands and completed primitive results survive moving compaction through every observable coercion boundary.
  • Coercions still run once each, left-to-right, and abrupt completion suppresses later coercion.
  • String add, numeric, relational, bitwise, and loose-equality focused normal and TSan tests pass.
  • A deterministic moving-GC regression proves relocation rather than only ordinary collection.
  • Exact-parent Test262 accounting, threadfuzz, and the full unit gate report no regressions.

Completed integration

CI run 33113309062 completed successfully on main commit 8a1398ffc04e9e30987f968693667c7271ca3ce1, a descendant containing this implementation. All 53 executed jobs succeeded (unit and TSan-unit shards, Linux no-GIL TSan, functional/no-GIL corpus gates, fuzz profiles, ABI, Wasm, Test262 parallel, and docs); the scheduled-only nightly job was skipped. Together with the measured local evidence in the comments, this completes this issue's acceptance.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions