Skip to content

Commit

Permalink
LLVM optimization
Browse files Browse the repository at this point in the history
@BlobCodes: I noticed that adding this code prevents LLVM from
re-running the once mechanism multiple times for the same variable.

Modified to avoid an undefined behavior when the assumption doesn't
hold that doubles as a safety net (print error + exit).
  • Loading branch information
ysbaddaden committed Jan 9, 2025
1 parent 43421ce commit 7495855
Showing 1 changed file with 14 additions and 3 deletions.
17 changes: 14 additions & 3 deletions src/crystal/once.cr
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@
raise "Recursion while initializing class variables and/or constants"
end
end

@[NoInline]
def self.once_unreachable : NoReturn
System.print_error "BUG: failed to initialize constant or class variable\n"
LibC._exit(1)
end
end

# :nodoc:
Expand All @@ -68,9 +74,14 @@
# is a `fun` the function will still appear in the symbol table, though it
# will never be called.
@[AlwaysInline]
fun __crystal_once(flag : Int8*, initializer : Void*) : Nil
flag = flag.as(Crystal::OnceState*)
Crystal.once(flag, initializer) unless flag.value.initialized?
fun __crystal_once(flag : Crystal::OnceState*, initializer : Void*) : Nil
return if flag.value.initialized?

Crystal.once(flag, initializer)

# make LLVM assume that it musn't call `__crystal_once` anymore for this,
# also doubles as a safety check
Crystal.once_unreachable unless flag.value.initialized?
end
{% else %}
# This implementation uses a global array to store the initialization flag
Expand Down

0 comments on commit 7495855

Please sign in to comment.