diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index b03880bd..ab61ce07 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -609,7 +609,7 @@ dasm_parse_thread__entry_point(void *p) { // TODO(rjf): need redirection path - this may map to a different path on the local machine, // need frontend to communicate path remapping info to this layer - U128 key = fs_key_from_path(file_normalized_full_path); + U128 key = fs_key_from_path_range(file_normalized_full_path, r1u64(0, max_U64)); TXT_LangKind lang_kind = txt_lang_kind_from_extension(file_normalized_full_path); U64 endt_us = max_U64; U128 hash = {0}; diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 81636358..51c1bf36 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3905,6 +3905,48 @@ df_eval_space_write(void *u, E_Space space, void *in, Rng1U64 range) return result; } +internal Rng1U64 +df_range_from_eval_cfg(E_Eval eval, DF_CfgNode *cfg) +{ + Temp scratch = scratch_begin(0, 0); + E_Eval value_eval = e_value_eval_from_eval(eval); + DF_CfgNode *size_cfg = df_cfg_node_child_from_string(cfg, str8_lit("size"), 0); + String8 size_expr = df_string_from_cfg_node_children(scratch.arena, size_cfg); + E_Eval size_eval = e_eval_from_string(scratch.arena, size_expr); + E_Eval size_value_eval = e_value_eval_from_eval(size_eval); + Rng1U64 result = {0}; + result.min = value_eval.value.u64; + result.max = max_U64; + if(size_eval.msgs.max_kind == E_MsgKind_Null) + { + result.max = result.min + size_value_eval.value.u64; + } + scratch_end(scratch); + return result; +} + +internal U128 +df_key_from_eval_space_range(E_Space space, Rng1U64 range) +{ + U128 result = {0}; + DF_Entity *entity = df_entity_from_eval_space(space); + switch(entity->kind) + { + //- rjf: nil space -> filesystem key encoded inside of `space` + case DF_EntityKind_Nil: + { + result = space; + }break; + + //- rjf: process space -> query + case DF_EntityKind_Process: + { + result = ctrl_hash_store_key_from_process_vaddr_range(entity->ctrl_machine_id, entity->ctrl_handle, range, 0); + }break; + } + return result; +} + internal E_Eval df_eval_from_eval_cfg_table(Arena *arena, E_Eval eval, DF_CfgTable *cfg) { diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index 14bb8405..2f86711b 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -1577,6 +1577,8 @@ internal DF_Entity *df_entity_from_eval_space(E_Space space); internal E_Space df_eval_space_from_entity(DF_Entity *entity); internal B32 df_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range); internal B32 df_eval_space_write(void *u, E_Space space, void *in, Rng1U64 range); +internal Rng1U64 df_range_from_eval_cfg(E_Eval eval, DF_CfgNode *cfg); +internal U128 df_key_from_eval_space_range(E_Space space, Rng1U64 range); internal E_Eval df_eval_from_eval_cfg_table(Arena *arena, E_Eval eval, DF_CfgTable *cfg); //////////////////////////////// diff --git a/src/df/gfx/df_view_rules.c b/src/df/gfx/df_view_rules.c index acfe15c3..234ac504 100644 --- a/src/df/gfx/df_view_rules.c +++ b/src/df/gfx/df_view_rules.c @@ -662,20 +662,10 @@ df_vr_txt_topology_info_from_cfg(DF_CfgNode *cfg) { StringJoin join = {0}; join.sep = str8_lit(" "); - DF_CfgNode *size_cfg = df_cfg_node_child_from_string(cfg, str8_lit("size"), 0); DF_CfgNode *lang_cfg = df_cfg_node_child_from_string(cfg, str8_lit("lang"), 0); - String8List size_expr_strs = {0}; String8 lang_string = {0}; - for(DF_CfgNode *child = size_cfg->first; child != &df_g_nil_cfg_node; child = child->next) - { - str8_list_push(scratch.arena, &size_expr_strs, child->string); - } lang_string = lang_cfg->first->string; - String8 size_expr = str8_list_join(scratch.arena, &size_expr_strs, &join); - E_Eval size_eval = e_eval_from_string(scratch.arena, size_expr); - E_Eval size_val_eval = e_value_eval_from_eval(size_eval); result.lang = txt_lang_kind_from_extension(lang_string); - result.size_cap = size_val_eval.value.u64; } scratch_end(scratch); return result; @@ -711,12 +701,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text) ////////////////////////////// //- rjf: unpack evaluation / view rule params // - DF_Entity *thread = df_entity_from_handle(df_interact_regs()->thread); - DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); + Rng1U64 range = df_range_from_eval_cfg(eval, cfg); DF_TxtTopologyInfo top = df_vr_txt_topology_info_from_cfg(cfg); - E_Eval value_eval = e_value_eval_from_eval(eval); - U64 base_vaddr = value_eval.value.u64; - Rng1U64 vaddr_range = r1u64(base_vaddr, base_vaddr + (top.size_cap ? top.size_cap : 2048)); ////////////////////////////// //- rjf: evaluation info -> text visualization info @@ -724,10 +710,9 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text) String8 data = {0}; TXT_TextInfo info = {0}; TXT_LineTokensSlice line_tokens_slice = {0}; - U128 text_key = {0}; + U128 text_key = df_key_from_eval_space_range(eval.space, range); { U128 text_hash = {0}; - text_key = ctrl_hash_store_key_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 1); info = txt_text_info_from_key_lang(txt_scope, text_key, top.lang, &text_hash); data = hs_data_from_hash(hs_scope, text_hash); line_tokens_slice = txt_line_tokens_slice_from_info_data_line_range(scratch.arena, &info, data, r1s64(1, info.lines_count)); diff --git a/src/df/gfx/df_view_rules.h b/src/df/gfx/df_view_rules.h index 1e9b2d99..b90ef704 100644 --- a/src/df/gfx/df_view_rules.h +++ b/src/df/gfx/df_view_rules.h @@ -24,7 +24,6 @@ typedef struct DF_TxtTopologyInfo DF_TxtTopologyInfo; struct DF_TxtTopologyInfo { TXT_LangKind lang; - U64 size_cap; }; typedef struct DF_VR_TextState DF_VR_TextState; diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index b3b78076..af2f05fe 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -6448,7 +6448,7 @@ DF_VIEW_CMD_FUNCTION_DEF(Code) HS_Scope *hs_scope = hs_scope_open(); TXT_Scope *txt_scope = txt_scope_open(); String8 path = df_interact_regs()->file_path; - df_interact_regs()->text_key = fs_key_from_path(path); + df_interact_regs()->text_key = fs_key_from_path_range(path, r1u64(0, max_U64)); df_interact_regs()->lang_kind = txt_lang_kind_from_extension(str8_skip_last_dot(path)); U128 hash = {0}; TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, df_interact_regs()->text_key, df_interact_regs()->lang_kind, &hash); @@ -6519,7 +6519,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code) //- rjf: unpack entity info // String8 path = df_interact_regs()->file_path; - df_interact_regs()->text_key = fs_key_from_path(path); + df_interact_regs()->text_key = fs_key_from_path_range(path, r1u64(0, max_U64)); df_interact_regs()->lang_kind = txt_lang_kind_from_extension(str8_skip_last_dot(path)); U128 hash = {0}; TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, df_interact_regs()->text_key, df_interact_regs()->lang_kind, &hash); diff --git a/src/eval/eval_interpret.c b/src/eval/eval_interpret.c index 6089b949..4970baef 100644 --- a/src/eval/eval_interpret.c +++ b/src/eval/eval_interpret.c @@ -84,7 +84,7 @@ e_interpret(String8 bytecode) ptr += 1; // rjf: decode - U64 imm = 0; + E_Value imm = {0}; { U32 decode_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); U8 *next_ptr = ptr + decode_size; @@ -95,13 +95,7 @@ e_interpret(String8 bytecode) } // TODO(rjf): guarantee 8 bytes padding after the end of serialized // bytecode; read 8 bytes and mask - switch(decode_size) - { - case 1:{imm = *ptr;}break; - case 2:{imm = *(U16*)ptr;}break; - case 4:{imm = *(U32*)ptr;}break; - case 8:{imm = *(U64*)ptr;}break; - } + MemoryCopy(&imm, ptr, decode_size); ptr = next_ptr; } @@ -127,7 +121,7 @@ e_interpret(String8 bytecode) { case E_IRExtKind_SetSpace: { - MemoryCopy(&selected_space, ptr, sizeof(E_Space)); + selected_space = imm.u128; }break; case RDI_EvalOp_Stop: @@ -143,18 +137,18 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Cond: if(svals[0].u64) { - ptr += imm; + ptr += imm.u64; }break; case RDI_EvalOp_Skip: { - ptr += imm; + ptr += imm.u64; }break; case RDI_EvalOp_MemRead: { U64 addr = svals[0].u64; - U64 size = imm; + U64 size = imm.u64; B32 good_read = e_space_read(selected_space, &nval, r1u64(addr, addr+size)); if(!good_read) { @@ -165,9 +159,9 @@ e_interpret(String8 bytecode) case RDI_EvalOp_RegRead: { - U8 rdi_reg_code = (imm&0x0000FF)>>0; - U8 byte_size = (imm&0x00FF00)>>8; - U8 byte_off = (imm&0xFF0000)>>16; + U8 rdi_reg_code = (imm.u64&0x0000FF)>>0; + U8 byte_size = (imm.u64&0x00FF00)>>8; + U8 byte_off = (imm.u64&0xFF0000)>>16; REGS_RegCode base_reg_code = regs_reg_code_from_arch_rdi_code(e_interpret_ctx->reg_arch, rdi_reg_code); REGS_Rng rng = regs_reg_code_rng_table_from_architecture(e_interpret_ctx->reg_arch)[base_reg_code]; U64 off = (U64)rng.byte_off + byte_off; @@ -196,7 +190,7 @@ e_interpret(String8 bytecode) { if(e_interpret_ctx->frame_base != 0) { - nval.u64 = *e_interpret_ctx->frame_base + imm; + nval.u64 = *e_interpret_ctx->frame_base + imm.u64; } else { @@ -209,7 +203,7 @@ e_interpret(String8 bytecode) { if(e_interpret_ctx->module_base != 0) { - nval.u64 = *e_interpret_ctx->module_base + imm; + nval.u64 = *e_interpret_ctx->module_base + imm.u64; } else { @@ -222,7 +216,7 @@ e_interpret(String8 bytecode) { if(e_interpret_ctx->tls_base != 0) { - nval.u64 = *e_interpret_ctx->tls_base + imm; + nval.u64 = *e_interpret_ctx->tls_base + imm.u64; } else { @@ -235,24 +229,20 @@ e_interpret(String8 bytecode) case RDI_EvalOp_ConstU16: case RDI_EvalOp_ConstU32: case RDI_EvalOp_ConstU64: - { - nval.u64 = imm; - }break; - case RDI_EvalOp_ConstU128: { - MemoryCopy(&nval, ptr, 16); + nval = imm; }break; case RDI_EvalOp_ConstString: { - MemoryCopy(&nval, ptr, imm); - ptr += imm; + MemoryCopy(&nval, ptr, imm.u64); + ptr += imm.u64; }break; case RDI_EvalOp_Abs: { - if(imm == RDI_EvalTypeGroup_F32) + if(imm.u64 == RDI_EvalTypeGroup_F32) { nval.f32 = svals[0].f32; if(svals[0].f32 < 0) @@ -260,7 +250,7 @@ e_interpret(String8 bytecode) nval.f32 = -svals[0].f32; } } - else if(imm == RDI_EvalTypeGroup_F64) + else if(imm.u64 == RDI_EvalTypeGroup_F64) { nval.f64 = svals[0].f64; if(svals[0].f64 < 0) @@ -280,11 +270,11 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Neg: { - if(imm == RDI_EvalTypeGroup_F32) + if(imm.u64 == RDI_EvalTypeGroup_F32) { nval.f32 = -svals[0].f32; } - else if(imm == RDI_EvalTypeGroup_F64) + else if(imm.u64 == RDI_EvalTypeGroup_F64) { nval.f64 = -svals[0].f64; } @@ -296,11 +286,11 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Add: { - if(imm == RDI_EvalTypeGroup_F32) + if(imm.u64 == RDI_EvalTypeGroup_F32) { nval.f32 = svals[0].f32 + svals[1].f32; } - else if(imm == RDI_EvalTypeGroup_F64) + else if(imm.u64 == RDI_EvalTypeGroup_F64) { nval.f64 = svals[0].f64 + svals[1].f64; } @@ -312,11 +302,11 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Sub: { - if(imm == RDI_EvalTypeGroup_F32) + if(imm.u64 == RDI_EvalTypeGroup_F32) { nval.f32 = svals[0].f32 - svals[1].f32; } - else if(imm == RDI_EvalTypeGroup_F64) + else if(imm.u64 == RDI_EvalTypeGroup_F64) { nval.f64 = svals[0].f64 - svals[1].f64; } @@ -328,11 +318,11 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Mul: { - if(imm == RDI_EvalTypeGroup_F32) + if(imm.u64 == RDI_EvalTypeGroup_F32) { nval.f32 = svals[0].f32*svals[1].f32; } - else if(imm == RDI_EvalTypeGroup_F64) + else if(imm.u64 == RDI_EvalTypeGroup_F64) { nval.f64 = svals[0].f64*svals[1].f64; } @@ -344,7 +334,7 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Div: { - if(imm == RDI_EvalTypeGroup_F32) + if(imm.u64 == RDI_EvalTypeGroup_F32) { if(svals[1].f32 != 0.f) { @@ -356,7 +346,7 @@ e_interpret(String8 bytecode) goto done; } } - else if(imm == RDI_EvalTypeGroup_F64) + else if(imm.u64 == RDI_EvalTypeGroup_F64) { if(svals[1].f64 != 0.) { @@ -368,8 +358,8 @@ e_interpret(String8 bytecode) goto done; } } - else if(imm == RDI_EvalTypeGroup_U || - imm == RDI_EvalTypeGroup_S) + else if(imm.u64 == RDI_EvalTypeGroup_U || + imm.u64 == RDI_EvalTypeGroup_S) { if(svals[1].u64 != 0) { @@ -390,8 +380,8 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Mod: { - if(imm == RDI_EvalTypeGroup_U || - imm == RDI_EvalTypeGroup_S) + if(imm.u64 == RDI_EvalTypeGroup_U || + imm.u64 == RDI_EvalTypeGroup_S) { if(svals[1].u64 != 0) { @@ -407,8 +397,8 @@ e_interpret(String8 bytecode) case RDI_EvalOp_LShift: { - if(imm == RDI_EvalTypeGroup_U || - imm == RDI_EvalTypeGroup_S) + if(imm.u64 == RDI_EvalTypeGroup_U || + imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = svals[0].u64 << svals[1].u64; } @@ -421,11 +411,11 @@ e_interpret(String8 bytecode) case RDI_EvalOp_RShift: { - if(imm == RDI_EvalTypeGroup_U) + if(imm.u64 == RDI_EvalTypeGroup_U) { nval.u64 = svals[0].u64 >> svals[1].u64; } - else if(imm == RDI_EvalTypeGroup_S) + else if(imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = svals[0].s64 >> svals[1].u64; } @@ -438,8 +428,8 @@ e_interpret(String8 bytecode) case RDI_EvalOp_BitAnd: { - if(imm == RDI_EvalTypeGroup_U || - imm == RDI_EvalTypeGroup_S) + if(imm.u64 == RDI_EvalTypeGroup_U || + imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = svals[0].u64&svals[1].u64; } @@ -452,8 +442,8 @@ e_interpret(String8 bytecode) case RDI_EvalOp_BitOr: { - if(imm == RDI_EvalTypeGroup_U || - imm == RDI_EvalTypeGroup_S) + if(imm.u64 == RDI_EvalTypeGroup_U || + imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = svals[0].u64|svals[1].u64; } @@ -466,8 +456,8 @@ e_interpret(String8 bytecode) case RDI_EvalOp_BitXor: { - if(imm == RDI_EvalTypeGroup_U || - imm == RDI_EvalTypeGroup_S) + if(imm.u64 == RDI_EvalTypeGroup_U || + imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = svals[0].u64^svals[1].u64; } @@ -480,8 +470,8 @@ e_interpret(String8 bytecode) case RDI_EvalOp_BitNot: { - if(imm == RDI_EvalTypeGroup_U || - imm == RDI_EvalTypeGroup_S) + if(imm.u64 == RDI_EvalTypeGroup_U || + imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = ~svals[0].u64; } @@ -494,8 +484,8 @@ e_interpret(String8 bytecode) case RDI_EvalOp_LogAnd: { - if(imm == RDI_EvalTypeGroup_U || - imm == RDI_EvalTypeGroup_S) + if(imm.u64 == RDI_EvalTypeGroup_U || + imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].u64 && svals[1].u64); } @@ -508,8 +498,8 @@ e_interpret(String8 bytecode) case RDI_EvalOp_LogOr: { - if(imm == RDI_EvalTypeGroup_U || - imm == RDI_EvalTypeGroup_S) + if(imm.u64 == RDI_EvalTypeGroup_U || + imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].u64 || svals[1].u64); } @@ -522,8 +512,8 @@ e_interpret(String8 bytecode) case RDI_EvalOp_LogNot: { - if(imm == RDI_EvalTypeGroup_U || - imm == RDI_EvalTypeGroup_S) + if(imm.u64 == RDI_EvalTypeGroup_U || + imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = (!svals[0].u64); } @@ -548,19 +538,19 @@ e_interpret(String8 bytecode) case RDI_EvalOp_LsEq: { - if(imm == RDI_EvalTypeGroup_F32) + if(imm.u64 == RDI_EvalTypeGroup_F32) { nval.u64 = (svals[0].f32 <= svals[1].f32); } - else if(imm == RDI_EvalTypeGroup_F64) + else if(imm.u64 == RDI_EvalTypeGroup_F64) { nval.u64 = (svals[0].f64 <= svals[1].f64); } - else if(imm == RDI_EvalTypeGroup_U) + else if(imm.u64 == RDI_EvalTypeGroup_U) { nval.u64 = (svals[0].u64 <= svals[1].u64); } - else if(imm == RDI_EvalTypeGroup_S) + else if(imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].s64 <= svals[1].s64); } @@ -573,19 +563,19 @@ e_interpret(String8 bytecode) case RDI_EvalOp_GrEq: { - if(imm == RDI_EvalTypeGroup_F32) + if(imm.u64 == RDI_EvalTypeGroup_F32) { nval.u64 = (svals[0].f32 >= svals[1].f32); } - else if(imm == RDI_EvalTypeGroup_F64) + else if(imm.u64 == RDI_EvalTypeGroup_F64) { nval.u64 = (svals[0].f64 >= svals[1].f64); } - else if(imm == RDI_EvalTypeGroup_U) + else if(imm.u64 == RDI_EvalTypeGroup_U) { nval.u64 = (svals[0].u64 >= svals[1].u64); } - else if(imm == RDI_EvalTypeGroup_S) + else if(imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].s64 >= svals[1].s64); } @@ -598,19 +588,19 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Less: { - if(imm == RDI_EvalTypeGroup_F32) + if(imm.u64 == RDI_EvalTypeGroup_F32) { nval.u64 = (svals[0].f32 < svals[1].f32); } - else if(imm == RDI_EvalTypeGroup_F64) + else if(imm.u64 == RDI_EvalTypeGroup_F64) { nval.u64 = (svals[0].f64 < svals[1].f64); } - else if(imm == RDI_EvalTypeGroup_U) + else if(imm.u64 == RDI_EvalTypeGroup_U) { nval.u64 = (svals[0].u64 < svals[1].u64); } - else if(imm == RDI_EvalTypeGroup_S) + else if(imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].s64 < svals[1].s64); } @@ -623,19 +613,19 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Grtr: { - if(imm == RDI_EvalTypeGroup_F32) + if(imm.u64 == RDI_EvalTypeGroup_F32) { nval.u64 = (svals[0].f32 > svals[1].f32); } - else if(imm == RDI_EvalTypeGroup_F64) + else if(imm.u64 == RDI_EvalTypeGroup_F64) { nval.u64 = (svals[0].f64 > svals[1].f64); } - else if(imm == RDI_EvalTypeGroup_U) + else if(imm.u64 == RDI_EvalTypeGroup_U) { nval.u64 = (svals[0].u64 > svals[1].u64); } - else if(imm == RDI_EvalTypeGroup_S) + else if(imm.u64 == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].s64 > svals[1].s64); } @@ -648,12 +638,12 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Trunc: { - if(0 < imm) + if(0 < imm.u64) { U64 mask = 0; - if(imm < 64) + if(imm.u64 < 64) { - mask = max_U64 >> (64 - imm); + mask = max_U64 >> (64 - imm.u64); } nval.u64 = svals[0].u64&mask; } @@ -661,15 +651,15 @@ e_interpret(String8 bytecode) case RDI_EvalOp_TruncSigned: { - if(0 < imm) + if(0 < imm.u64) { U64 mask = 0; - if(imm < 64) + if(imm.u64 < 64) { - mask = max_U64 >> (64 - imm); + mask = max_U64 >> (64 - imm.u64); } U64 high = 0; - if(svals[0].u64 & (1 << (imm - 1))) + if(svals[0].u64 & (1 << (imm.u64 - 1))) { high = ~mask; } @@ -679,8 +669,8 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Convert: { - U32 in = imm&0xFF; - U32 out = (imm >> 8)&0xFF; + U32 in = imm.u64&0xFF; + U32 out = (imm.u64 >> 8)&0xFF; if(in != out) { switch(in + out*RDI_EvalTypeGroup_COUNT) @@ -734,9 +724,9 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Pick: { - if(stack_count > imm) + if(stack_count > imm.u64) { - nval = stack[stack_count - imm - 1]; + nval = stack[stack_count - imm.u64 - 1]; } else { @@ -752,14 +742,14 @@ e_interpret(String8 bytecode) case RDI_EvalOp_Insert: { - if(stack_count > imm) + if(stack_count > imm.u64) { - if(imm > 0) + if(imm.u64 > 0) { E_Value tval = stack[stack_count - 1]; - E_Value *dst = stack + stack_count - 1 - imm; + E_Value *dst = stack + stack_count - 1 - imm.u64; E_Value *shift = dst + 1; - MemoryCopy(shift, dst, imm*sizeof(E_Value)); + MemoryCopy(shift, dst, imm.u64*sizeof(E_Value)); *dst = tval; } } @@ -772,7 +762,7 @@ e_interpret(String8 bytecode) case RDI_EvalOp_ValueRead: { - U64 bytes_to_read = imm; + U64 bytes_to_read = imm.u64; U64 offset = svals[0].u64; if(offset + bytes_to_read <= sizeof(E_Value)) { diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index cc33b01a..b641bdd7 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -1231,7 +1231,7 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr) //- rjf: leaf file paths case E_ExprKind_LeafFilePath: { - U128 key = fs_key_from_path(expr->string); + U128 key = fs_key_from_path_range(expr->string, r1u64(0, max_U64)); U64 size = fs_size_from_path(expr->string); E_IRNode *base_offset = e_irtree_const_u(arena, 0); E_IRNode *set_space = e_irtree_set_space(arena, key, base_offset); @@ -1442,7 +1442,7 @@ e_bytecode_from_oplist(Arena *arena, E_OpList *oplist) // rjf: fill bytecode ptr[0] = opcode; - MemoryCopy(ptr + 1, &op->value.u64, extra_byte_count); + MemoryCopy(ptr + 1, &op->value.u128, extra_byte_count); // rjf: advance ptr = next_ptr; diff --git a/src/file_stream/file_stream.c b/src/file_stream/file_stream.c index f4d80975..229b7c45 100644 --- a/src/file_stream/file_stream.c +++ b/src/file_stream/file_stream.c @@ -1,6 +1,34 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) +//////////////////////////////// +//~ rjf: Basic Helpers + +internal U64 +fs_little_hash_from_string(String8 string) +{ + U64 result = 5381; + for(U64 i = 0; i < string.size; i += 1) + { + result = ((result << 5) + result) + string.str[i]; + } + return result; +} + +internal U128 +fs_big_hash_from_string_range(String8 string, Rng1U64 range) +{ + Temp scratch = scratch_begin(0, 0); + U64 buffer_size = string.size + sizeof(U64)*2; + U8 *buffer = push_array_no_zero(scratch.arena, U8, buffer_size); + MemoryCopy(buffer, string.str, string.size); + MemoryCopy(buffer + string.size, &range.min, sizeof(range.min)); + MemoryCopy(buffer + string.size + sizeof(range.min), &range.max, sizeof(range.max)); + U128 hash = hs_hash_from_data(str8(buffer, buffer_size)); + scratch_end(scratch); + return hash; +} + //////////////////////////////// //~ rjf: Top-Level API @@ -47,21 +75,129 @@ fs_change_gen(void) //~ rjf: Cache Interaction internal U128 -fs_hash_from_path(String8 path, U64 endt_us) +fs_hash_from_path_range(String8 path, Rng1U64 range, U64 endt_us) { Temp scratch = scratch_begin(0, 0); - U128 result = {0}; + + //- rjf: unpack args path = path_normalized_from_string(scratch.arena, path); - U128 path_key = hs_hash_from_data(path); + U128 key = fs_big_hash_from_string_range(path, range); + + //- rjf: loop through key -> hash history; obtain most recent hash for this key + U128 result = {0}; for(U64 rewind_idx = 0; rewind_idx < 2; rewind_idx += 1) { - result = hs_hash_from_key(path_key, rewind_idx); + result = hs_hash_from_key(key, rewind_idx); + + //- rjf: nonzero hash -> got valid results, return if(!u128_match(result, u128_zero())) { break; } + + //- rjf: zero hash, not rewound? -> send new stream request if needed else if(u128_match(result, u128_zero()) && rewind_idx == 0) { + // rjf: unpack path cache info + U64 path_little_hash = fs_little_hash_from_string(path); + U64 path_slot_idx = path_little_hash%fs_shared->slots_count; + U64 path_stripe_idx = path_slot_idx%fs_shared->stripes_count; + FS_Slot *path_slot = &fs_shared->slots[path_slot_idx]; + FS_Stripe *path_stripe = &fs_shared->stripes[path_stripe_idx]; + + // rjf: loop: request, check for results, return until we can't + OS_MutexScopeR(path_stripe->rw_mutex) for(;;) + { + // rjf: path -> node + FS_Node *node = 0; + for(FS_Node *n = path_slot->first; n != 0; n = n->next) + { + if(str8_match(path, n->path, 0)) + { + node = n; + break; + } + } + + // rjf: node does not exist? -> create & store (we must re-search after promoting r -> w) + if(node == 0) OS_MutexScopeRWPromote(path_stripe->rw_mutex) + { + for(FS_Node *n = path_slot->first; n != 0; n = n->next) + { + if(str8_match(path, n->path, 0)) + { + node = n; + break; + } + } + if(node == 0) + { + node = push_array(path_stripe->arena, FS_Node, 1); + SLLQueuePush(path_slot->first, path_slot->last, node); + node->path = push_str8_copy(path_stripe->arena, path); + node->slots_count = 64; + node->slots = push_array(path_stripe->arena, FS_RangeSlot, node->slots_count); + } + } + + // rjf: range -> node + U64 range_hash = fs_little_hash_from_string(str8_struct(&range)); + U64 range_slot_idx = range_hash%node->slots_count; + FS_RangeSlot *range_slot = &node->slots[range_slot_idx]; + FS_RangeNode *range_node = 0; + for(FS_RangeNode *n = range_slot->first; n != 0; n = n->next) + { + if(MemoryMatchStruct(&n->range, &range)) + { + range_node = n; + break; + } + } + + // rjf: range node does not exist? create & store (we must re-search after promoting r -> w) + if(range_node == 0) OS_MutexScopeRWPromote(path_stripe->rw_mutex) + { + for(FS_RangeNode *n = range_slot->first; n != 0; n = n->next) + { + if(MemoryMatchStruct(&n->range, &range)) + { + range_node = n; + break; + } + } + if(range_node == 0) + { + range_node = push_array(path_stripe->arena, FS_RangeNode, 1); + SLLQueuePush(range_slot->first, range_slot->last, range_node); + range_node->range = range; + } + } + + // rjf: try to send stream request + if(!ins_atomic_u32_eval_cond_assign(&range_node->is_working, 1, 0) && + !fs_u2s_enqueue_req(range, path, endt_us)) + { + ins_atomic_u32_eval_assign(&range_node->is_working, 0); + } + + // rjf: try to reobtain results + result = hs_hash_from_key(key, 0); + + // rjf: have time to wait? -> wait on this stripe; otherwise exit + if(u128_match(result, u128_zero()) && os_now_microseconds() <= endt_us) + { + os_condition_variable_wait_rw_r(path_stripe->cv, path_stripe->rw_mutex, endt_us); + } + else + { + break; + } + } + + //- + // TODO(rjf): OLD vvvvvvvvvvvvvvvv + //- +#if 0 U64 slot_idx = path_key.u64[0]%fs_shared->slots_count; U64 stripe_idx = slot_idx%fs_shared->stripes_count; FS_Slot *slot = &fs_shared->slots[slot_idx]; @@ -84,7 +220,7 @@ fs_hash_from_path(String8 path, U64 endt_us) node->path = push_str8_copy(stripe->arena, path); } if(!ins_atomic_u32_eval_cond_assign(&node->is_working, 1, 0) && - !fs_u2s_enqueue_path(path, endt_us)) + !fs_u2s_enqueue_req(range, path, endt_us)) { ins_atomic_u32_eval_assign(&node->is_working, 0); } @@ -98,17 +234,22 @@ fs_hash_from_path(String8 path, U64 endt_us) break; } } +#endif } } + scratch_end(scratch); return result; } internal U128 -fs_key_from_path(String8 path) +fs_key_from_path_range(String8 path, Rng1U64 range) { - U128 key = hs_hash_from_data(path); - fs_hash_from_path(path, 0); + Temp scratch = scratch_begin(0, 0); + String8 path_normalized = path_normalized_from_string(scratch.arena, path); + U128 key = fs_big_hash_from_string_range(path_normalized, range); + fs_hash_from_path_range(path_normalized, range, 0); + scratch_end(scratch); return key; } @@ -118,8 +259,8 @@ fs_timestamp_from_path(String8 path) Temp scratch = scratch_begin(0, 0); U64 result = 0; path = path_normalized_from_string(scratch.arena, path); - U128 path_key = hs_hash_from_data(path); - U64 slot_idx = path_key.u64[0]%fs_shared->slots_count; + U64 path_hash = fs_little_hash_from_string(path); + U64 slot_idx = path_hash%fs_shared->slots_count; U64 stripe_idx = slot_idx%fs_shared->stripes_count; FS_Slot *slot = &fs_shared->slots[slot_idx]; FS_Stripe *stripe = &fs_shared->stripes[stripe_idx]; @@ -144,8 +285,8 @@ fs_size_from_path(String8 path) Temp scratch = scratch_begin(0, 0); U64 result = 0; path = path_normalized_from_string(scratch.arena, path); - U128 path_key = hs_hash_from_data(path); - U64 slot_idx = path_key.u64[0]%fs_shared->slots_count; + U64 path_hash = fs_little_hash_from_string(path); + U64 slot_idx = path_hash%fs_shared->slots_count; U64 stripe_idx = slot_idx%fs_shared->stripes_count; FS_Slot *slot = &fs_shared->slots[slot_idx]; FS_Stripe *stripe = &fs_shared->stripes[stripe_idx]; @@ -168,7 +309,7 @@ fs_size_from_path(String8 path) //~ rjf: Streamer Threads internal B32 -fs_u2s_enqueue_path(String8 path, U64 endt_us) +fs_u2s_enqueue_req(Rng1U64 range, String8 path, U64 endt_us) { B32 result = 0; path.size = Min(path.size, fs_shared->u2s_ring_size); @@ -179,6 +320,8 @@ fs_u2s_enqueue_path(String8 path, U64 endt_us) if(available_size >= sizeof(U64) + path.size) { result = 1; + fs_shared->u2s_ring_write_pos += ring_write_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_write_pos, &range.min); + fs_shared->u2s_ring_write_pos += ring_write_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_write_pos, &range.max); fs_shared->u2s_ring_write_pos += ring_write_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_write_pos, &path.size); fs_shared->u2s_ring_write_pos += ring_write(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_write_pos, path.str, path.size); fs_shared->u2s_ring_write_pos += 7; @@ -194,18 +337,19 @@ fs_u2s_enqueue_path(String8 path, U64 endt_us) return result; } -internal String8 -fs_u2s_dequeue_path(Arena *arena) +internal void +fs_u2s_dequeue_req(Arena *arena, Rng1U64 *range_out, String8 *path_out) { - String8 path = {0}; OS_MutexScope(fs_shared->u2s_ring_mutex) for(;;) { U64 unconsumed_size = fs_shared->u2s_ring_write_pos - fs_shared->u2s_ring_read_pos; if(unconsumed_size >= sizeof(U64)) { - fs_shared->u2s_ring_read_pos += ring_read_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_read_pos, &path.size); - path.str = push_array(arena, U8, path.size); - fs_shared->u2s_ring_read_pos += ring_read(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_read_pos, path.str, path.size); + fs_shared->u2s_ring_read_pos += ring_read_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_read_pos, &range_out->min); + fs_shared->u2s_ring_read_pos += ring_read_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_read_pos, &range_out->max); + fs_shared->u2s_ring_read_pos += ring_read_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_read_pos, &path_out->size); + path_out->str = push_array(arena, U8, path_out->size); + fs_shared->u2s_ring_read_pos += ring_read(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_read_pos, path_out->str, path_out->size); fs_shared->u2s_ring_read_pos += 7; fs_shared->u2s_ring_read_pos -= fs_shared->u2s_ring_read_pos%8; break; @@ -213,7 +357,6 @@ fs_u2s_dequeue_path(Arena *arena) os_condition_variable_wait(fs_shared->u2s_ring_cv, fs_shared->u2s_ring_mutex, max_U64); } os_condition_variable_broadcast(fs_shared->u2s_ring_cv); - return path; } internal void @@ -224,26 +367,33 @@ fs_streamer_thread__entry_point(void *p) { Temp scratch = scratch_begin(0, 0); - //- rjf: unpack path - String8 path = fs_u2s_dequeue_path(scratch.arena); - U128 key = hs_hash_from_data(path); - U64 slot_idx = key.u64[0]%fs_shared->slots_count; - U64 stripe_idx = slot_idx%fs_shared->stripes_count; - FS_Slot *slot = &fs_shared->slots[slot_idx]; - FS_Stripe *stripe = &fs_shared->stripes[stripe_idx]; + //- rjf: get next request + Rng1U64 range = {0}; + String8 path = {0}; + fs_u2s_dequeue_req(scratch.arena, &range, &path); + + //- rjf: unpack request + U128 key = fs_big_hash_from_string_range(path, range); + U64 path_hash = fs_little_hash_from_string(path); + U64 path_slot_idx = path_hash%fs_shared->slots_count; + U64 path_stripe_idx = path_slot_idx%fs_shared->stripes_count; + FS_Slot *path_slot = &fs_shared->slots[path_slot_idx]; + FS_Stripe *path_stripe = &fs_shared->stripes[path_stripe_idx]; //- rjf: load ProfBegin("load \"%.*s\"", str8_varg(path)); FileProperties pre_props = os_properties_from_file_path(path); + U64 range_size = dim_1u64(range); + U64 read_size = Min(pre_props.size, range_size); OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite, path); - U64 data_arena_size = pre_props.size+ARENA_HEADER_SIZE; + U64 data_arena_size = read_size+ARENA_HEADER_SIZE; data_arena_size += KB(4)-1; data_arena_size -= data_arena_size%KB(4); ProfBegin("allocate"); Arena *data_arena = arena_alloc(.reserve_size = data_arena_size, .commit_size = data_arena_size); ProfEnd(); ProfBegin("read"); - String8 data = os_string_from_file_range(data_arena, file, r1u64(0, pre_props.size)); + String8 data = os_string_from_file_range(data_arena, file, r1u64(range.min, range.min+read_size)); ProfEnd(); os_file_close(file); FileProperties post_props = os_properties_from_file_path(path); @@ -269,10 +419,10 @@ fs_streamer_thread__entry_point(void *p) } //- rjf: commit info to cache - ProfScope("commit to cache") OS_MutexScopeW(stripe->rw_mutex) + ProfScope("commit to cache") OS_MutexScopeW(path_stripe->rw_mutex) { FS_Node *node = 0; - for(FS_Node *n = slot->first; n != 0; n = n->next) + for(FS_Node *n = path_slot->first; n != 0; n = n->next) { if(str8_match(n->path, path, 0)) { @@ -291,10 +441,22 @@ fs_streamer_thread__entry_point(void *p) node->timestamp = post_props.modified; node->size = post_props.size; } - ins_atomic_u32_eval_assign(&node->is_working, 0); + U64 range_hash = fs_little_hash_from_string(str8_struct(&range)); + U64 range_slot_idx = range_hash%node->slots_count; + FS_RangeSlot *range_slot = &node->slots[range_slot_idx]; + FS_RangeNode *range_node = 0; + for(FS_RangeNode *n = range_slot->first; n != 0; n = n->next) + { + if(MemoryMatchStruct(&n->range, &range)) + { + range_node = n; + break; + } + } + ins_atomic_u32_eval_assign(&range_node->is_working, 0); } } - os_condition_variable_broadcast(stripe->cv); + os_condition_variable_broadcast(path_stripe->cv); ProfEnd(); scratch_end(scratch); @@ -323,10 +485,18 @@ fs_detector_thread__entry_point(void *p) FileProperties props = os_properties_from_file_path(n->path); if(props.modified != n->timestamp) { - if(!ins_atomic_u32_eval_cond_assign(&n->is_working, 1, 0) && - !fs_u2s_enqueue_path(n->path, os_now_microseconds()+100000)) + for(U64 range_slot_idx = 0; range_slot_idx < n->slots_count; range_slot_idx += 1) { - ins_atomic_u32_eval_assign(&n->is_working, 0); + for(FS_RangeNode *range_n = n->slots[range_slot_idx].first; + range_n != 0; + range_n = range_n->next) + { + if(!ins_atomic_u32_eval_cond_assign(&range_n->is_working, 1, 0) && + !fs_u2s_enqueue_req(range_n->range, n->path, os_now_microseconds()+100000)) + { + ins_atomic_u32_eval_assign(&range_n->is_working, 0); + } + } } } } diff --git a/src/file_stream/file_stream.h b/src/file_stream/file_stream.h index 86c6d47c..26d3a6f0 100644 --- a/src/file_stream/file_stream.h +++ b/src/file_stream/file_stream.h @@ -7,14 +7,34 @@ //////////////////////////////// //~ rjf: Per-Path Info Cache Types +typedef struct FS_RangeNode FS_RangeNode; +struct FS_RangeNode +{ + FS_RangeNode *next; + Rng1U64 range; + B32 is_working; +}; + +typedef struct FS_RangeSlot FS_RangeSlot; +struct FS_RangeSlot +{ + FS_RangeNode *first; + FS_RangeNode *last; +}; + typedef struct FS_Node FS_Node; struct FS_Node { FS_Node *next; + + // rjf: file metadata String8 path; U64 timestamp; U64 size; - B32 is_working; + + // rjf: sub-table of per-requested-file-range info + U64 slots_count; + FS_RangeSlot *slots; }; typedef struct FS_Slot FS_Slot; @@ -68,6 +88,12 @@ struct FS_Shared global FS_Shared *fs_shared = 0; +//////////////////////////////// +//~ rjf: Basic Helpers + +internal U64 fs_little_hash_from_string(String8 string); +internal U128 fs_big_hash_from_string_range(String8 string, Rng1U64 range); + //////////////////////////////// //~ rjf: Top-Level API @@ -81,16 +107,17 @@ internal U64 fs_change_gen(void); //////////////////////////////// //~ rjf: Cache Interaction -internal U128 fs_hash_from_path(String8 path, U64 endt_us); -internal U128 fs_key_from_path(String8 path); +internal U128 fs_hash_from_path_range(String8 path, Rng1U64 range, U64 endt_us); +internal U128 fs_key_from_path_range(String8 path, Rng1U64 range); + internal U64 fs_timestamp_from_path(String8 path); internal U64 fs_size_from_path(String8 path); //////////////////////////////// //~ rjf: Streamer Threads -internal B32 fs_u2s_enqueue_path(String8 path, U64 endt_us); -internal String8 fs_u2s_dequeue_path(Arena *arena); +internal B32 fs_u2s_enqueue_req(Rng1U64 range, String8 path, U64 endt_us); +internal void fs_u2s_dequeue_req(Arena *arena, Rng1U64 *range_out, String8 *path_out); internal void fs_streamer_thread__entry_point(void *p);