summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-02-19 08:27:20 -0800
committerKaz Kylheku <kaz@kylheku.com>2022-02-19 08:27:20 -0800
commit834ebaf314521b9b61a2e9f0f3f3afa8b16990bb (patch)
treece5fdc70b2b4826d105426a4baabfac8027e851b
parente66c35b6eebe6f04c8feca78c2a3e68205f9dc56 (diff)
downloadtxr-834ebaf314521b9b61a2e9f0f3f3afa8b16990bb.tar.gz
txr-834ebaf314521b9b61a2e9f0f3f3afa8b16990bb.tar.bz2
txr-834ebaf314521b9b61a2e9f0f3f3afa8b16990bb.zip
autoload: use weak hash to erase registrations.
In autoload the _set_entries functions are being called twice: the first time with a functional argument to associate symbols with that function, and then when the module is loaded, a second time with a nil argument to erase those associations. This is inefficient; some modules have many symbols to remove from a hash. What we can do is make the hash weak; associate the symbols with a function weakly, such that those entries lapse when the function becomes garbage. Lapsing of weak hash table entries during GC is more efficient than making numerous calls to remhash. We can use a separate strong hash table to hang on to the functions; when a module is instantiated, all we have to do is remove the instantiation function from the table. Then that function is reachable only as a weak value from the other tables. * autoload.c (autoload_reg_hash): New static variable. (place_instantiate, ver_instantiate, ifa_instantiate, txr_case_instantiate, with_resources_instantiate, path_test_instantiate, struct_instantiate, with_stream_instantiate, hash_instantiate, except_instantiate, type_instantiate, yield_instantiate, sock_instantiate, termios_instantiate, awk_instantiate, build_instantiate, trace_instantiate, getopts_instantiate, package_instantiate, getput_instantiate, tagbody_instantiate, pmac_instantiate, error_instantiate, keyparams_instantiate, ffi_instantiate, doloop_instantiate, stream_wrap_instantiate, asm_instantiate, compiler_instantiate, debugger_instantiate, op_instantiate, save_exe_instantiate, defset_instantiate, copy_file_instantiate, arith_each_instantiate, each_prod_instantiate, quips_instantiate, match_instantiate, doc_instantiate, pic_instantiate, constfun_instantiate): Remove set_fun argument and call to that function. (autoload_reg): Remove argument from instantiate function. Add the function to the autoload_reg_hash table, associated with the t symbol. (autoload_init_tables): Initialize autoload_reg_hash. Turn the existing symbol hashes into weak tables. Let's use weak or-semantics, so they don't hang onto uninterned symbols. (autoload_try): If a symbol resolves to a function, indicating a load might be required, we now must verify whether that is really the case by seeing whether the function exists in the autolod_reg_hash table. If so, we remove it from that table and do the load. * autoload.h (autoload_reg): Declaration updated. * gencadr.txr (cadr_register): Remove set_fun argument and call to that function. * cadr.c: Regenerated.
-rw-r--r--autoload.c160
-rw-r--r--autoload.h2
-rw-r--r--cadr.c3
-rw-r--r--gencadr.txr3
4 files changed, 69 insertions, 99 deletions
diff --git a/autoload.c b/autoload.c
index f039cb3a..22185ba1 100644
--- a/autoload.c
+++ b/autoload.c
@@ -45,6 +45,7 @@ int opt_dbg_autoload;
val trace_loaded;
static val autoload_hash[al_max + 1];
+static val autoload_reg_hash;
static void autload_set_impl(al_ns_t ns, val *name, val fun, val package)
{
@@ -118,9 +119,8 @@ static val place_set_entries(val fun)
return nil;
}
-static val place_instantiate(val set_fun)
+static val place_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("place")));
return nil;
}
@@ -132,9 +132,8 @@ static val ver_set_entries(val fun)
return nil;
}
-static val ver_instantiate(val set_fun)
+static val ver_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("ver")));
return nil;
}
@@ -148,9 +147,8 @@ static val ifa_set_entries(val fun)
return nil;
}
-static val ifa_instantiate(val set_fun)
+static val ifa_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("ifa")));
return nil;
}
@@ -162,9 +160,8 @@ static val txr_case_set_entries(val fun)
return nil;
}
-static val txr_case_instantiate(val set_fun)
+static val txr_case_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("txr-case")));
return nil;
}
@@ -180,9 +177,8 @@ static val with_resources_set_entries(val fun)
return nil;
}
-static val with_resources_instantiate(val set_fun)
+static val with_resources_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("with-resources")));
return nil;
}
@@ -207,9 +203,8 @@ static val path_test_set_entries(val fun)
return nil;
}
-static val path_test_instantiate(val set_fun)
+static val path_test_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("path-test")));
return nil;
}
@@ -241,9 +236,8 @@ static val struct_set_entries(val fun)
return nil;
}
-static val struct_instantiate(val set_fun)
+static val struct_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("struct")));
return nil;
}
@@ -264,9 +258,8 @@ static val with_stream_set_entries(val fun)
return nil;
}
-static val with_stream_instantiate(val set_fun)
+static val with_stream_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("with-stream")));
return nil;
}
@@ -278,9 +271,8 @@ static val hash_set_entries(val fun)
return nil;
}
-static val hash_instantiate(val set_fun)
+static val hash_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("hash")));
return nil;
}
@@ -296,9 +288,8 @@ static val except_set_entries(val fun)
return nil;
}
-static val except_instantiate(val set_fun)
+static val except_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("except")));
return nil;
}
@@ -312,9 +303,8 @@ static val type_set_entries(val fun)
return nil;
}
-static val type_instantiate(val set_fun)
+static val type_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("type")));
return nil;
}
@@ -335,9 +325,8 @@ static val yield_set_entries(val fun)
return nil;
}
-static val yield_instantiate(val set_fun)
+static val yield_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("yield")));
return nil;
}
@@ -396,9 +385,8 @@ static val sock_set_entries(val fun)
return nil;
}
-static val sock_instantiate(val set_fun)
+static val sock_instantiate(void)
{
- funcall1(set_fun, nil);
sock_load_init();
load(scat2(stdlib_path, lit("socket")));
return nil;
@@ -420,9 +408,8 @@ static val termios_set_entries(val fun)
return nil;
}
-static val termios_instantiate(val set_fun)
+static val termios_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("termios")));
return nil;
}
@@ -455,9 +442,8 @@ static val awk_set_entries(val fun)
return nil;
}
-static val awk_instantiate(val set_fun)
+static val awk_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("awk")));
return nil;
}
@@ -482,9 +468,8 @@ static val build_set_entries(val fun)
return nil;
}
-static val build_instantiate(val set_fun)
+static val build_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("build")));
return nil;
}
@@ -506,9 +491,8 @@ static val trace_set_entries(val fun)
return nil;
}
-static val trace_instantiate(val set_fun)
+static val trace_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("trace")));
trace_loaded = t;
return nil;
@@ -534,9 +518,8 @@ static val getopts_set_entries(val fun)
return nil;
}
-static val getopts_instantiate(val set_fun)
+static val getopts_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("getopts")));
return nil;
}
@@ -551,9 +534,8 @@ static val package_set_entries(val fun)
return nil;
}
-static val package_instantiate(val set_fun)
+static val package_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("package")));
return nil;
}
@@ -581,9 +563,8 @@ static val getput_set_entries(val fun)
return nil;
}
-static val getput_instantiate(val set_fun)
+static val getput_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("getput")));
return nil;
}
@@ -597,9 +578,8 @@ static val tagbody_set_entries(val fun)
return nil;
}
-static val tagbody_instantiate(val set_fun)
+static val tagbody_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("tagbody")));
return nil;
}
@@ -613,9 +593,8 @@ static val pmac_set_entries(val fun)
return nil;
}
-static val pmac_instantiate(val set_fun)
+static val pmac_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("pmac")));
return nil;
}
@@ -637,9 +616,8 @@ static val error_set_entries(val fun)
return nil;
}
-static val error_instantiate(val set_fun)
+static val error_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("error")));
return nil;
}
@@ -662,9 +640,8 @@ static val keyparams_set_entries(val fun)
return nil;
}
-static val keyparams_instantiate(val set_fun)
+static val keyparams_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("keyparams")));
return nil;
}
@@ -685,9 +662,8 @@ static val ffi_set_entries(val fun)
return nil;
}
-static val ffi_instantiate(val set_fun)
+static val ffi_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("ffi")));
return nil;
}
@@ -702,9 +678,8 @@ static val doloop_set_entries(val fun)
return nil;
}
-static val doloop_instantiate(val set_fun)
+static val doloop_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("doloop")));
return nil;
}
@@ -724,9 +699,8 @@ static val stream_wrap_set_entries(val fun)
return nil;
}
-static val stream_wrap_instantiate(val set_fun)
+static val stream_wrap_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("stream-wrap")));
return nil;
}
@@ -746,9 +720,8 @@ static val asm_set_entries(val fun)
return nil;
}
-static val asm_instantiate(val set_fun)
+static val asm_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("asm")));
return nil;
}
@@ -775,9 +748,8 @@ static val compiler_set_entries(val fun)
return nil;
}
-static val compiler_instantiate(val set_fun)
+static val compiler_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("compiler")));
return nil;
}
@@ -792,9 +764,8 @@ static val debugger_set_entries(val fun)
return nil;
}
-static val debugger_instantiate(val set_fun)
+static val debugger_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("debugger")));
return nil;
}
@@ -811,9 +782,8 @@ static val op_set_entries(val fun)
return nil;
}
-static val op_instantiate(val set_fun)
+static val op_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("op")));
return nil;
}
@@ -829,9 +799,8 @@ static val save_exe_set_entries(val fun)
return nil;
}
-static val save_exe_instantiate(val set_fun)
+static val save_exe_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("save-exe")));
return nil;
}
@@ -848,9 +817,8 @@ static val defset_set_entries(val fun)
return nil;
}
-static val defset_instantiate(val set_fun)
+static val defset_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("defset")));
return nil;
}
@@ -873,9 +841,8 @@ static val copy_file_set_entries(val fun)
return nil;
}
-static val copy_file_instantiate(val set_fun)
+static val copy_file_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("copy-file")));
return nil;
}
@@ -891,9 +858,8 @@ static val arith_each_set_entries(val fun)
return nil;
}
-static val arith_each_instantiate(val set_fun)
+static val arith_each_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("arith-each")));
return nil;
}
@@ -911,9 +877,8 @@ static val each_prod_set_entries(val fun)
return nil;
}
-static val each_prod_instantiate(val set_fun)
+static val each_prod_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("each-prod")));
return nil;
}
@@ -927,9 +892,8 @@ static val quips_set_entries(val fun)
return nil;
}
-static val quips_instantiate(val set_fun)
+static val quips_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("quips")));
return nil;
}
@@ -966,9 +930,8 @@ static val match_set_entries(val fun)
return nil;
}
-static val match_instantiate(val set_fun)
+static val match_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("match")));
return nil;
}
@@ -986,9 +949,8 @@ static val doc_set_entries(val fun)
return nil;
}
-static val doc_instantiate(val set_fun)
+static val doc_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("doc-lookup")));
return nil;
}
@@ -1003,9 +965,8 @@ static val pic_set_entries(val fun)
return nil;
}
-static val pic_instantiate(val set_fun)
+static val pic_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("pic")));
return nil;
}
@@ -1020,26 +981,32 @@ static val constfun_set_entries(val fun)
return nil;
}
-static val constfun_instantiate(val set_fun)
+static val constfun_instantiate(void)
{
- funcall1(set_fun, nil);
load(scat2(stdlib_path, lit("constfun")));
return nil;
}
-val autoload_reg(val (*instantiate)(val),
+val autoload_reg(val (*instantiate)(void),
val (*set_entries)(val))
{
- return set_entries(func_f0(func_n1(set_entries), instantiate));
+ val fun = func_n0(instantiate);
+ set_entries(fun);
+ return sethash(autoload_reg_hash, fun, t);
}
static void autoload_init_tables(void)
{
int i;
+
+ prot1(&autoload_reg_hash);
+
for (i = 0; i <= al_max; i++) {
- autoload_hash[i] = make_hash(hash_weak_none, nil);
+ autoload_hash[i] = make_hash(hash_weak_or, nil);
prot1(&autoload_hash[i]);
}
+
+ autoload_reg_hash = make_hash(hash_weak_none, nil);
}
void autoload_init(void)
@@ -1102,15 +1069,20 @@ static val autoload_try(al_ns_t ns, val sym)
val fun = gethash(autoload_hash[ns], sym);
if (fun) {
- unsigned ds = debug_clear(opt_dbg_autoload ? 0 : DBG_ENABLE);
- val saved_dyn_env = dyn_env;
- dyn_env = make_env(nil, nil, dyn_env);
- env_vbind(dyn_env, package_s, system_package);
- env_vbind(dyn_env, package_alist_s, packages);
- funcall(fun);
- dyn_env = saved_dyn_env;
- debug_restore(ds);
- return t;
+ val check = gethash(autoload_reg_hash, fun);
+
+ if (check) {
+ unsigned ds = debug_clear(opt_dbg_autoload ? 0 : DBG_ENABLE);
+ val saved_dyn_env = dyn_env;
+ remhash(autoload_reg_hash, fun);
+ dyn_env = make_env(nil, nil, dyn_env);
+ env_vbind(dyn_env, package_s, system_package);
+ env_vbind(dyn_env, package_alist_s, packages);
+ funcall(fun);
+ dyn_env = saved_dyn_env;
+ debug_restore(ds);
+ return t;
+ }
}
return nil;
}
diff --git a/autoload.h b/autoload.h
index 23ad7883..7097583b 100644
--- a/autoload.h
+++ b/autoload.h
@@ -39,5 +39,5 @@ val autoload_try_slot(val sym);
val autoload_try_struct(val sym);
val autoload_try_keyword(val sym);
void autoload_set(al_ns_t ns, val *name, val fun);
-val autoload_reg(val (*instantiate)(val),
+val autoload_reg(val (*instantiate)(void),
val (*set_entries)(val));
diff --git a/cadr.c b/cadr.c
index 2a2ce117..97d128ec 100644
--- a/cadr.c
+++ b/cadr.c
@@ -340,9 +340,8 @@ val cdddddr(val cons)
return cdr(cdr(cdr(cdr(cdr(cons)))));
}
-static val cadr_register(val set_fun)
+static val cadr_register(void)
{
- funcall1(set_fun, nil);
reg_fun(intern(lit("caar"), user_package), func_n1(caar));
reg_fun(intern(lit("cadr"), user_package), func_n1(cadr));
reg_fun(intern(lit("cdar"), user_package), func_n1(cdar));
diff --git a/gencadr.txr b/gencadr.txr
index 42a7f435..6ed9ae5e 100644
--- a/gencadr.txr
+++ b/gencadr.txr
@@ -40,9 +40,8 @@ val c@{ad}r(val cons)
}
@ (end)
-static val cadr_register(val set_fun)
+static val cadr_register(void)
{
- funcall1(set_fun, nil);
@ (repeat)
reg_fun(intern(lit("c@{ad}r"), user_package), func_n1(c@{ad}r));
@ (end)