Repository navigation
6.0.0 release checklist #154
Copy link
Copy link
Open
Milestone
Description
What has to happen before libhxcpp 6.0.0 goes to haxelib. Pre-releases follow RELEASING.md: 6.0.0-rc.1 is out, and anything fixed before 6.0.0 ships as -rc.2 and on.
The bar for 6.0.0: every known problem that libhxcpp can fix without a change in Haxe is fixed, shown not to reproduce, or moved out with a reason (#192 for the critical ones). That covers wrong results, crashes and leaks, performance and memory, each performance fix with a before and after measurement, and cppia being usable and debuggable on every CPU, from VS Code, with clear errors.
Open for 6.0.0
Wrong results and crashes:
- cppia: CPPIA JIT: typed-array helper exceptions bypass script catches and terminate the host #404 (typed-array helper exceptions in the JIT bypass script catches and end the host), CPPIA interpreter: Array<Dynamic>.reverse and resize silently do nothing #409 (Array.reverse and resize do nothing in the interpreter), CPPIA JIT: dynamic-array searches ignore fromIndex and skip its side effects #410 (dynamic-array searches in the JIT ignore fromIndex), CPPIA JIT: dynamic-array resize evaluates the receiver twice and can resize the wrong array #411 (dynamic-array resize in the JIT evaluates the receiver twice)
- Strings and UTF-8: Return an empty array from Utf8.encode for an empty string #406 (Utf8.encode of an empty string), Validate Unicode scalar values before native UTF-8 encoding #407 (Unicode scalar values not validated before native UTF-8 encoding), Honor string lengths and terminator capacity in UTF-8 buffer conversion #408 (string lengths and terminator capacity in UTF-8 buffer conversion), Keep UTF-16 string construction inside the supplied native view #412 (UTF-16 string construction reads past the supplied native view)
- Haxe 5, all fixed: Add the typed atomic classes Haxe 5's haxe.atomic now needs #416 (the typed atomic classes
haxe.atomicnow needs), cppia: haxe.Timer.milliseconds() fails with "Unknown function : __time_stamp_ms" #417 (Timer.milliseconds()in cppia), A @:cpp.PointerType of an incomplete struct can't be stored in a class field #418 (a@:cpp.PointerTypeof an incomplete struct in a class field), Haxe 5: Lock.wait() without a timeout returns false at once #420 (Lock.wait()without a timeout returns at once) - Other: Keep Date.now Unix seconds out of 32-bit long on Windows #413 (Date.now seconds in a 32-bit long on Windows), Account for reused small blocks in current GC memory statistics #414 (current GC memory statistics miss reused small blocks), Generated C++ file names for generic instances pass the Windows 260 character limit in deep folders #356 (generated file names for generic instances pass Windows' 260-character limit in deep folders), A failing library load can still crash at exit on musl #423 (a failing library load can still crash at exit on musl)
Performance and memory, each with a before and after measurement:
- Avoid temporary numeric boxes when popping typed arrays #306 (temporary numeric boxes when popping typed arrays), Avoid retaining three times the encoded payload in Haxe 5 Bytes.ofString #405 (Haxe 5 Bytes.ofString keeps three times the encoded payload), Avoid per-element temporary string allocation in integer-array joins #415 (a temporary string per element in integer-array joins)
GC:
- Incremental GC with automatic pacing and optional scheduling hooks #372, the opt-in incremental collector: merged in 1afcf1e behind
HXCPP_GC_INCREMENTAL; close it once what remains is done or filed. Incremental GC:std::mininArray.hfails to compile on MSVC after<windows.h>(breaksSSL.cpp) #422 (std::minin Array.h after<windows.h>) fixed in 76441d8
cppia:
- Moving live instances onto a replaced class (cppia: move live instances of a replaced class onto its replacement #265): the design is agreed, the build is next
Before the release:
- Haxe 5 on every change (Test Haxe 5 on every change #153): hxb and compile-server builds, which CI does not run yet
- Architecture pass over the GC, threads, cppia and the build tool, filing what it finds
- Lime:
lime setupinstalls and runslibhxcpp setup - Every item in 6.0.0: critical runtime and cppia issues #192 fixed, shown not to reproduce, or moved out with a reason
-
6.0.0-rc.2from a greenmain, then6.0.0from a greenmain
Done since rc.1
- Wrong results, lost data and objects freed in use: SQLite SQLite TEXT reads truncate values at embedded NUL characters #272, Failed SQLite opens leave native connection handles allocated #273, SQLite result column names accumulate in the permanent string pool #274, GC of a SQLite connection silently truncates a still-live result set #290; sockets and TLS Prepared socket polls do not retain registered wrappers, allowing GC to close active connections #286, Peer certificate objects lose their native data when the SSL socket closes #291, Windows Poll misses failed connections beyond 64 read sockets and in write-only polls #304, Windows IPv6 Socket.accept fails with an IPv4-sized peer address buffer #309 to Retry resolver buffer exhaustion instead of reporting valid hosts as unknown #312; Int64 ObjectMap Float insertion rounds Int64 values already stored under other keys #282, Writable cached Int64 boxes let reflection change independent and future values #295, Boxed Int64 high-word updates are overwritten by sign extension from the low word #296, Handle minimum Int64 division and remainder by negative one without terminating the process #326; arrays and strings Array formatting shares its recursion depth across threads #277, String.substr overflows before clamping a large positive length #279, Failed dynamic-array searches box the whole array and can change element types #281, Dynamic array concat changes source storage and can discard later string pushes #293; files, Random, CFFI and cppia Zero-length file reads grow empty buffers and change read-ahead EOF state #275, cpp.Random.int cannot reach the full range of large positive bounds #276, CFFI field IDs misinterpret UTF-8 names, causing missed reads and duplicate fields #288, Loading a second CPPIA module hides resources of a still-loaded module #292, Preserve file timestamps beyond 2038 in FileSystem.stat #321, Preserve Unicode arguments and results in ordinary CFFI wrappers for Prime exports #323
- Performance and memory, each with a before and after measurement: boxing Int64-key hashes abandon specialized value storage on the second boxed Int64 #278, Avoid temporary numeric boxes when pushing into specialized dynamic arrays #294, Avoid boxing typed start offsets in array and string searches #307, Store SQLite row primitives inline instead of retaining a box for each cell #308; searching and parsing String.split and lastIndexOf still repeat long comparisons at every candidate #280, Numeric parsing transcodes unused UTF-16 suffixes before reading a short prefix #284, Bound the linear pointer scan for literal field names on wide anonymous objects #285; maps Release excess weak-map bucket capacity after GC removes the keys #204, Int64 hashing collapses packed coordinate pairs and equal halves into long chains #289; buffers and the large-object allocator Chunked array growth repeatedly copies whole buffers in socket reads and CFFI appends #287, NativeArray.reserve ignores empty dynamic arrays and causes avoidable buffer growth #297, Large-buffer release scans unrelated live allocations while holding the shared allocator lock #298, Index recycled large buffers by size to avoid repeated scans under the allocator lock #300, Include recycled large buffers in reserved-memory reporting #313, Avoid clearing large atomic copy destinations immediately before overwriting them #315; the generational collector Track dirty pointer-array ranges to reduce minor GC work after sparse writes #301, Avoid scanning every old finalizer during minor collections #302, Avoid scanning entire old maps after sparse writes during minor GC #305, Avoid rescanning stable old weak references during every minor GC #314, Skip stable old large allocations during minor GC sweeps #318, Avoid recounting unchanged block row metadata during minor GC #329; native memory Account for PCRE2 native allocations in GC memory pressure #303, Account for SQLite native database and statement memory in GC pressure #319, Account for native TLS context memory in GC pressure #325; threads Reclaim oversized backing storage from long-lived empty Deques #316, Avoid quadratic front insertion in sys.thread.Deque #317; CFFI Reuse UTF-8 conversion work across repeated CFFI string access #322, Avoid temporary argument arrays for small fixed-arity CFFI vector calls #324; a persistent Poll backend Use a persistent event backend for Poll with many mostly idle sockets #320; the cppia JIT's executable-memory probe The cppia JIT's executable-memory probe slows jitted loops and calls by about 9% #368; Avoid quadratic string copying when formatting deeply nested enums #328, cppia object allocation is 7% slower than stock in the JIT, with 12% more peak memory #369, StringMap uses 30% more peak memory than stock #370
- Found and fixed since 2026-10-23: Allow GC progress while other threads run long native regular expression matches #330 to Keep the rest of the runtime's statics alive through exit #371 (Generated C++ file names for generic instances pass the Windows 260 character limit in deep folders #356 still open), Conservative GC misses large objects held through native field pointers #373 to Release surplus native identity-table capacity after registration bursts #379 and Rebuild object-map hashes when freezing copied keys into new identities #381 to The cppia JIT compiles a whole module when it loads, so large scripts start slower than interpreted #403
- cppia: cppia: a host fingerprint that scripts can require #263 (a host fingerprint scripts can require), cppia: report what keeps a released module loaded #264 (what keeps a released module loaded), cppia: check a script against its host before linking and report every missing class and member #262 (one error naming everything a script needs from its host), cppia frames store objects, Strings and doubles at misaligned offsets #157 (frame slots read and written without misaligned access; the sanitizer job suppresses no alignment reports)
- GC: GcCensus does not find a local array on macOS #269 (objects freed when only a pointer into them was on the stack, every clang build, 740e0b9), HXCPP_SANITIZE=address builds free objects that only a local holds #270 (ASan builds, 9bee2f4), Intermittent segfault in test/haxe on macOS arm64 (generational GC) #254 (GetNextFree on ARM64, very likely EXC_BAD_ACCESS Unclosed string > KERN_INVALID_ADDRESS at 0x627. HaxeFoundation/hxcpp#1177, d734565), Reduce repeated ephemeron sweeps for weak-map dependency chains #203 (weak-map chains, c3ab80a), Release-mode heap census by class #82 (release-build heap census), A released weak-reference target stays alive on the Windows CI runners #367 (a weak-reference check held on the Windows CI runners). Generational GC: a nursery object occasionally escapes a collection under stress on Windows #168 closed as not reproducible
- cppia JIT: cppia JIT: a Bool stored in a dynamic field is boxed as 1 #259 and cppia jit: Array contains, remove and Array<Bool> element results are boxed as Int #260 (Bools boxed as Int), cppia JIT: executable memory on Apple platforms, and saying when the JIT is not used #266 (executable memory on Apple platforms, 9d64e1d), cppia JIT: bring up the arm64 code generator #271 (the JIT runs on arm64, fe67557), cppia JIT: with HXCPP_GC_GENERATIONAL, objects only the stack holds are freed while in use #299 (objects only the stack held freed under HXCPP_GC_GENERATIONAL, Calling Gc.compact() in cppia collects the current CppiaClosure/ScriptCallable? HaxeFoundation/hxcpp#1196, 0fe6cbe), cppia JIT: most global builtins have no code and only trace their name #421 (global builtins with no JIT code, 920781c)
- Debugging cppia from VS Code, interpreted and with the JIT, on Windows, Linux and macOS (cppia: a debugger that attaches before a script loads cannot set breakpoints in it #283, Breakpoints don't work on cppia compiled with HXCPP_DEBUGGER HaxeFoundation/hxcpp#498): libhxcpp's half is on main, and the server's half is Set breakpoints in cppia scripts loaded after the server attaches vshaxe/hxcpp-debugger#48. docs/CppiaDebugging.md describes the setup
- Processes: Windows: Process.close waits for a descendant that holds the output pipe while another thread reads it #261 (Windows Process.close waiting on a descendant's pipe, d8e534c), cpp.Function fields don't compile with HXCPP_GC_GENERATIONAL #167 (
cpp.Functionfields underHXCPP_GC_GENERATIONAL), Generated files whose names differ only in case overwrite each other #70 (the build tool stops when generated file names differ only in case) - Infrastructure: Haxe 5.0.0-preview.1 builds against the API level 430 runtime and runs the suites on every change (b26ce09), output compared with the other Haxe targets (Compare test program output with the other Haxe targets #150), nightly downstream builds (Nightly downstream builds of Lime, OpenFL, Flixel, HaxeUI and CrossByte #149), the build tool stops a Haxe older than 4.2, fuzzing the runtime's parsers (Fuzz the runtime's parsers #257), benchmark results tracked in CI (Track benchmark results in CI and report regressions #258), the benchmark tables republished at 72eedd0 with a 5% band for code layout
Done before rc.1
- Sanitizer CI (UBSan, ASan, TSan, CodeQL) and everything it reported (Run the test suites under sanitizers and CodeQL #148, Constant allocations are only 4-byte aligned #155, String headers are read from unaligned string data #156, SSL casts the socket handle to its own copy of SocketWrapper #158, cppia: functions with an untyped return read an uninitialised return type #159)
- GC and thread races and the thread API: Generational GC: a thread attaching during a mode switch gets no remembered set #139, ARM64: the collector can miss a thread leaving a GC-free zone #142, The moving GC ignores the pin flag on alloc finalizers #143, ThreadLocal reuses a slot without clearing its old values #68, Sys.exit destroys GC state while other threads still allocate #67, Process.exitCode returns 0 when called again on POSIX #114, Thread wait timeouts break on negative, NaN, huge and sub-millisecond values #122, Natively attached threads all get thread id 0 #123, Windows semaphores cap at 134 million permits #125
- Security and dependencies: the PCRE2 backports, SQLite 3.54.0 with the WAL-reset fix, Actions off Node 20 (Dependency upgrades by priority #147), the mbedTLS provider for static builds (Let a library provide mbedTLS for static builds #161)
- Wrong results: Comparing a String with a Dynamic depends on the static types #97 to haxe.Utf8 truncates characters above U+FFFF #107, Bytes.ofString and urlEncode throw on a lone surrogate #110, Date.getTimezoneOffset ignores daylight saving time on Windows #112, Negative fractional times round toward zero #116, Sys.environment decodes the Windows environment as UTF-8 #117, Haxe 5 thread objects: pseudo-handles for names, and Scratch copy assignment #124, cppia JIT: String += drops null and turns an empty string into null #129, cppia: isOfType, cast and catch ignore interfaces inherited through other interfaces #131 to cppia: safe casts to Int, Float, Bool and String never throw #135, the narrow-trigger group (Zero-length process pipe operations grow empty byte buffers #209, POSIX child stdin is closed during exec when the parent has no fd 0 #210, Socket select and poll restart finite timeouts after every signal interruption #217, Whole-file reads return empty data for readable zero-size procfs files #219, Positive sub-microsecond socket timeouts disable the timeout on POSIX #220, Reflect.hasField misses fields in fixed anonymous objects #222, Anonymous-object formatting shares its recursion limit across threads #223, Reflected Array.filter rereads source values after the predicate changes them #224, Native heap freezing duplicates shared objects instead of preserving graph identity #226, Native cleanup callbacks erase outer frames from a propagating exception stack #229, Print floats with the shortest digits that round-trip #93, HXCPP_GC_VERIFY reports unmarked row HaxeFoundation/hxcpp#1415) and the high-severity triage of @:nativeGen interfaces: second interface gets the object's address, and the collector misses it #193 to Native cleanup callbacks erase outer frames from a propagating exception stack #229 (6.0.0: critical runtime and cppia issues #192)
- Performance against stock hxcpp 4.3.53 and its regression suite (Add a native benchmark suite, recorded baselines and performance regression checks #151, GC heap does not grow; HXCPP_MINIMUM_WORKING_MEMORY is ignored (allocation ~3x slower than stock) #230 to Peak memory is 4-22% higher than stock hxcpp 4.3.53 on most benchmarks #235 and the items in 6.0.0: critical runtime and cppia issues #192)
- Haxe 5 API level 500 fixes tested on Haxe 5: Scratch can reuse a live buffer when allocations are released out of order #184 to Endian-aware native pointer readers instantiate the wrong pointer type #188, Weak bound-method liveness does not follow callable adapter chains #202
- Docs: README, Defines.md, Changes.md, SECURITY.md and supported versions (Release process: versions, a stable branch and a security policy #152), the performance table
- Release mechanics:
haxelib pathoutput for hxp (extraParams -D lines make hxp misread libhxcpp's path #165), Lime 8.4.0's own mbedTLS 3.6 copy, fixes for a released line on arelease/<major>.<minor>branch (Release process: versions, a stable branch and a security policy #152),6.0.0-rc.1on haxelib and GitHub
After 6.0.0
- Issues labelled
needs haxe(Array.iterator() is not a haxe.iterators.ArrayIterator #5, cppia: extern abstract over a native enum fails to link #8, Generated files whose names differ only in case overwrite each other #70, Provide native map iteration without copying the whole map into arrays #199, IPv6 socket host and peer queries return an IPv4 address instead of the endpoint #218, Null<UInt> compared with null is wrong on cpp #251), which wait on HaxeFoundation/haxe - Haxe nightly (API level 500): GC stress segfaults and suite failures #164 and Avoid Dynamic boxing in typed Haxe 5 numeric array sorting #195, which wait for Haxe 5 itself
- Port the bundled mbedTLS to the 4.1 LTS before 3.6 support ends #255 (the mbedTLS 4.1 port; Lime 8.4.0 provides the 3.6 LTS, supported to March 2027), Investigate where else allocation cost and memory can come down #256
- Upgrade the cppia JIT's sljit to 0.95 #419, sljit 0.95 for the cppia JIT, which drops our four sljit patches but changes the x86-32 ABI
- Opt-in concurrent marking for the GC (6.x) #327, opt-in concurrent marking, a proposal for 6.x. Codex's uncommitted work on it is saved on the local branch
codex/concurrent-gc-wip - CrossByte's testASmallInt64IsAnInt64WhenWrapped expects hxcpp's old Int64 boxing and needs changing in CrossByte
Metadata
Metadata
Assignees
Labels
No labels
Activity
Group the 6.0.0 changes by area