Skip to content

Commit

Permalink
Use Win32 heap functions with -Dgc_none
Browse files Browse the repository at this point in the history
  • Loading branch information
HertzDevil committed Nov 7, 2024
1 parent 84a293d commit e316816
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 6 deletions.
39 changes: 33 additions & 6 deletions src/gc/none.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{% if flag?(:win32) %}
require "c/process"
require "c/heapapi"
{% end %}
require "crystal/tracing"

Expand All @@ -11,21 +12,42 @@ module GC
# :nodoc:
def self.malloc(size : LibC::SizeT) : Void*
Crystal.trace :gc, "malloc", size: size
# libc malloc is not guaranteed to return cleared memory, so we need to
# explicitly clear it. Ref: https://github.com/crystal-lang/crystal/issues/14678
LibC.malloc(size).tap(&.clear)

{% if flag?(:win32) %}
LibC.HeapAlloc(LibC.GetProcessHeap, LibC::HEAP_ZERO_MEMORY, size)
{% else %}
# libc malloc is not guaranteed to return cleared memory, so we need to
# explicitly clear it. Ref: https://github.com/crystal-lang/crystal/issues/14678
LibC.malloc(size).tap(&.clear)
{% end %}
end

# :nodoc:
def self.malloc_atomic(size : LibC::SizeT) : Void*
Crystal.trace :gc, "malloc", size: size, atomic: 1
LibC.malloc(size)

{% if flag?(:win32) %}
LibC.HeapAlloc(LibC.GetProcessHeap, 0, size)
{% else %}
LibC.malloc(size)
{% end %}
end

# :nodoc:
def self.realloc(pointer : Void*, size : LibC::SizeT) : Void*
Crystal.trace :gc, "realloc", size: size
LibC.realloc(pointer, size)

{% if flag?(:win32) %}
# realloc with a null pointer should behave like plain malloc, but Win32
# doesn't do that
if pointer
LibC.HeapReAlloc(LibC.GetProcessHeap, LibC::HEAP_ZERO_MEMORY, pointer, size)
else
LibC.HeapAlloc(LibC.GetProcessHeap, LibC::HEAP_ZERO_MEMORY, size)
end
{% else %}
LibC.realloc(pointer, size)
{% end %}
end

def self.collect
Expand All @@ -39,7 +61,12 @@ module GC

def self.free(pointer : Void*) : Nil
Crystal.trace :gc, "free"
LibC.free(pointer)

{% if flag?(:win32) %}
LibC.HeapFree(LibC.GetProcessHeap, 0, pointer)
{% else %}
LibC.free(pointer)
{% end %}
end

def self.is_heap_ptr(pointer : Void*) : Bool
Expand Down
2 changes: 2 additions & 0 deletions src/lib_c/x86_64-windows-msvc/c/heapapi.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require "c/winnt"

lib LibC
HEAP_ZERO_MEMORY = 0x00000008

fun GetProcessHeap : HANDLE
fun HeapAlloc(hHeap : HANDLE, dwFlags : DWORD, dwBytes : SizeT) : Void*
fun HeapReAlloc(hHeap : HANDLE, dwFlags : DWORD, lpMem : Void*, dwBytes : SizeT) : Void*
Expand Down

0 comments on commit e316816

Please sign in to comment.