kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit b732a5d4604781dd27b372bb604ad6210062b2d3
parent 9437e8f1750cb6133f73a22b6efe18bdf3717181
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu, 14 May 2026 17:45:54 -0700

Avoid duplicate segment copies in JIT

Diffstat:
Msrc/link/link_jit.c | 48+++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/link/link_layout.c | 10++++++----
2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/src/link/link_jit.c b/src/link/link_jit.c @@ -147,6 +147,39 @@ static uintptr_t vaddr_to_write(const LinkImage* img, return 0; } +static void jit_copy_input_section_bytes(LinkImage* img, + const CfreeExecMemRegion* segs) { + Compiler* c = img->c; + Linker* l = img->linker; + u32 i; + for (i = 0; i < img->nsections; ++i) { + const LinkSection* ls = &img->sections[i]; + const LinkSegment* seg; + ObjBuilder* ob; + const Section* s; + u32 input_idx; + u8* dst; + if (ls->input_id == LINK_INPUT_NONE) continue; + input_idx = ls->input_id - 1u; + if (ls->segment_id == LINK_SEG_NONE || ls->segment_id > img->nsegments) + compiler_panic(c, no_loc(), + "cfree_jit_from_image: section has invalid segment"); + seg = &img->segments[ls->segment_id - 1u]; + ob = (input_idx < img->dbg_objs_n) ? img->dbg_objs[input_idx] : NULL; + if (!ob && l && input_idx < LinkInputs_count(&l->inputs)) + ob = LinkInputs_at(&l->inputs, input_idx)->obj; + if (!ob) + compiler_panic(c, no_loc(), + "cfree_jit_from_image: input section bytes unavailable"); + s = obj_section_get(ob, ls->obj_section_id); + if (!s || s->sem == SSEM_NOBITS) continue; + if (s->bytes.total == 0) continue; + dst = (u8*)segs[seg->id - 1u].write + (size_t)(ls->vaddr - seg->vaddr); + metrics_count(c, "jit.input_section_bytes", s->bytes.total); + buf_flatten(&s->bytes, dst); + } +} + /* Walk every TLV descriptor and overwrite its three slots with * (thunk_addr, ctx, per-thread offset). See src/jit/tlv_thunk.h for * the descriptor contract. Iteration is reloc-driven: every descriptor @@ -268,6 +301,7 @@ CfreeJit* cfree_jit_from_image(LinkImage* img) { u64 image_end = 0; u64 master_size; int needs_exec = 0; + int needs_input_materialize = 0; u32 i; if (!img) return NULL; @@ -335,14 +369,26 @@ CfreeJit* cfree_jit_from_image(LinkImage* img) { } /* Master reservation is zeroed; BSS is naturally zero. */ - /* Copy each segment's file bytes to its write alias. */ + /* Copy synthetic segment buffers to their write aliases. In JIT mode, + * ordinary input-section segments intentionally have NULL payload buffers + * and are materialized directly from input Buf chunks below. */ metrics_scope_begin(c, "jit.copy_segments"); for (i = 0; i < img->nsegments; ++i) { const LinkSegment* seg = &img->segments[i]; if (seg->file_size == 0) continue; + if (!img->segment_bytes[i]) { + needs_input_materialize = 1; + continue; + } metrics_count(c, "jit.segment_bytes", seg->file_size); memcpy(segs[i].write, img->segment_bytes[i], (size_t)seg->file_size); } + if (needs_input_materialize) { + if (!img->linker || !img->linker->jit_mode) + compiler_panic(c, no_loc(), + "cfree_jit_from_image: segment bytes are not materialized"); + jit_copy_input_section_bytes(img, segs); + } metrics_scope_end(c, "jit.copy_segments"); /* Apply relocations. The patch site bytes go through the write diff --git a/src/link/link_layout.c b/src/link/link_layout.c @@ -361,12 +361,14 @@ void link_layout_sections(Linker* l, LinkImage* img, const GcLive* g) { img->nsegments++; } - /* Allocate segment buffers and fix up section offsets/vaddrs. */ + /* Allocate segment buffers and fix up section offsets/vaddrs. The + * JIT lane maps input section bytes directly into execmem, so ordinary + * segment payload buffers would be copied only to be copied again. */ for (b = 0; b < SEG_NBUCKETS; ++b) { if (!bucket_seg[b]) continue; { LinkSegment* seg = &img->segments[bucket_seg[b] - 1]; - if (seg->file_size) { + if (seg->file_size && !l->jit_mode) { img->segment_bytes[bucket_seg[b] - 1] = (u8*)h->alloc(h, (size_t)seg->file_size, 16); if (!img->segment_bytes[bucket_seg[b] - 1]) @@ -756,7 +758,7 @@ static void link_layout_sections_scripted(Linker* l, LinkImage* img, seg->align = align_max; seg->nsections = nsec_in_seg; file_cursor += file_size_accum; - if (file_size_accum) { + if (file_size_accum && !l->jit_mode) { img->segment_bytes[img->nsegments] = (u8*)h->alloc(h, (size_t)file_size_accum, 16); if (!img->segment_bytes[img->nsegments]) @@ -981,7 +983,7 @@ LinkImage* link_resolve(Linker* l) { metrics_count(l->c, "link.segments", img->nsegments); metrics_scope_end(l->c, "link.layout_sections"); metrics_scope_begin(l->c, "link.emit_segment_bytes"); - link_emit_segment_bytes(l, img); + if (!l->jit_mode) link_emit_segment_bytes(l, img); metrics_scope_end(l->c, "link.emit_segment_bytes"); link_assign_symbol_vaddrs(l, img); link_emit_array_boundaries(l, img);