Repository navigation
Conversation
A script function unwinds its frame on a throw only inside a script try. What a static initialiser throws is caught by ScriptedClass.init instead, so the frame of a function that threw stayed on the stack, and building the next static function of the class crashed. The initialiser now runs as if inside a try. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Compiled, the module ran the initialiser again as it booted, and the throw was the loader refusing the whole batch. The batch was then split until the module was alone, and the halves could no longer name each other's classes, so modules with nothing wrong with them were left interpreted as compiled elsewhere. The class now remembers the first initialiser that threw, and the compiler skips its module before writing it, with that as the reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A static initialiser that throws no longer reaches beyond its own field. It could crash the next static function of its class, and, compiled, take modules with nothing wrong with them out of the compile. One commit for each.
1. Unwind a function that throws through a static initialiser.
A script function unwinds its frame on a throw only inside a script
try(inTry). What a static initialiser throws is caught byScriptedClass.initinstead, so the frame of the function that threw stayed on the stack. Buildingbthen took thestack.length > 1branch ofbuildFunction, wherecapturedLocalsis null for a class's statics.initFieldnow runs the initialiser as if inside atry, as the:safebridges already do around the methods they call, and restores the declared names when it throws.Any other host catch around a script function call outside
:safeleaves the frame the same way,Module.startaround the module-level program for one. Only the static initialiser is fixed here.2. Leave a module whose static initialiser threw interpreted.
Compiled, the module ran the initialiser again as it booted, and the throw was the loader refusing the whole batch.
batchthen split it until the module was alone, and the halves could no longer name each other's classes, so modules with nothing wrong with them were left interpreted ascompiled elsewhere. Measured withLib, six modules using it, and:Bada static initialiser threw when the module started (v: start)Libcompileduses Lib, which is compiled elsewhereBad.go()3, interpreted3, interpretedScriptedClasskeeps the first static initialiser that threw instaticFailure(field: message, reset when the class initialises again).batchhands that to the compiler as the newUnit.skip, andBackend.compilerecords the module as skipped before writing it.dropDanglingUsersthen takes its users with it, as for any skip.onExpressionErroris still called as before.Tests
ClassProbecase for the first. Without the fix it readsGAP ... => null (want 4)on eval and ends the hxcpp suite.StaticInitTest.throwingfor the second, over the world above. Without the fix, three checks fail: the module is refused rather than skipped, and3 of 6 users of the library compiled.test/run.sh eval cpp: 422 / 422 / 455 passed (upstream: 421 / 421 / 451). Conformance columns (eval-interp, hxcpp-interp, hxcpp-cppia, hxcpp-cppia-jit) and the frontier are unchanged.Playground,Shapes) as upstream. HashLink not run.