1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-17 17:20:29 +02:00

Add gc_allocation_kind argument to gc_allocate

Adapt all users.  Will eventually allow for mmc to have untagged
allocations.
This commit is contained in:
Andy Wingo 2025-03-07 10:58:05 +01:00
parent 5bddd522cf
commit 521cd44ebd
13 changed files with 158 additions and 75 deletions

View file

@ -21,15 +21,29 @@ static inline size_t gc_allocator_allocation_limit_offset(void) {
GC_CRASH();
}
static inline size_t gc_allocator_freelist_offset(size_t size) {
static inline size_t gc_allocator_freelist_offset(size_t size,
enum gc_allocation_kind kind) {
GC_ASSERT(size);
return sizeof(void*) * ((size - 1) / gc_allocator_small_granule_size());
size_t base;
switch (kind) {
case GC_ALLOCATION_TAGGED:
case GC_ALLOCATION_UNTAGGED_CONSERVATIVE:
base = 0;
break;
case GC_ALLOCATION_UNTAGGED_POINTERLESS:
case GC_ALLOCATION_TAGGED_POINTERLESS:
base = (sizeof(void*) * gc_allocator_large_threshold() /
gc_allocator_small_granule_size());
break;
}
size_t bucket = (size - 1) / gc_allocator_small_granule_size();
return base + sizeof(void*) * bucket;
}
static inline size_t gc_allocator_alloc_table_alignment(void) {
return 0;
}
static inline uint8_t gc_allocator_alloc_table_begin_pattern(void) {
static inline uint8_t gc_allocator_alloc_table_begin_pattern(enum gc_allocation_kind) {
GC_CRASH();
}
static inline uint8_t gc_allocator_alloc_table_end_pattern(void) {

19
api/gc-allocation-kind.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef GC_ALLOCATION_KIND_H
#define GC_ALLOCATION_KIND_H
enum gc_allocation_kind {
// An object whose type can be inspected at run-time based on its contents,
// and whose fields be traced via the gc_trace_object procedure.
GC_ALLOCATION_TAGGED,
// Like GC_ALLOCATION_TAGGED, but not containing any fields that reference
// GC-managed objects. The GC may choose to handle these specially.
GC_ALLOCATION_TAGGED_POINTERLESS,
// A raw allocation whose type cannot be inspected at trace-time, and whose
// fields should be traced conservatively.
GC_ALLOCATION_UNTAGGED_CONSERVATIVE,
// A raw allocation whose type cannot be inspected at trace-time, but
// containing no fields that reference GC-managed objects.
GC_ALLOCATION_UNTAGGED_POINTERLESS
};
#endif // GC_ALLOCATION_KIND_H

View file

@ -2,6 +2,7 @@
#define GC_API_H_
#include "gc-config.h"
#include "gc-allocation-kind.h"
#include "gc-assert.h"
#include "gc-attrs.h"
#include "gc-collection-kind.h"
@ -56,10 +57,10 @@ GC_API_ void* gc_call_without_gc(struct gc_mutator *mut, void* (*f)(void*),
GC_API_ void gc_collect(struct gc_mutator *mut,
enum gc_collection_kind requested_kind);
static inline void gc_update_alloc_table(struct gc_ref obj,
size_t size) GC_ALWAYS_INLINE;
static inline void gc_update_alloc_table(struct gc_ref obj,
size_t size) {
static inline void gc_update_alloc_table(struct gc_ref obj, size_t size,
enum gc_allocation_kind kind) GC_ALWAYS_INLINE;
static inline void gc_update_alloc_table(struct gc_ref obj, size_t size,
enum gc_allocation_kind kind) {
size_t alignment = gc_allocator_alloc_table_alignment();
if (!alignment) return;
@ -69,7 +70,7 @@ static inline void gc_update_alloc_table(struct gc_ref obj,
uintptr_t granule = (addr & (alignment - 1)) / granule_size;
uint8_t *alloc = (uint8_t*)(base + granule);
uint8_t begin_pattern = gc_allocator_alloc_table_begin_pattern();
uint8_t begin_pattern = gc_allocator_alloc_table_begin_pattern(kind);
uint8_t end_pattern = gc_allocator_alloc_table_end_pattern();
if (end_pattern) {
size_t granules = size / granule_size;
@ -86,11 +87,15 @@ static inline void gc_update_alloc_table(struct gc_ref obj,
}
}
GC_API_ void* gc_allocate_slow(struct gc_mutator *mut, size_t bytes) GC_NEVER_INLINE;
GC_API_ void* gc_allocate_slow(struct gc_mutator *mut, size_t bytes,
enum gc_allocation_kind kind) GC_NEVER_INLINE;
static inline void*
gc_allocate_small_fast_bump_pointer(struct gc_mutator *mut, size_t size) GC_ALWAYS_INLINE;
static inline void* gc_allocate_small_fast_bump_pointer(struct gc_mutator *mut, size_t size) {
gc_allocate_small_fast_bump_pointer(struct gc_mutator *mut, size_t size,
enum gc_allocation_kind kind) GC_ALWAYS_INLINE;
static inline void* gc_allocate_small_fast_bump_pointer(struct gc_mutator *mut,
size_t size,
enum gc_allocation_kind kind) {
GC_ASSERT(size <= gc_allocator_large_threshold());
size_t granule_size = gc_allocator_small_granule_size();
@ -111,17 +116,20 @@ static inline void* gc_allocate_small_fast_bump_pointer(struct gc_mutator *mut,
*hp_loc = new_hp;
gc_update_alloc_table(gc_ref(hp), size);
gc_update_alloc_table(gc_ref(hp), size, kind);
return (void*)hp;
}
static inline void* gc_allocate_small_fast_freelist(struct gc_mutator *mut,
size_t size) GC_ALWAYS_INLINE;
static inline void* gc_allocate_small_fast_freelist(struct gc_mutator *mut, size_t size) {
size_t size,
enum gc_allocation_kind kind) GC_ALWAYS_INLINE;
static inline void* gc_allocate_small_fast_freelist(struct gc_mutator *mut,
size_t size,
enum gc_allocation_kind kind) {
GC_ASSERT(size <= gc_allocator_large_threshold());
size_t freelist_offset = gc_allocator_freelist_offset(size);
size_t freelist_offset = gc_allocator_freelist_offset(size, kind);
uintptr_t base_addr = (uintptr_t)mut;
void **freelist_loc = (void**)(base_addr + freelist_offset);
@ -131,21 +139,23 @@ static inline void* gc_allocate_small_fast_freelist(struct gc_mutator *mut, size
*freelist_loc = *(void**)head;
gc_update_alloc_table(gc_ref_from_heap_object(head), size);
gc_update_alloc_table(gc_ref_from_heap_object(head), size, kind);
return head;
}
static inline void* gc_allocate_small_fast(struct gc_mutator *mut, size_t size) GC_ALWAYS_INLINE;
static inline void* gc_allocate_small_fast(struct gc_mutator *mut, size_t size) {
static inline void* gc_allocate_small_fast(struct gc_mutator *mut, size_t size,
enum gc_allocation_kind kind) GC_ALWAYS_INLINE;
static inline void* gc_allocate_small_fast(struct gc_mutator *mut, size_t size,
enum gc_allocation_kind kind) {
GC_ASSERT(size != 0);
GC_ASSERT(size <= gc_allocator_large_threshold());
switch (gc_allocator_kind()) {
case GC_ALLOCATOR_INLINE_BUMP_POINTER:
return gc_allocate_small_fast_bump_pointer(mut, size);
return gc_allocate_small_fast_bump_pointer(mut, size, kind);
case GC_ALLOCATOR_INLINE_FREELIST:
return gc_allocate_small_fast_freelist(mut, size);
return gc_allocate_small_fast_freelist(mut, size, kind);
case GC_ALLOCATOR_INLINE_NONE:
return NULL;
default:
@ -153,27 +163,28 @@ static inline void* gc_allocate_small_fast(struct gc_mutator *mut, size_t size)
}
}
static inline void* gc_allocate_fast(struct gc_mutator *mut, size_t size) GC_ALWAYS_INLINE;
static inline void* gc_allocate_fast(struct gc_mutator *mut, size_t size) {
static inline void* gc_allocate_fast(struct gc_mutator *mut, size_t size,
enum gc_allocation_kind kind) GC_ALWAYS_INLINE;
static inline void* gc_allocate_fast(struct gc_mutator *mut, size_t size,
enum gc_allocation_kind kind) {
GC_ASSERT(size != 0);
if (size > gc_allocator_large_threshold())
return NULL;
return gc_allocate_small_fast(mut, size);
return gc_allocate_small_fast(mut, size, kind);
}
static inline void* gc_allocate(struct gc_mutator *mut, size_t size) GC_ALWAYS_INLINE;
static inline void* gc_allocate(struct gc_mutator *mut, size_t size) {
void *ret = gc_allocate_fast(mut, size);
static inline void* gc_allocate(struct gc_mutator *mut, size_t size,
enum gc_allocation_kind kind) GC_ALWAYS_INLINE;
static inline void* gc_allocate(struct gc_mutator *mut, size_t size,
enum gc_allocation_kind kind) {
void *ret = gc_allocate_fast(mut, size, kind);
if (GC_LIKELY(ret != NULL))
return ret;
return gc_allocate_slow(mut, size);
return gc_allocate_slow(mut, size, kind);
}
// FIXME: remove :P
GC_API_ void* gc_allocate_pointerless(struct gc_mutator *mut, size_t bytes);
GC_API_ int gc_object_is_old_generation_slow(struct gc_mutator *mut,
struct gc_ref obj) GC_NEVER_INLINE;

View file

@ -2,6 +2,7 @@
#define GC_ATTRS_H
#include "gc-inline.h"
#include "gc-allocation-kind.h"
#include <stddef.h>
#include <stdint.h>
@ -19,10 +20,11 @@ static inline size_t gc_allocator_small_granule_size(void) GC_ALWAYS_INLINE;
static inline size_t gc_allocator_allocation_pointer_offset(void) GC_ALWAYS_INLINE;
static inline size_t gc_allocator_allocation_limit_offset(void) GC_ALWAYS_INLINE;
static inline size_t gc_allocator_freelist_offset(size_t size) GC_ALWAYS_INLINE;
static inline size_t gc_allocator_freelist_offset(size_t size,
enum gc_allocation_kind kind) GC_ALWAYS_INLINE;
static inline size_t gc_allocator_alloc_table_alignment(void) GC_ALWAYS_INLINE;
static inline uint8_t gc_allocator_alloc_table_begin_pattern(void) GC_ALWAYS_INLINE;
static inline uint8_t gc_allocator_alloc_table_begin_pattern(enum gc_allocation_kind kind) GC_ALWAYS_INLINE;
static inline uint8_t gc_allocator_alloc_table_end_pattern(void) GC_ALWAYS_INLINE;
enum gc_old_generation_check_kind {

View file

@ -22,14 +22,15 @@ static inline size_t gc_allocator_allocation_limit_offset(void) {
return sizeof(uintptr_t) * 1;
}
static inline size_t gc_allocator_freelist_offset(size_t size) {
static inline size_t gc_allocator_freelist_offset(size_t size,
enum gc_allocation_kind kind) {
GC_CRASH();
}
static inline size_t gc_allocator_alloc_table_alignment(void) {
return 4 * 1024 * 1024;
}
static inline uint8_t gc_allocator_alloc_table_begin_pattern(void) {
static inline uint8_t gc_allocator_alloc_table_begin_pattern(enum gc_allocation_kind kind) {
return 1;
}
static inline uint8_t gc_allocator_alloc_table_end_pattern(void) {

View file

@ -25,14 +25,14 @@ static inline size_t gc_allocator_allocation_limit_offset(void) {
return sizeof(uintptr_t) * 1;
}
static inline size_t gc_allocator_freelist_offset(size_t size) {
static inline size_t gc_allocator_freelist_offset(size_t size, enum gc_allocation_kind kind) {
GC_CRASH();
}
static inline size_t gc_allocator_alloc_table_alignment(void) {
return 0;
}
static inline uint8_t gc_allocator_alloc_table_begin_pattern(void) {
static inline uint8_t gc_allocator_alloc_table_begin_pattern(enum gc_allocation_kind kind) {
GC_CRASH();
}
static inline uint8_t gc_allocator_alloc_table_end_pattern(void) {

View file

@ -24,14 +24,15 @@ static inline size_t gc_allocator_allocation_limit_offset(void) {
return sizeof(uintptr_t) * 1;
}
static inline size_t gc_allocator_freelist_offset(size_t size) {
static inline size_t gc_allocator_freelist_offset(size_t size,
enum gc_allocation_kind kind) {
GC_CRASH();
}
static inline size_t gc_allocator_alloc_table_alignment(void) {
return 0;
}
static inline uint8_t gc_allocator_alloc_table_begin_pattern(void) {
static inline uint8_t gc_allocator_alloc_table_begin_pattern(enum gc_allocation_kind kind) {
GC_CRASH();
}
static inline uint8_t gc_allocator_alloc_table_end_pattern(void) {