wip messing around with adding jai flavored hash/key table.
This commit is contained in:
@@ -172,6 +172,6 @@ when ODIN_DEBUG {
|
||||
farena_allocator :: #force_inline proc "contextless" (arena: ^FArena) -> Odin_Allocator { return transmute(Odin_Allocator) AllocatorInfo{proc_id = .FArena, data = arena} }
|
||||
}
|
||||
else {
|
||||
farena_ainfo :: #force_inline proc "contextless" (arena: ^FArena) -> AllocatorInfo { return AllocatorInfo{procedure = farena_allocator_proc, data = arena} }
|
||||
farena_allocator :: #force_inline proc "contextless" (arena: ^FArena) -> Odin_Allocator { return transmute(Odin_Allocator) AllocatorInfo{procedure = farena_odin_allocator_proc, data = arena} }
|
||||
farena_ainfo :: #force_inline proc "contextless" (arena: ^FArena) -> AllocatorInfo { return AllocatorInfo{procedure = farena_allocator_proc, data = arena} }
|
||||
farena_allocator :: #force_inline proc "contextless" (arena: ^FArena) -> Odin_Allocator { return transmute(Odin_Allocator) AllocatorInfo{procedure = farena_allocator_proc, data = arena} }
|
||||
}
|
||||
|
141
code2/grime/key_table.odin
Normal file
141
code2/grime/key_table.odin
Normal file
@@ -0,0 +1,141 @@
|
||||
package grime
|
||||
|
||||
/*
|
||||
Hassh Table based on John's Jai & Sean Barrett's
|
||||
I don't like the table definition cntaining
|
||||
the allocator, hash or compare procedure to be used.
|
||||
So it has been stripped and instead applied on procedure site,
|
||||
the parent container or is responsible for tracking that.
|
||||
|
||||
TODO(Ed): Resolve appropriate Key-Table term for it.
|
||||
*/
|
||||
|
||||
KT_Slot :: struct(
|
||||
$TypeHash: typeid,
|
||||
$TypeKey: typeid,
|
||||
$TypeValue: typeid
|
||||
) {
|
||||
hash: TypeHash,
|
||||
key: TypeKey,
|
||||
value: TypeValue,
|
||||
}
|
||||
|
||||
KT :: struct($KT_Slot: typeid) {
|
||||
load_factor_perent: int,
|
||||
count: int,
|
||||
allocated: int,
|
||||
slots_filled: int,
|
||||
slots: []KT_Slot,
|
||||
}
|
||||
|
||||
KT_Info :: struct {
|
||||
key_width: int,
|
||||
value_width: int,
|
||||
slot_width: int,
|
||||
}
|
||||
|
||||
KT_Opaque :: struct {
|
||||
count: int,
|
||||
allocated: int,
|
||||
slots_filled: int,
|
||||
slots: []byte,
|
||||
}
|
||||
|
||||
KT_ByteMeta :: struct {
|
||||
hash_width: int,
|
||||
value_width: int,
|
||||
}
|
||||
|
||||
KT_COUNT_COLLISIONS :: #config(KT_COUNT_COLLISIONS, false)
|
||||
|
||||
KT_HASH_NEVER_OCCUPIED :: 0
|
||||
KT_HASH_REMOVED :: 1
|
||||
KT_HASH_FIRST_VALID :: 2
|
||||
KT_LOAD_FACTOR_PERCENT :: 70
|
||||
|
||||
kt_byte_init :: proc(info: KT_Info, tbl_allocator: Odin_Allocator, kt: ^KT_Opaque, $HashType: typeid)
|
||||
{
|
||||
#assert(size_of(HashType) >= 32)
|
||||
assert(tbl_allocator.procedure != nil)
|
||||
assert(info.value_width >= 32)
|
||||
assert(info.slot_width >= 64)
|
||||
}
|
||||
kt_deinit :: proc(table: ^$KT / typeid, allocator: Odin_Allocator)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
kt_walk_table_body_proc :: #type proc($TypeHash: typeid, hash: TypeHash, kt: ^KT_Opaque, info: KT_Info, id: TypeHash) -> (should_break: bool)
|
||||
kt_walk_table :: proc($TypeHash: typeid, hash: TypeHash, kt: ^KT_Opaque, info: KT_Info, $walk_body: kt_walk_table_body_proc) -> (index: TypeHash)
|
||||
{
|
||||
mask := cast(TypeHash)(kt.allocated - 1) // Cast may truncate
|
||||
if hash < KT_HASH_FIRST_VALID do hash += KT_HASH_FIRST_VALID
|
||||
index : TypeHash = hash & mask
|
||||
probe_increment: TypeHash = 1
|
||||
for id := transmute(TypeHash) kt.slots[info.slot_width * index:]; id != 0;
|
||||
{
|
||||
if #force_inline walk_body(hash, kt, info, id) do break
|
||||
index = (index + probe_increment) & mask
|
||||
probe_increment += 1
|
||||
}
|
||||
}
|
||||
|
||||
// Will not expand table if capacity reached, user must do that check beforehand.
|
||||
// Will return existing if hash found
|
||||
kt_byte_add :: proc(value: [^]byte, key: [^]byte, hash: $TypeHash, kt: ^KT_Opaque, info: KT_Info)-> [^]byte
|
||||
{
|
||||
aasert(kt.slots_filled, kt.allocated)
|
||||
index := #force_inline kt_walk_table(hash, kt, info,
|
||||
proc(hash: $TypeHash, kt: ^KT_Opaque, info: KT_Info, id: TypeHash) -> (should_break: bool)
|
||||
{
|
||||
if id == KT_HASH_REMOVED {
|
||||
kt.slots_filled -= 1
|
||||
should_break = true
|
||||
return
|
||||
}
|
||||
//TODO(Ed): Add collision tracking
|
||||
return
|
||||
})
|
||||
kt.count += 1
|
||||
kt.slots_filled += 1
|
||||
slot_offset := info.slot_width * index
|
||||
entry := table.slots[info.slot_width * index:]
|
||||
mem_copy_non_overlapping(entry, hash, size_of(TypeHash))
|
||||
mem_copy_non_overlapping(entry[size_of(hash):], key, info.key_width)
|
||||
mem_copy_non_overlapping(entry[size_of(hash) + size_of(key):], value, info.value_width)
|
||||
return entry
|
||||
}
|
||||
|
||||
// Will not expand table if capacity reached, user must do that check beforehand.
|
||||
// Will override if hash exists
|
||||
kt_byte_set :: proc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
kt_remove :: proc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
kt_byte_contains :: proc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
kt_byte_find_pointer :: proc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
kt_find :: proc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
kt_find_multiple :: proc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
kt_next_power_of_two :: #force_inline proc(x: int) -> int { power := 1; for ;x > power; do power += power; return power }
|
@@ -9,9 +9,9 @@ KT1L_Slot :: struct($Type: typeid) {
|
||||
value: Type,
|
||||
}
|
||||
KT1L_Meta :: struct {
|
||||
slot_size: uintptr,
|
||||
kt_value_offset: uintptr,
|
||||
type_width: uintptr,
|
||||
slot_size: int,
|
||||
kt_value_offset: int,
|
||||
type_width: int,
|
||||
type: typeid,
|
||||
}
|
||||
kt1l_populate_slice_a2_Slice_Byte :: proc(kt: ^[]byte, backing: AllocatorInfo, values: []byte, num_values: int, m: KT1L_Meta) {
|
||||
@@ -21,7 +21,7 @@ kt1l_populate_slice_a2_Slice_Byte :: proc(kt: ^[]byte, backing: AllocatorInfo, v
|
||||
kt^, _ = mem_alloc(table_size_bytes, ainfo = transmute(Odin_Allocator) backing)
|
||||
slice_assert(kt ^)
|
||||
kt_raw : SliceByte = transmute(SliceByte) kt^
|
||||
for id in 0 ..< cast(uintptr) num_values {
|
||||
for id in 0 ..< num_values {
|
||||
slot_offset := id * m.slot_size // slot id
|
||||
slot_cursor := kt_raw.data[slot_offset:] // slots[id] type: KT1L_<Type>
|
||||
// slot_key := transmute(^u64) slot_cursor // slots[id].key type: U64
|
||||
@@ -30,7 +30,7 @@ kt1l_populate_slice_a2_Slice_Byte :: proc(kt: ^[]byte, backing: AllocatorInfo, v
|
||||
a2_cursor := cursor(values)[a2_offset:] // a2_entries[id] type: A2_<Type>
|
||||
// a2_key := (transmute(^[]byte) a2_cursor) ^ // a2_entries[id].key type: <Type>
|
||||
// a2_value := slice(a2_cursor[m.type_width:], m.type_width) // a2_entries[id].value type: <Type>
|
||||
mem_copy_non_overlapping(slot_cursor[m.kt_value_offset:], a2_cursor[m.type_width:], cast(int) m.type_width) // slots[id].value = a2_entries[id].value
|
||||
mem_copy_non_overlapping(slot_cursor[m.kt_value_offset:], a2_cursor[m.type_width:], m.type_width) // slots[id].value = a2_entries[id].value
|
||||
(transmute([^]u64) slot_cursor)[0] = 0;
|
||||
hash64_djb8(transmute(^u64) slot_cursor, (transmute(^[]byte) a2_cursor) ^) // slots[id].key = hash64_djb8(a2_entries[id].key)
|
||||
}
|
||||
|
28
code2/grime/string_cache.odin
Normal file
28
code2/grime/string_cache.odin
Normal file
@@ -0,0 +1,28 @@
|
||||
package grime
|
||||
|
||||
StrKey_U4 :: struct {
|
||||
len: u32, // Length of string
|
||||
offset: u32, // Offset in varena
|
||||
}
|
||||
|
||||
StrKT_U4_Cell_Depth :: 4
|
||||
|
||||
StrKT_U4_Slot :: KT1CX_Slot(StrKey_U4)
|
||||
StrKT_U4_Cell :: KT1CX_Cell(StrKT_U4_Slot, 4)
|
||||
StrKT_U4_Table :: KT1CX(StrKT_U4_Cell)
|
||||
|
||||
VStrKT_U4 :: struct {
|
||||
varena: VArena, // Backed by growing vmem
|
||||
entries: StrKT_U4_Table
|
||||
}
|
||||
|
||||
vstrkt_u4_init :: proc(varena: ^VArena) -> (cache: ^VStrKT_U4)
|
||||
{
|
||||
return nil
|
||||
}
|
||||
|
||||
vstrkt_u4_intern :: proc(cache: ^VStrKT_U4) -> StrKey_U4
|
||||
{
|
||||
// profile(#procedure)
|
||||
return {}
|
||||
}
|
@@ -292,6 +292,6 @@ when ODIN_DEBUG {
|
||||
varena_allocator :: #force_inline proc "contextless" (arena: ^VArena) -> Odin_Allocator { return transmute(Odin_Allocator) AllocatorInfo{proc_id = .VArena, data = arena} }
|
||||
}
|
||||
else {
|
||||
varena_ainfo :: #force_inline proc "contextless" (arena: ^VArena) -> AllocatorInfo { return AllocatorInfo{procedure = varena_allocator_proc, data = arena} }
|
||||
varena_allocator :: #force_inline proc "contextless" (arena: ^VArena) -> Odin_Allocator { return transmute(Odin_Allocator) AllocatorInfo{procedure = varena_odin_allocator_proc, data = arena} }
|
||||
varena_ainfo :: #force_inline proc "contextless" (arena: ^VArena) -> AllocatorInfo { return AllocatorInfo{procedure = varena_allocator_proc, data = arena} }
|
||||
varena_allocator :: #force_inline proc "contextless" (arena: ^VArena) -> Odin_Allocator { return transmute(Odin_Allocator) AllocatorInfo{procedure = varena_allocator_proc, data = arena} }
|
||||
}
|
||||
|
@@ -23,14 +23,14 @@ load_client_api :: proc(version_id: int) -> (loaded_module: Client_API) {
|
||||
file_copy_sync( Path_Sectr_Module, Path_Sectr_Live_Module, allocator = context.temp_allocator )
|
||||
did_load: bool; lib, did_load = os_lib_load( Path_Sectr_Live_Module )
|
||||
if ! did_load do panic( "Failed to load the sectr module.")
|
||||
startup = cast( type_of( host_memory.client_api.startup)) os_lib_get_proc(lib, "startup")
|
||||
shutdown = cast( type_of( host_memory.client_api.shutdown)) os_lib_get_proc(lib, "sectr_shutdown")
|
||||
tick_lane_startup = cast( type_of( host_memory.client_api.tick_lane_startup)) os_lib_get_proc(lib, "tick_lane_startup")
|
||||
job_worker_startup = cast( type_of( host_memory.client_api.job_worker_startup)) os_lib_get_proc(lib, "job_worker_startup")
|
||||
hot_reload = cast( type_of( host_memory.client_api.hot_reload)) os_lib_get_proc(lib, "hot_reload")
|
||||
tick_lane = cast( type_of( host_memory.client_api.tick_lane)) os_lib_get_proc(lib, "tick_lane")
|
||||
clean_frame = cast( type_of( host_memory.client_api.clean_frame)) os_lib_get_proc(lib, "clean_frame")
|
||||
jobsys_worker_tick = cast( type_of( host_memory.client_api.jobsys_worker_tick)) os_lib_get_proc(lib, "jobsys_worker_tick")
|
||||
startup = transmute( type_of( host_memory.client_api.startup)) os_lib_get_proc(lib, "startup")
|
||||
shutdown = transmute( type_of( host_memory.client_api.shutdown)) os_lib_get_proc(lib, "sectr_shutdown")
|
||||
tick_lane_startup = transmute( type_of( host_memory.client_api.tick_lane_startup)) os_lib_get_proc(lib, "tick_lane_startup")
|
||||
job_worker_startup = transmute( type_of( host_memory.client_api.job_worker_startup)) os_lib_get_proc(lib, "job_worker_startup")
|
||||
hot_reload = transmute( type_of( host_memory.client_api.hot_reload)) os_lib_get_proc(lib, "hot_reload")
|
||||
tick_lane = transmute( type_of( host_memory.client_api.tick_lane)) os_lib_get_proc(lib, "tick_lane")
|
||||
clean_frame = transmute( type_of( host_memory.client_api.clean_frame)) os_lib_get_proc(lib, "clean_frame")
|
||||
jobsys_worker_tick = transmute( type_of( host_memory.client_api.jobsys_worker_tick)) os_lib_get_proc(lib, "jobsys_worker_tick")
|
||||
if startup == nil do panic("Failed to load sectr.startup symbol" )
|
||||
if shutdown == nil do panic("Failed to load sectr.shutdown symbol" )
|
||||
if tick_lane_startup == nil do panic("Failed to load sectr.tick_lane_startup symbol" )
|
||||
|
0
config/sectr_config.mdesk
Normal file
0
config/sectr_config.mdesk
Normal file
@@ -216,8 +216,8 @@ push-location $path_root
|
||||
$build_args += $flag_microarch_zen5
|
||||
$build_args += $flag_use_separate_modules
|
||||
$build_args += $flag_thread_count + $CoreCount_Physical
|
||||
$build_args += $flag_optimize_none
|
||||
# $build_args += $flag_optimize_minimal
|
||||
# $build_args += $flag_optimize_none
|
||||
$build_args += $flag_optimize_minimal
|
||||
# $build_args += $flag_optimize_speed
|
||||
# $build_args += $falg_optimize_aggressive
|
||||
$build_args += $flag_debug
|
||||
|
Reference in New Issue
Block a user