Only refer to LLVM symbol table in calls to Symbol#to_s#15486
Merged
straight-shoota merged 3 commits intocrystal-lang:masterfrom Mar 13, 2025
Merged
Only refer to LLVM symbol table in calls to Symbol#to_s#15486straight-shoota merged 3 commits intocrystal-lang:masterfrom
Symbol#to_s#15486straight-shoota merged 3 commits intocrystal-lang:masterfrom
Conversation
Symbol#to_sSymbol#to_s
ysbaddaden
approved these changes
Feb 20, 2025
Blacksmoke16
pushed a commit
to Blacksmoke16/crystal
that referenced
this pull request
Mar 18, 2025
…ng#15486) The compiler places the string contents of all symbols defined in the source code into a special `:symbol_table` LLVM global variable in the main LLVM module: ```llvm @":symbol_table" = global [24 x ptr] [ ptr @"'general'", ptr @"'no_error'", ptr @"'gc'", ptr @"'sequentially_consis...'", ptr @"'monotonic'", ptr @"'acquire'", ptr @"'evloop'", ptr @"'xchg'", ptr @"'release'", ptr @"'acquire_release'", ptr @"'io_write'", ptr @"'sched'", ptr @"'io_read'", ptr @"'skip'", ptr @"'none'", ptr @"'active'", ptr @"'done'", ptr @"'unchecked'", ptr @"'sleep'", ptr @"'relaxed'", ptr @"'add'", ptr @"'sub'", ptr @"'file'", ptr @"'target'" ] ``` Every LLVM module, without exception, also declares it: ```llvm @":symbol_table" = external global [24 x ptr] ``` Since the total number of symbols is part of the variable type, adding or removing any symbol invalidates all object files in the Crystal cache, even though only `Symbol#to_s`, or rather `@[Primitive(:symbol_to_s)]`, has access to this variable. This PR removes this declaration except where the primitive accesses it. Changes to the symbol table will only affect LLVM modules that call `Symbol#to_s` (the primitive body itself is inlined). Building an empty file, replacing it with `x = :abcde`, then rebuilding the same file will now give: ``` Codegen (bc+obj): - 315/317 .o files were reused These modules were not reused: - _main (_main.o0.bc) - Crystal (C-rystal.o0.bc) ``` (`Crystal` is also invalidated because the return type of `Crystal.main` is now `Symbol` instead of `Nil`; appending `nil` to the file makes this module reusable.) Note that it is still possible to invalidate large portions of the cache from the addition or removal of symbols, because their indices are allocated sequentially, and inlined on every use. Something like crystal-lang#15485 but for `Symbol` values would solve that.
1 task
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.
The compiler places the string contents of all symbols defined in the source code into a special
:symbol_tableLLVM global variable in the main LLVM module:Every LLVM module, without exception, also declares it:
Since the total number of symbols is part of the variable type, adding or removing any symbol invalidates all object files in the Crystal cache, even though only
Symbol#to_s, or rather@[Primitive(:symbol_to_s)], has access to this variable.This PR removes this declaration except where the primitive accesses it. Changes to the symbol table will only affect LLVM modules that call
Symbol#to_s(the primitive body itself is inlined). Building an empty file, replacing it withx = :abcde, then rebuilding the same file will now give:(
Crystalis also invalidated because the return type ofCrystal.mainis nowSymbolinstead ofNil; appendingnilto the file makes this module reusable.)Note that it is still possible to invalidate large portions of the cache from the addition or removal of symbols, because their indices are allocated sequentially, and inlined on every use. Something like #15485 but for
Symbolvalues would solve that.