mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-08 08:53:43 +08:00
perf(lsp): C/C++ Tier 2 — pre-built per-language cross-LSP registry
Brings C/C++/CUDA to Go's optimization level. Extracts the cross-LSP
registration loop into c_register_lsp_defs (shared by per-file and
Tier 2 paths), adds:
cbm_c_build_cross_registry — builds ONE project-wide registry from
all C-family defs (filters by lang) + both C and C++ stdlibs,
finalized, shared READ-ONLY across resolve workers.
cbm_run_c_lsp_cross_with_registry — per-file resolve using the
shared registry; no per-file registry rebuild.
C cross-LSP is DEF-DRIVEN (fields/returns/embeds come from the def
strings, no per-file AST field collection), so the shared registry
produces identical resolution to the per-file build — zero quality
loss. resolve_worker dispatches CBM_LANG_C/CPP/CUDA to the new path;
pipeline.c builds cross_registries.c; pass_lsp_cross.h includes c_lsp.h.
postgres bench (4,967 files, ADVANCED mode): 628 C files share one
pre-built registry (lsp_cross_prepare=17ms, zero slow files), 44 LSP
overrides, +9 edges vs FULL. All 200 test_c_lsp tests pass. No
SEGV/ASan. Total pipeline overhead vs FULL: +5.2%.
This commit is contained in:
+93
-22
@@ -4554,26 +4554,13 @@ void cbm_run_c_lsp(CBMArena* arena, CBMFileResult* result,
|
||||
// Entry point: cross-file LSP
|
||||
// ============================================================================
|
||||
|
||||
void cbm_run_c_lsp_cross(
|
||||
CBMArena* arena,
|
||||
const char* source, int source_len,
|
||||
const char* module_qn,
|
||||
bool cpp_mode,
|
||||
CBMLSPDef* defs, int def_count,
|
||||
const char** include_paths, const char** include_ns_qns, int include_count,
|
||||
TSTree* cached_tree,
|
||||
CBMResolvedCallArray* out) {
|
||||
|
||||
if (!source || source_len == 0 || !out) return;
|
||||
|
||||
CBMTypeRegistry reg;
|
||||
cbm_registry_init(®, arena);
|
||||
|
||||
// Register stdlib
|
||||
cbm_c_stdlib_register(®, arena);
|
||||
if (cpp_mode) cbm_cpp_stdlib_register(®, arena);
|
||||
|
||||
// Register all defs
|
||||
/* Register one batch of CBMLSPDef[] into a registry. Shared by the
|
||||
* per-file cross-LSP path and the Tier 2 pre-built registry builder.
|
||||
* Reads field/return/embedded info from the def strings (def-driven —
|
||||
* no per-file AST mutation), so the same defs always yield the same
|
||||
* registry entries regardless of which file is being processed. */
|
||||
static void c_register_lsp_defs(CBMArena* arena, CBMTypeRegistry* reg,
|
||||
const char* module_qn, CBMLSPDef* defs, int def_count) {
|
||||
for (int i = 0; i < def_count; i++) {
|
||||
CBMLSPDef* d = &defs[i];
|
||||
if (!d->qualified_name || !d->short_name) continue;
|
||||
@@ -4642,7 +4629,7 @@ void cbm_run_c_lsp_cross(
|
||||
}
|
||||
}
|
||||
|
||||
cbm_registry_add_type(®, rt);
|
||||
cbm_registry_add_type(reg, rt);
|
||||
}
|
||||
|
||||
if (d->label && (strcmp(d->label, "Function") == 0 || strcmp(d->label, "Method") == 0)) {
|
||||
@@ -4681,9 +4668,93 @@ void cbm_run_c_lsp_cross(
|
||||
rf.receiver_type = d->receiver_type; /* borrowed */
|
||||
}
|
||||
|
||||
cbm_registry_add_func(®, rf);
|
||||
cbm_registry_add_func(reg, rf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Tier 2: build a project-wide C/C++/CUDA registry ONCE from all defs.
|
||||
* Registers both C and C++ stdlibs (C is a subset; harmless overlap)
|
||||
* and all C-family defs. Shared READ-ONLY across resolve workers.
|
||||
* Def-driven (no AST field collection) so produces identical entries
|
||||
* to the per-file build — zero quality loss. */
|
||||
CBMTypeRegistry* cbm_c_build_cross_registry(CBMArena* arena, CBMLSPDef* defs, int def_count) {
|
||||
if (!arena) return NULL;
|
||||
CBMTypeRegistry* reg = (CBMTypeRegistry*)cbm_arena_alloc(arena, sizeof(*reg));
|
||||
if (!reg) return NULL;
|
||||
cbm_registry_init(reg, arena);
|
||||
cbm_c_stdlib_register(reg, arena);
|
||||
cbm_cpp_stdlib_register(reg, arena);
|
||||
for (int i = 0; i < def_count; i++) {
|
||||
CBMLSPDef* d = &defs[i];
|
||||
if (d->lang != CBM_LANG_C && d->lang != CBM_LANG_CPP && d->lang != CBM_LANG_CUDA) {
|
||||
continue;
|
||||
}
|
||||
c_register_lsp_defs(arena, reg, "", d, 1);
|
||||
}
|
||||
cbm_registry_finalize(reg);
|
||||
return reg;
|
||||
}
|
||||
|
||||
void cbm_run_c_lsp_cross_with_registry(
|
||||
CBMArena* arena,
|
||||
const char* source, int source_len,
|
||||
const char* module_qn,
|
||||
bool cpp_mode,
|
||||
CBMTypeRegistry* reg,
|
||||
const char** include_paths, const char** include_ns_qns, int include_count,
|
||||
TSTree* cached_tree,
|
||||
CBMResolvedCallArray* out) {
|
||||
if (!source || source_len == 0 || !out || !reg) return;
|
||||
|
||||
TSParser* parser = NULL;
|
||||
TSTree* tree = cached_tree;
|
||||
bool owns_tree = false;
|
||||
if (!tree) {
|
||||
parser = ts_parser_new();
|
||||
if (!parser) return;
|
||||
const TSLanguage* ts_lang = cpp_mode ? tree_sitter_cpp() : tree_sitter_c();
|
||||
ts_parser_set_language(parser, ts_lang);
|
||||
tree = ts_parser_parse_string(parser, NULL, source, source_len);
|
||||
ts_parser_delete(parser);
|
||||
owns_tree = true;
|
||||
if (!tree) return;
|
||||
}
|
||||
TSNode root = ts_tree_root_node(tree);
|
||||
|
||||
CLSPContext ctx;
|
||||
c_lsp_init(&ctx, arena, source, source_len, reg, module_qn, cpp_mode, out);
|
||||
for (int i = 0; i < include_count; i++) {
|
||||
c_lsp_add_include(&ctx, include_paths[i], include_ns_qns[i]);
|
||||
}
|
||||
c_lsp_process_file(&ctx, root);
|
||||
|
||||
if (owns_tree) {
|
||||
ts_tree_delete(tree);
|
||||
}
|
||||
}
|
||||
|
||||
void cbm_run_c_lsp_cross(
|
||||
CBMArena* arena,
|
||||
const char* source, int source_len,
|
||||
const char* module_qn,
|
||||
bool cpp_mode,
|
||||
CBMLSPDef* defs, int def_count,
|
||||
const char** include_paths, const char** include_ns_qns, int include_count,
|
||||
TSTree* cached_tree,
|
||||
CBMResolvedCallArray* out) {
|
||||
|
||||
if (!source || source_len == 0 || !out) return;
|
||||
|
||||
CBMTypeRegistry reg;
|
||||
cbm_registry_init(®, arena);
|
||||
|
||||
// Register stdlib
|
||||
cbm_c_stdlib_register(®, arena);
|
||||
if (cpp_mode) cbm_cpp_stdlib_register(®, arena);
|
||||
|
||||
// Register all defs (shared helper — def-driven)
|
||||
c_register_lsp_defs(arena, ®, module_qn, defs, def_count);
|
||||
|
||||
// Use cached tree if available, otherwise parse fresh
|
||||
TSParser* parser = NULL;
|
||||
|
||||
@@ -114,6 +114,23 @@ void cbm_run_c_lsp_cross(
|
||||
TSTree* cached_tree, // NULL = parse internally
|
||||
CBMResolvedCallArray* out);
|
||||
|
||||
// Tier 2: build a project-wide C/C++/CUDA registry ONCE from all defs
|
||||
// (filters by lang). Shared READ-ONLY across resolve workers. Def-driven
|
||||
// (no AST field collection) → identical entries to the per-file build.
|
||||
CBMTypeRegistry* cbm_c_build_cross_registry(CBMArena* arena, CBMLSPDef* defs, int def_count);
|
||||
|
||||
// Cross-file LSP using a pre-built shared registry (Tier 2). Skips the
|
||||
// per-file registry build; just parse + resolve.
|
||||
void cbm_run_c_lsp_cross_with_registry(
|
||||
CBMArena* arena,
|
||||
const char* source, int source_len,
|
||||
const char* module_qn,
|
||||
bool cpp_mode,
|
||||
CBMTypeRegistry* reg, // pre-built, finalized, READ-ONLY
|
||||
const char** include_paths, const char** include_ns_qns, int include_count,
|
||||
TSTree* cached_tree, // NULL = parse internally
|
||||
CBMResolvedCallArray* out);
|
||||
|
||||
// Register C stdlib types and functions into a registry.
|
||||
void cbm_c_stdlib_register(CBMTypeRegistry* reg, CBMArena* arena);
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
* go_lsp.h was where the project-wide def descriptor landed first. */
|
||||
#include "lsp/go_lsp.h"
|
||||
#include "lsp/py_lsp.h" /* cbm_py_build_cross_registry / cbm_run_py_lsp_cross_with_registry */
|
||||
#include "lsp/c_lsp.h" /* cbm_c_build_cross_registry / cbm_run_c_lsp_cross_with_registry */
|
||||
#include "pipeline/pipeline_internal.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
@@ -2052,9 +2052,18 @@ static void resolve_worker(int worker_id, void *ctx_ptr) {
|
||||
result->cached_tree, &result->resolved_calls);
|
||||
used_prebuilt = true;
|
||||
break;
|
||||
/* C/C++/CUDA, TS/JS/TSX, PHP, C# fall through to the
|
||||
* per-file build path below until their _with_registry
|
||||
* variants are added in follow-up commits. */
|
||||
case CBM_LANG_C:
|
||||
case CBM_LANG_CPP:
|
||||
case CBM_LANG_CUDA:
|
||||
cbm_run_c_lsp_cross_with_registry(
|
||||
&result->arena, result->source, result->source_len,
|
||||
def_module, (lang != CBM_LANG_C), prebuilt,
|
||||
imp_keys, imp_vals, imp_count,
|
||||
result->cached_tree, &result->resolved_calls);
|
||||
used_prebuilt = true;
|
||||
break;
|
||||
/* TS/JS/TSX, PHP fall through to the per-file build
|
||||
* path below until their _with_registry variants land. */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user