diff options
author | nop <nop> | 1997-07-07 03:24:53 +0000 |
---|---|---|
committer | nop <nop> | 1997-07-07 03:24:53 +0000 |
commit | 4e8941e8c27ace0e64bb27e06cd955e2137f2ac8 (patch) | |
tree | 37904929fb883595e143fe48a51a0f4c554b79ec | |
parent | 5b0b8d4d456c535f60f2034a57097567a3d0d75f (diff) | |
download | moo-4e8941e8c27ace0e64bb27e06cd955e2137f2ac8.tar.gz moo-4e8941e8c27ace0e64bb27e06cd955e2137f2ac8.tar.xz moo-4e8941e8c27ace0e64bb27e06cd955e2137f2ac8.zip |
Merge UNSAFE_OPTS (r5) after extensive testing.
-rw-r--r-- | code_gen.c | 16 | ||||
-rw-r--r-- | db_io.c | 24 | ||||
-rw-r--r-- | db_objects.c | 31 | ||||
-rw-r--r-- | db_private.h | 32 | ||||
-rw-r--r-- | db_tune.h | 6 | ||||
-rw-r--r-- | db_verbs.c | 250 | ||||
-rw-r--r-- | decompile.c | 20 | ||||
-rw-r--r-- | eval_env.c | 23 | ||||
-rw-r--r-- | execute.c | 28 | ||||
-rw-r--r-- | extensions.c | 55 | ||||
-rw-r--r-- | functions.c | 19 | ||||
-rw-r--r-- | list.c | 33 | ||||
-rw-r--r-- | objects.c | 15 | ||||
-rw-r--r-- | parse_cmd.c | 23 | ||||
-rw-r--r-- | program.c | 13 | ||||
-rw-r--r-- | program.h | 14 | ||||
-rw-r--r-- | ref_count.c | 15 | ||||
-rw-r--r-- | ref_count.h | 18 | ||||
-rw-r--r-- | storage.c | 103 | ||||
-rw-r--r-- | storage.h | 35 | ||||
-rw-r--r-- | structures.h | 54 | ||||
-rw-r--r-- | tasks.c | 15 | ||||
-rw-r--r-- | utils.c | 81 | ||||
-rw-r--r-- | utils.h | 50 | ||||
-rw-r--r-- | version.c | 2 |
25 files changed, 835 insertions, 140 deletions
@@ -306,6 +306,9 @@ add_pseudo_label(unsigned value, State * state) f.value = value; f.prev_literals = f.prev_forks = 0; f.prev_var_refs = f.prev_labels = 0; + + f.prev_stacks = 0; + f.next = -1; add_known_fixup(f, state); @@ -332,6 +335,7 @@ capture_label(State * state) f.prev_forks = state->num_forks; f.prev_var_refs = state->num_var_refs; f.prev_labels = state->num_labels; + f.prev_stacks = state->num_stacks; f.next = -1; return f; @@ -350,6 +354,7 @@ define_label(int label, State * state) fixup->prev_forks = state->num_forks; fixup->prev_var_refs = state->num_var_refs; fixup->prev_labels = state->num_labels; + fixup->prev_stacks = state->num_stacks; label = fixup->next; } } @@ -1198,9 +1203,16 @@ generate_code(Stmt * stmt, DB_Version version) char rcsid_code_gen[] = "$Id$"; /* $Log$ -/* Revision 1.2 1997/03/03 04:18:24 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:53 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.1 1997/05/29 15:50:01 nop + * Make sure to clear prev_stacks to avoid referring to uninitialized memory + * later. (Usually multiplied by zero, so only a problem in weird circumstances.) + * + * Revision 1.2 1997/03/03 04:18:24 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:44:59 nop * LambdaMOO 1.8.0p5 * @@ -205,8 +205,9 @@ dbio_read_var(void) case TYPE_CLEAR: case TYPE_NONE: break; - case TYPE_STR: + case _TYPE_STR: r.v.str = str_dup(dbio_read_string()); + r.type |= TYPE_COMPLEX_FLAG; break; case TYPE_OBJ: case TYPE_ERR: @@ -215,10 +216,10 @@ dbio_read_var(void) case TYPE_FINALLY: r.v.num = dbio_read_num(); break; - case TYPE_FLOAT: + case _TYPE_FLOAT: r = new_float(dbio_read_float()); break; - case TYPE_LIST: + case _TYPE_LIST: l = dbio_read_num(); r = new_list(l); for (i = 0; i < l; i++) @@ -354,8 +355,8 @@ dbio_write_var(Var v) { int i; - dbio_write_num((int) v.type); - switch (v.type) { + dbio_write_num((int) v.type & TYPE_DB_MASK); + switch ((int) v.type) { case TYPE_CLEAR: case TYPE_NONE: break; @@ -403,9 +404,18 @@ dbio_write_forked_program(Program * program, int f_index) char rcsid_db_io[] = "$Id$"; /* $Log$ -/* Revision 1.2 1997/03/03 04:18:27 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:53 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.1 1997/03/20 18:07:51 bjj + * Add a flag to the in-memory type identifier so that inlines can cheaply + * identify Vars that need actual work done to ref/free/dup them. Add the + * appropriate inlines to utils.h and replace old functions in utils.c with + * complex_* functions which only handle the types with external storage. + * + * Revision 1.2 1997/03/03 04:18:27 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:44:59 nop * LambdaMOO 1.8.0p5 * diff --git a/db_objects.c b/db_objects.c index 8ff1fae..ab2c678 100644 --- a/db_objects.c +++ b/db_objects.c @@ -136,6 +136,8 @@ db_destroy_object(Objid oid) Verbdef *v, *w; int i; + db_priv_affected_callable_verb_lookup(); + if (!o) panic("DB_DESTROY_OBJECT: Invalid object!"); @@ -182,6 +184,8 @@ db_renumber_object(Objid old) Objid new; Object *o; + db_priv_affected_callable_verb_lookup(); + for (new = 0; new < old; new++) { if (objects[new] == 0) { /* Change the identity of the object. */ @@ -405,6 +409,19 @@ db_change_parent(Objid oid, Objid parent) if (!dbpriv_check_properties_for_chparent(oid, parent)) return 0; + if (objects[oid]->child == NOTHING && objects[oid]->verbdefs == NULL) { + /* Since this object has no children and no verbs, we know that it + can't have had any part in affecting verb lookup, since we use first + parent with verbs as a key in the verb lookup cache. */ + /* The "no kids" rule is necessary because potentially one of the kids + could have verbs on it--and that kid could have cache entries for + THIS object's parentage. */ + /* In any case, don't clear the cache. */ + ; + } else { + db_priv_affected_callable_verb_lookup(); + } + old_parent = objects[oid]->parent; if (old_parent != NOTHING) @@ -536,9 +553,19 @@ dbpriv_set_all_users(Var v) char rcsid_db_objects[] = "$Id$"; /* $Log$ -/* Revision 1.2 1997/03/03 04:18:29 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:53 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.2 1997/07/07 01:40:20 nop + * Because we use first-parent-with-verbs as a verb cache key, we can skip + * a generation bump if the target of a chparent has no kids and no verbs. + * + * Revision 1.2.2.1 1997/03/20 07:26:01 nop + * First pass at the new verb cache. Some ugly code inside. + * + * Revision 1.2 1997/03/03 04:18:29 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:44:59 nop * LambdaMOO 1.8.0p5 * diff --git a/db_private.h b/db_private.h index e04b3f8..c62b5d2 100644 --- a/db_private.h +++ b/db_private.h @@ -75,6 +75,28 @@ typedef struct Object { Pval *propval; } Object; +/*********** Verb cache support ***********/ + +#define VERB_CACHE 1 + +#ifdef VERB_CACHE + +/* Whenever anything is modified that could influence callable verb + * lookup, this function must be called. + */ + +#ifdef RONG +#define db_priv_affected_callable_verb_lookup() (db_verb_generation++) + /* The choice of a new generation. */ +extern unsigned int db_verb_generation; +#endif + +extern void db_priv_affected_callable_verb_lookup(void); + +#else /* no cache */ +#define db_priv_affected_callable_verb_lookup() +#endif + /*********** Objects ***********/ extern void dbpriv_set_all_users(Var); @@ -139,9 +161,15 @@ extern void dbpriv_set_dbio_input(FILE *); extern void dbpriv_set_dbio_output(FILE *); /* $Log$ -/* Revision 1.2 1997/03/03 04:18:30 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:53 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.1 1997/03/20 07:26:03 nop + * First pass at the new verb cache. Some ugly code inside. + * + * Revision 1.2 1997/03/03 04:18:30 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:45:02 nop * LambdaMOO 1.8.0p5 * diff --git a/db_tune.h b/db_tune.h new file mode 100644 index 0000000..1daab54 --- /dev/null +++ b/db_tune.h @@ -0,0 +1,6 @@ +/* This is just a stub for now; various db-layer-specific tuning functions + * will eventually live here. + */ + +extern void db_log_cache_stats(void); +extern Var db_verb_cache_stats(void); @@ -26,6 +26,9 @@ #include "config.h" #include "db.h" #include "db_private.h" +#include "db_tune.h" +#include "list.h" +#include "log.h" #include "parse_cmd.h" #include "program.h" #include "storage.h" @@ -198,6 +201,8 @@ db_add_verb(Objid oid, const char *vnames, Objid owner, unsigned flags, Object *o = dbpriv_find_object(oid); Verbdef *v, *newv; + db_priv_affected_callable_verb_lookup(); + newv = mymalloc(sizeof(Verbdef), M_VERBDEF); newv->name = vnames; newv->owner = owner; @@ -267,6 +272,8 @@ db_delete_verb(db_verb_handle vh) Object *o = dbpriv_find_object(oid); Verbdef *vv; + db_priv_affected_callable_verb_lookup(); + vv = o->verbdefs; if (vv == v) o->verbdefs = v->next; @@ -314,22 +321,224 @@ db_find_command_verb(Objid oid, const char *verb, return vh; } +#ifdef VERB_CACHE +int db_verb_generation = 0; + +int verbcache_hit = 0; +int verbcache_neg_hit = 0; +int verbcache_miss = 0; + +typedef struct vc_entry vc_entry; + +struct vc_entry { + unsigned int hash; +#ifdef RONG + int generation; +#endif + Objid oid_key; /* Note that we proceed up the parent tree + until we hit an object with verbs on it */ + char *verbname; + handle h; + struct vc_entry *next; +}; + +static vc_entry **vc_table = NULL; +static int vc_size = 0; + +#define DEFAULT_VC_SIZE 721 + +void +db_priv_affected_callable_verb_lookup(void) +{ + int i; + vc_entry *vc, *vc_next; + + if (vc_table == NULL) + return; + + db_verb_generation++; + + for (i = 0; i < vc_size; i++) { + vc = vc_table[i]; + while (vc) { + vc_next = vc->next; + free_str(vc->verbname); + myfree(vc, M_VC_ENTRY); + vc = vc_next; + } + vc_table[i] = NULL; + } +} + +static void +make_vc_table(int size) +{ + int i; + + vc_size = size; + vc_table = mymalloc(size * sizeof(vc_entry *), M_VC_TABLE); + for (i = 0; i < size; i++) { + vc_table[i] = NULL; + } +} + +#define VC_CACHE_STATS_MAX 16 + +Var +db_verb_cache_stats(void) +{ + int i, depth, histogram[VC_CACHE_STATS_MAX + 1]; + vc_entry *vc; + Var v, vv; + + for (i = 0; i < VC_CACHE_STATS_MAX + 1; i++) { + histogram[i] = 0; + } + + for (i = 0; i < vc_size; i++) { + depth = 0; + for (vc = vc_table[i]; vc; vc = vc->next) + depth++; + if (depth > VC_CACHE_STATS_MAX) + depth = VC_CACHE_STATS_MAX; + histogram[depth]++; + } + + v = new_list(5); + v.v.list[1].type = TYPE_INT; + v.v.list[1].v.num = verbcache_hit; + v.v.list[2].type = TYPE_INT; + v.v.list[2].v.num = verbcache_neg_hit; + v.v.list[3].type = TYPE_INT; + v.v.list[3].v.num = verbcache_miss; + v.v.list[4].type = TYPE_INT; + v.v.list[4].v.num = db_verb_generation; + vv = (v.v.list[5] = new_list(VC_CACHE_STATS_MAX + 1)); + for (i = 0; i < VC_CACHE_STATS_MAX + 1; i++) { + vv.v.list[i + 1].type = TYPE_INT; + vv.v.list[i + 1].v.num = histogram[i]; + } + return v; +} + +void +db_log_cache_stats(void) +{ + int i, depth, histogram[VC_CACHE_STATS_MAX + 1]; + vc_entry *vc; + + for (i = 0; i < VC_CACHE_STATS_MAX + 1; i++) { + histogram[i] = 0; + } + + for (i = 0; i < vc_size; i++) { + depth = 0; + for (vc = vc_table[i]; vc; vc = vc->next) + depth++; + if (depth > VC_CACHE_STATS_MAX) + depth = VC_CACHE_STATS_MAX; + histogram[depth]++; + } + + oklog("Verb cache stat summary: %d hits, %d misses, %d generations\n", + verbcache_hit, verbcache_miss, db_verb_generation); + oklog("Depth Count\n"); + for (i = 0; i < VC_CACHE_STATS_MAX + 1; i++) + oklog("%-5d %-5d\n", i, histogram[i]); + oklog("---\n"); +} + +#endif + db_verb_handle db_find_callable_verb(Objid oid, const char *verb) { Object *o; Verbdef *v; +#ifdef VERB_CACHE + vc_entry *new_vc; +#else static handle h; +#endif db_verb_handle vh; - for (o = dbpriv_find_object(oid); o; o = dbpriv_find_object(o->parent)) +#ifdef VERB_CACHE + unsigned int hash, bucket; + Objid first_parent_with_verbs = oid; + vc_entry *vc; + + if (vc_table == NULL) + make_vc_table(DEFAULT_VC_SIZE); + + for (o = dbpriv_find_object(oid); o; o = dbpriv_find_object(o->parent)) { + if (o->verbdefs != NULL) + break; + } + + if (o) { + first_parent_with_verbs = o->id; + } else { + first_parent_with_verbs = NOTHING; + } + + hash = str_hash(verb) ^ (~first_parent_with_verbs); /* ewww, but who cares */ + bucket = hash % vc_size; + + for (vc = vc_table[bucket]; vc; vc = vc->next) { + if (hash == vc->hash + && first_parent_with_verbs == vc->oid_key + && !mystrcasecmp(verb, vc->verbname)) { + /* we haaave a winnaaah */ + if (vc->h.verbdef) { + verbcache_hit++; + vh.ptr = &vc->h; + } else { + verbcache_neg_hit++; + vh.ptr = 0; + } + return vh; + } + } + + /* A swing and a miss. */ + verbcache_miss++; +#else + o = dbpriv_find_object(oid); +#endif + +#ifdef VERB_CACHE + /* + * Add the entry to the verbcache whether we find it or not. This means + * we do "negative caching", keeping track of failed lookups so that + * repeated failures hit the cache instead of going through a lookup. + */ + new_vc = mymalloc(sizeof(vc_entry), M_VC_ENTRY); + + new_vc->hash = hash; + new_vc->oid_key = first_parent_with_verbs; + new_vc->verbname = str_dup(verb); + new_vc->h.verbdef = NULL; + new_vc->next = vc_table[bucket]; + vc_table[bucket] = new_vc; +#endif + + for ( /* from above */ ; o; o = dbpriv_find_object(o->parent)) if ((v = find_verbdef_by_name(o, verb, 1)) != 0) { +#ifdef VERB_CACHE + new_vc->h.definer = o->id; + new_vc->h.verbdef = v; + vh.ptr = &new_vc->h; +#else h.definer = o->id; h.verbdef = v; vh.ptr = &h; - +#endif return vh; } + /* + * note that the verbcache has cleared h.verbdef, so it defaults to a + * "miss" cache if the for loop doesn't win + */ vh.ptr = 0; return vh; @@ -417,6 +626,8 @@ db_set_verb_names(db_verb_handle vh, const char *names) { handle *h = (handle *) vh.ptr; + db_priv_affected_callable_verb_lookup(); + if (h) { if (h->verbdef->name) free_str(h->verbdef->name); @@ -465,6 +676,8 @@ db_set_verb_flags(db_verb_handle vh, unsigned flags) { handle *h = (handle *) vh.ptr; + db_priv_affected_callable_verb_lookup(); + if (h) { h->verbdef->perms &= ~PERMMASK; h->verbdef->perms |= flags; @@ -491,6 +704,10 @@ db_set_verb_program(db_verb_handle vh, Program * program) { handle *h = (handle *) vh.ptr; + /* Not necessary, since this was only here to cope with nonprogrammed verbs, and that turns out to be handled properly in modern servers. */ + + /* db_priv_affected_callable_verb_lookup(); */ + if (h) { if (h->verbdef->program) free_program(h->verbdef->program); @@ -519,6 +736,8 @@ db_set_verb_arg_specs(db_verb_handle vh, { handle *h = (handle *) vh.ptr; + db_priv_affected_callable_verb_lookup(); + if (h) { h->verbdef->perms = ((h->verbdef->perms & PERMMASK) | (dobj << DOBJSHIFT) @@ -540,9 +759,32 @@ db_verb_allows(db_verb_handle h, Objid progr, db_verb_flag flag) char rcsid_db_verbs[] = "$Id$"; /* $Log$ -/* Revision 1.2 1997/03/03 04:18:31 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:53 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.5 1997/07/07 01:41:20 nop + * set_verb_code() doesn't really need a verb generation bump. + * + * Revision 1.2.2.4 1997/06/05 08:38:37 bjj + * Tweak nop's verbcache by moving an actual handle into vc_entry to avoid the + * copy after the lookup. Also, keep verbs that aren't found in the cache so + * repeated calls to nonexistant verbs benefit from caching as well (need to + * watch the new field in verb_cache_stats()[2] to see how often this is useful). + * + * Revision 1.2.2.3 1997/05/29 11:56:21 nop + * Added Jason Maltzen's builtin to return a list version of cache stats. + * + * Revision 1.2.2.2 1997/03/22 22:54:36 bjj + * Tiny tweak to db_find_callable_verb to avoid recomputing the first parent + * with verbdefs. Also hit it with indent, which made these diffs bigger than + * they should have been... + * + * Revision 1.2.2.1 1997/03/20 07:26:03 nop + * First pass at the new verb cache. Some ugly code inside. + * + * Revision 1.2 1997/03/03 04:18:31 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:44:59 nop * LambdaMOO 1.8.0p5 * diff --git a/decompile.c b/decompile.c index c9e0265..d78c652 100644 --- a/decompile.c +++ b/decompile.c @@ -963,7 +963,12 @@ find_hot_node(Stmt * stmt) int find_line_number(Program * prog, int vector, int pc) { - Stmt *tree = program_to_tree(prog, MAIN_VECTOR, vector, pc); + Stmt *tree; + + if (prog->cached_lineno_pc == pc) + return prog->cached_lineno; + + tree = program_to_tree(prog, MAIN_VECTOR, vector, pc); lineno = prog->first_lineno; find_hot_node(tree); @@ -972,15 +977,24 @@ find_line_number(Program * prog, int vector, int pc) if (!hot_node && hot_position != DONE) panic("Can't do job in FIND_LINE_NUMBER!"); + prog->cached_lineno_pc = pc; + prog->cached_lineno = lineno; return lineno; } char rcsid_decompile[] = "$Id$"; /* $Log$ -/* Revision 1.2 1997/03/03 04:18:32 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:53 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.1 1997/06/05 09:00:00 bjj + * Cache one pc/lineno pair with each Program. Hopefully most programs that + * fail multiple times usually do it on the same line! + * + * Revision 1.2 1997/03/03 04:18:32 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:44:59 nop * LambdaMOO 1.8.0p5 * @@ -82,17 +82,17 @@ fill_in_rt_consts(Var * env, DB_Version version) env[SLOT_ERR] = var_ref(v); v.v.num = (int) TYPE_INT; env[SLOT_NUM] = var_ref(v); - v.v.num = (int) TYPE_STR; + v.v.num = (int) _TYPE_STR; env[SLOT_STR] = var_ref(v); v.v.num = (int) TYPE_OBJ; env[SLOT_OBJ] = var_ref(v); - v.v.num = (int) TYPE_LIST; + v.v.num = (int) _TYPE_LIST; env[SLOT_LIST] = var_ref(v); if (version >= DBV_Float) { v.v.num = (int) TYPE_INT; env[SLOT_INT] = var_ref(v); - v.v.num = (int) TYPE_FLOAT; + v.v.num = (int) _TYPE_FLOAT; env[SLOT_FLOAT] = var_ref(v); } } @@ -124,11 +124,20 @@ set_rt_env_var(Var * env, int slot, Var v) char rcsid_rt_env[] = "$Id$"; /* $Log$ -/* Revision 1.3 1997/03/05 08:41:50 bjj -/* A few malloc-friendly changes: rt_stacks are now centrally allocated/freed -/* so that we can keep a pool of them handy. rt_envs are similarly pooled. -/* Both revert to malloc/free for large requests. +/* Revision 1.4 1997/07/07 03:24:53 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.3.2.1 1997/03/20 18:07:50 bjj + * Add a flag to the in-memory type identifier so that inlines can cheaply + * identify Vars that need actual work done to ref/free/dup them. Add the + * appropriate inlines to utils.h and replace old functions in utils.c with + * complex_* functions which only handle the types with external storage. + * + * Revision 1.3 1997/03/05 08:41:50 bjj + * A few malloc-friendly changes: rt_stacks are now centrally allocated/freed + * so that we can keep a pool of them handy. rt_envs are similarly pooled. + * Both revert to malloc/free for large requests. + * * Revision 1.2 1997/03/03 04:18:35 nop * GNU Indent normalization * @@ -1351,6 +1351,8 @@ do { \ db_prop_handle h; h = db_find_property(obj.v.obj, propname.v.str, &prop); + free_var(propname); + free_var(obj); if (!h.ptr) PUSH_ERROR(E_PROPNF); else if (h.built_in @@ -1361,8 +1363,6 @@ do { \ PUSH(prop); /* it's already freshly allocated */ else PUSH_REF(prop); - free_var(propname); - free_var(obj); } } break; @@ -1476,6 +1476,8 @@ do { \ } } + free_var(propname); + free_var(obj); if (err == E_NONE) { db_set_property_value(h, var_ref(rhs)); PUSH(rhs); @@ -1483,8 +1485,6 @@ do { \ free_var(rhs); PUSH_ERROR(err); } - free_var(propname); - free_var(obj); } } break; @@ -2819,12 +2819,22 @@ read_activ(activation * a, int which_vector) char rcsid_execute[] = "$Id$"; /* $Log$ -/* Revision 1.7 1997/03/21 13:23:23 bjj -/* Reorganize the top of run() slightly to make it slightly more efficient -/* (we do execute it billions of times, after all). Later we'll want to -/* get rid of if (task_killed) by introducing BI_KILL or by moving it into -/* the BI_FUNC_CALL case, at least. +/* Revision 1.8 1997/07/07 03:24:54 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.7 1997/03/21 13:23:23 bjj + * Reorganize the top of run() slightly to make it slightly more efficient + * (we do execute it billions of times, after all). Later we'll want to + * get rid of if (task_killed) by introducing BI_KILL or by moving it into + * the BI_FUNC_CALL case, at least. + * + * Revision 1.6.2.2 1997/05/24 07:08:37 bjj + * Cleanup of Jay's last checkin to avoid some code duplication. + * + * Revision 1.6.2.1 1997/05/23 07:03:44 nop + * Failure during property lookups/stores sometimes fails to free the string + * containing the property name. (PUSH_ERROR() may return immediately.) + * * Revision 1.6 1997/03/08 06:25:39 nop * 1.8.0p6 merge by hand. * diff --git a/extensions.c b/extensions.c index 1d118f2..07883c6 100644 --- a/extensions.c +++ b/extensions.c @@ -34,6 +34,7 @@ #include "bf_register.h" #include "functions.h" +#include "db_tune.h" #if EXAMPLE @@ -138,6 +139,40 @@ bf_read_stdin(Var arglist, Byte next, void *vdata, Objid progr) } #endif /* EXAMPLE */ +#define STUPID_VERB_CACHE 1 +#ifdef STUPID_VERB_CACHE +#include "utils.h" + +static package +bf_verb_cache_stats(Var arglist, Byte next, void *vdata, Objid progr) +{ + Var r; + + free_var(arglist); + + if (!is_wizard(progr)) { + return make_error_pack(E_PERM); + } + r = db_verb_cache_stats(); + + return make_var_pack(r); +} + +static package +bf_log_cache_stats(Var arglist, Byte next, void *vdata, Objid progr) +{ + free_var(arglist); + + if (!is_wizard(progr)) { + return make_error_pack(E_PERM); + } + db_log_cache_stats(); + + return no_var_pack(); +} +#endif + + void register_extensions() { @@ -145,14 +180,30 @@ register_extensions() register_task_queue(stdin_enumerator); register_function("read_stdin", 0, 0, bf_read_stdin); #endif +#ifdef STUPID_VERB_CACHE + register_function("log_cache_stats", 0, 0, bf_log_cache_stats); + register_function("verb_cache_stats", 0, 0, bf_verb_cache_stats); +#endif } char rcsid_extensions[] = "$Id$"; /* $Log$ -/* Revision 1.2 1997/03/03 04:18:41 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:54 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.3 1997/05/29 11:56:22 nop + * Added Jason Maltzen's builtin to return a list version of cache stats. + * + * Revision 1.2.2.2 1997/03/20 18:08:29 bjj + * add #include "utils.h" to get new inline free_var + * + * Revision 1.2.2.1 1997/03/20 07:26:04 nop + * First pass at the new verb cache. Some ugly code inside. + * + * Revision 1.2 1997/03/03 04:18:41 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:45:00 nop * LambdaMOO 1.8.0p5 * diff --git a/functions.c b/functions.c index 6a0136d..fdca898 100644 --- a/functions.c +++ b/functions.c @@ -386,8 +386,9 @@ function_description(int i) nargs = entry.maxargs == -1 ? entry.minargs : entry.maxargs; vv = v.v.list[4] = new_list(nargs); for (j = 0; j < nargs; j++) { + int proto = entry.prototype[j]; vv.v.list[j + 1].type = TYPE_INT; - vv.v.list[j + 1].v.num = entry.prototype[j]; + vv.v.list[j + 1].v.num = proto < 0 ? proto : (proto & TYPE_DB_MASK); } return v; @@ -456,10 +457,20 @@ register_functions(void) char rcsid_functions[] = "$Id$"; /* $Log$ -/* Revision 1.3 1997/03/03 05:03:50 nop -/* steak2: move protectedness into builtin struct, load_server_options() -/* now required for $server_options updates. +/* Revision 1.4 1997/07/07 03:24:54 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.3.2.2 1997/05/12 04:03:21 bjj + * This time for sure! + * + * Revision 1.3.2.1 1997/05/11 04:31:54 bjj + * Missed the place in bf_function_info where TYPE_* constants make it into + * the database. Masked off the complex flag in the obvious place. + * + * Revision 1.3 1997/03/03 05:03:50 nop + * steak2: move protectedness into builtin struct, load_server_options() + * now required for $server_options updates. + * * Revision 1.2 1997/03/03 04:18:42 nop * GNU Indent normalization * @@ -108,8 +108,15 @@ doinsert(Var list, Var value, int pos) { Var new; int i; + int size = list.v.list[0].v.num + 1; - new = new_list(list.v.list[0].v.num + 1); + if (var_refcount(list) == 1 && pos == size) { + list.v.list = (Var *) myrealloc(list.v.list, (size + 1) * sizeof(Var), M_LIST); + list.v.list[0].v.num = size; + list.v.list[pos] = value; + return list; + } + new = new_list(size); for (i = 1; i < pos; i++) new.v.list[i] = var_ref(list.v.list[i]); new.v.list[pos] = value; @@ -697,6 +704,7 @@ get_pattern(const char *string, int case_matters) free_pattern(entry->pattern); } entry->pattern = new_pattern(string, case_matters); + entry->case_matters = case_matters; if (!entry->pattern.ptr) entry->string = 0; else @@ -987,7 +995,7 @@ bf_decode_binary(Var arglist, Byte next, void *vdata, Objid progr) r = new_list(length); for (i = 1; i <= length; i++) { r.v.list[i].type = TYPE_INT; - r.v.list[i].v.num = bytes[i - 1]; + r.v.list[i].v.num = (unsigned char) bytes[i - 1]; } } else { static Stream *s = 0; @@ -1130,9 +1138,26 @@ register_list(void) char rcsid_list[] = "$Id$"; /* $Log$ -/* Revision 1.3 1997/03/03 06:20:04 bjj -/* new_list(0) now returns the same empty list to every caller +/* Revision 1.4 1997/07/07 03:24:54 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.3.2.3 1997/07/03 08:04:01 bjj + * Pattern cache was not storing case_matters flag, causing many patterns to + * be impossible to find in the cache. + * + * Revision 1.3.2.2 1997/05/20 14:55:52 nop + * Include Jason's patch for bf_decode_binary losing on systems where + * char is signed. + * + * Revision 1.3.2.1 1997/03/21 15:22:56 bjj + * doinsert reallocs for appending to refcnt 1 lists. note that this wins + * because it avoids all the var_ref/free_var that's done in the general case, + * not because it avoids malloc/free. the general case could also benefit from + * using memcpy when the refcnt is 1, rather than looping with var_ref. + * + * Revision 1.3 1997/03/03 06:20:04 bjj + * new_list(0) now returns the same empty list to every caller + * * Revision 1.2 1997/03/03 04:18:46 nop * GNU Indent normalization * @@ -206,7 +206,7 @@ bf_typeof(Var arglist, Byte next, void *vdata, Objid progr) { Var r; r.type = TYPE_INT; - r.v.num = (int) arglist.v.list[1].type; + r.v.num = (int) arglist.v.list[1].type & TYPE_DB_MASK; free_var(arglist); return make_var_pack(r); } @@ -621,9 +621,18 @@ register_objects(void) char rcsid_objects[] = "$Id$"; /* $Log$ -/* Revision 1.2 1997/03/03 04:19:12 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:54 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.1 1997/03/20 18:07:50 bjj + * Add a flag to the in-memory type identifier so that inlines can cheaply + * identify Vars that need actual work done to ref/free/dup them. Add the + * appropriate inlines to utils.h and replace old functions in utils.c with + * complex_* functions which only handle the types with external storage. + * + * Revision 1.2 1997/03/03 04:19:12 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:45:01 nop * LambdaMOO 1.8.0p5 * diff --git a/parse_cmd.c b/parse_cmd.c index c395df3..d93a23d 100644 --- a/parse_cmd.c +++ b/parse_cmd.c @@ -40,7 +40,7 @@ parse_into_words(char *input, int *nwords) if (!words) { max_words = 50; - words = mymalloc(max_words * sizeof(char *), M_STRING); + words = mymalloc(max_words * sizeof(char *), M_STRING_PTRS); } while (*input == ' ') input++; @@ -48,13 +48,13 @@ parse_into_words(char *input, int *nwords) for (*nwords = 0; *input != '\0'; (*nwords)++) { if (*nwords == max_words) { int new_max = max_words * 2; - char **new = mymalloc(new_max * sizeof(char *), M_STRING); + char **new = mymalloc(new_max * sizeof(char *), M_STRING_PTRS); int i; for (i = 0; i < max_words; i++) new[i] = words[i]; - myfree(words, M_STRING); + myfree(words, M_STRING_PTRS); words = new; max_words = new_max; } @@ -252,9 +252,22 @@ free_parsed_command(Parsed_Command * pc) char rcsid_parse_cmd[] = "$Id$"; /* $Log$ -/* Revision 1.2 1997/03/03 04:19:14 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:54 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.2 1997/05/30 18:36:17 nop + * Oops, make sure to free words as M_STRING_PTRS, not M_STRING. I crashed + * LambdaMOO for the first time with this! + * + * Revision 1.2.2.1 1997/05/20 03:01:34 nop + * parse_into_words was allocating pointers to strings as strings. Predictably, + * the refcount prepend code was not prepared for this, causing unaligned memory + * access on the Alpha. Added new M_STRING_PTRS allocation class that could + * be renamed to something better, perhaps. + * + * Revision 1.2 1997/03/03 04:19:14 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:45:01 nop * LambdaMOO 1.8.0p5 * @@ -31,6 +31,8 @@ new_program(void) p->ref_count = 1; p->first_lineno = 1; + p->cached_lineno = 1; + p->cached_lineno_pc = 0; return p; } @@ -113,9 +115,16 @@ free_program(Program * p) char rcsid_program[] = "$Id$"; /* $Log$ -/* Revision 1.3 1997/03/08 06:25:42 nop -/* 1.8.0p6 merge by hand. +/* Revision 1.4 1997/07/07 03:24:54 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.3.2.1 1997/06/05 09:00:00 bjj + * Cache one pc/lineno pair with each Program. Hopefully most programs that + * fail multiple times usually do it on the same line! + * + * Revision 1.3 1997/03/08 06:25:42 nop + * 1.8.0p6 merge by hand. + * * Revision 1.2 1997/03/03 04:19:17 nop * GNU Indent normalization * @@ -46,6 +46,9 @@ typedef struct { unsigned num_var_names; const char **var_names; + + unsigned cached_lineno; + unsigned cached_lineno_pc; } Program; #define MAIN_VECTOR -1 /* As opposed to an index into fork_vectors */ @@ -59,9 +62,16 @@ extern void free_program(Program *); #endif /* !Program_H */ /* $Log$ -/* Revision 1.2 1997/03/03 04:19:18 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:55 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.1 1997/06/05 09:00:01 bjj + * Cache one pc/lineno pair with each Program. Hopefully most programs that + * fail multiple times usually do it on the same line! + * + * Revision 1.2 1997/03/03 04:19:18 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:45:04 nop * LambdaMOO 1.8.0p5 * diff --git a/ref_count.c b/ref_count.c index 89a47b3..eb820da 100644 --- a/ref_count.c +++ b/ref_count.c @@ -20,6 +20,8 @@ #include "ref_count.h" #include "storage.h" +#if 0 + typedef struct reftab_entry { struct reftab_entry *next; const void *p; @@ -204,13 +206,22 @@ delref(const void *p) index = key(p); return ll_delete_value(&(ref_table[index]), p); } +#endif char rcsid_ref_count[] = "$Id$"; /* $Log$ -/* Revision 1.2 1997/03/03 04:19:21 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:55 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.1 1997/03/20 18:59:24 bjj + * Allocate refcounts with objects that can be addref()'d (strings, lists, + * floats). Use macros to manipulate those counts. This completely replaces + * the external hash table addref and friends. + * + * Revision 1.2 1997/03/03 04:19:21 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:45:01 nop * LambdaMOO 1.8.0p5 * diff --git a/ref_count.h b/ref_count.h index e2d47bc..ab4f332 100644 --- a/ref_count.h +++ b/ref_count.h @@ -17,13 +17,27 @@ #include "config.h" +#if 0 extern void addref(const void *p); extern unsigned int delref(const void *p); +#else +#define addref(X) (++((int *)(X))[-1]) +#define delref(X) (--((int *)(X))[-1]) +#define refcount(X) (((int *)(X))[-1]) +#endif /* $Log$ -/* Revision 1.2 1997/03/03 04:19:21 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:55 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.1 1997/03/20 18:59:25 bjj + * Allocate refcounts with objects that can be addref()'d (strings, lists, + * floats). Use macros to manipulate those counts. This completely replaces + * the external hash table addref and friends. + * + * Revision 1.2 1997/03/03 04:19:21 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:45:04 nop * LambdaMOO 1.8.0p5 * @@ -24,34 +24,50 @@ #include "ref_count.h" #include "storage.h" #include "structures.h" +#include "utils.h" static unsigned alloc_num[Sizeof_Memory_Type]; #ifdef USE_GNU_MALLOC static unsigned alloc_size[Sizeof_Memory_Type], alloc_real_size[Sizeof_Memory_Type]; #endif +static inline int +refcount_overhead(Memory_Type type) +{ + /* These are the only allocation types that are addref()'d. + * As long as we're living on the wild side, avoid getting the + * refcount slot for allocations that won't need it. + */ + switch (type) { + case M_FLOAT: + /* for systems with picky double alignment */ + return MAX(sizeof(int), sizeof(double)); + case M_STRING: + return sizeof(int); + case M_LIST: + /* for systems with picky pointer alignment */ + return MAX(sizeof(int), sizeof(Var *)); + default: + return 0; + } +} + void * mymalloc(unsigned size, Memory_Type type) { - void *memptr; + char *memptr; char msg[100]; + int offs; if (size == 0) /* For queasy systems */ size = 1; - memptr = (void *) malloc(size -#ifdef FIND_LEAKS - + 8 -#endif - ); + offs = refcount_overhead(type); + memptr = (char *) malloc(size + offs); if (!memptr) { sprintf(msg, "memory allocation (size %u) failed!", size); panic(msg); } -#ifdef FIND_LEAKS - *((int *) memptr) = type; -#endif - alloc_num[type]++; #ifdef USE_GNU_MALLOC { @@ -63,11 +79,11 @@ mymalloc(unsigned size, Memory_Type type) } #endif -#ifdef FIND_LEAKS - return ((char *) memptr) + 8; -#else + if (offs) { + memptr += offs; + ((int *) memptr)[-1] = 1; + } return memptr; -#endif } const char * @@ -98,16 +114,39 @@ str_dup(const char *s) return r; } -void -myfree(void *ptr, Memory_Type type) +void * +myrealloc(void *ptr, unsigned size, Memory_Type type) { -#ifdef FIND_LEAKS - ptr = ((char *) ptr) - 8; + int offs = refcount_overhead(type); + static char msg[100]; - if (*((int *) ptr) != type) - abort(); +#ifdef USE_GNU_MALLOC + { + extern unsigned malloc_real_size(void *ptr); + extern unsigned malloc_size(void *ptr); + + alloc_size[type] -= malloc_size(ptr); + alloc_real_size[type] -= malloc_real_size(ptr); #endif + ptr = realloc((char *) ptr - offs, size + offs); + if (!ptr) { + sprintf(msg, "memory re-allocation (size %u) failed!", size); + panic(msg); + } + +#ifdef USE_GNU_MALLOC + alloc_size[type] += malloc_size(ptr); + alloc_real_size[type] += malloc_real_size(ptr); + } +#endif + + return (char *)ptr + offs; +} + +void +myfree(void *ptr, Memory_Type type) +{ alloc_num[type]--; #ifdef USE_GNU_MALLOC { @@ -119,7 +158,7 @@ myfree(void *ptr, Memory_Type type) } #endif - free(ptr); + free((char *) ptr - refcount_overhead(type)); } #ifdef USE_GNU_MALLOC @@ -132,12 +171,15 @@ struct mstats_value { extern struct mstats_value malloc_stats(int size); #endif +/* XXX stupid fix for non-gcc compilers, already in storage.h */ +#ifdef NEVER void free_str(const char *s) { if (delref(s) == 0) myfree((void *) s, M_STRING); } +#endif Var memory_usage(void) @@ -182,9 +224,24 @@ memory_usage(void) char rcsid_storage[] = "$Id$"; /* $Log$ -/* Revision 1.3 1997/03/03 06:32:10 bjj -/* str_dup("") now returns the same empty string to every caller +/* Revision 1.4 1997/07/07 03:24:55 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.3.2.3 1997/05/29 20:47:32 nop + * Stupid hack to allow non-gcc compilers to use -Dinline= to make the server + * compile. + * + * Revision 1.3.2.2 1997/03/21 15:19:23 bjj + * add myrealloc interface, inline free_str + * + * Revision 1.3.2.1 1997/03/20 18:59:26 bjj + * Allocate refcounts with objects that can be addref()'d (strings, lists, + * floats). Use macros to manipulate those counts. This completely replaces + * the external hash table addref and friends. + * + * Revision 1.3 1997/03/03 06:32:10 bjj + * str_dup("") now returns the same empty string to every caller + * * Revision 1.2 1997/03/03 04:19:26 nop * GNU Indent normalization * @@ -20,6 +20,7 @@ #include "config.h" #include "structures.h" +#include "ref_count.h" typedef enum Memory_Type { M_AST_POOL, M_AST, M_PROGRAM, M_PVAL, M_NETWORK, M_STRING, M_VERBDEF, @@ -31,7 +32,7 @@ typedef enum Memory_Type { M_RT_STACK, M_RT_ENV, M_BI_FUNC_DATA, M_VM, - M_REF_ENTRY, M_REF_TABLE, + M_REF_ENTRY, M_REF_TABLE, M_VC_ENTRY, M_VC_TABLE, M_STRING_PTRS, Sizeof_Memory_Type @@ -39,18 +40,44 @@ typedef enum Memory_Type { extern char *str_dup(const char *); extern const char *str_ref(const char *); -extern void free_str(const char *); extern Var memory_usage(void); extern void myfree(void *where, Memory_Type type); extern void *mymalloc(unsigned size, Memory_Type type); +extern void *myrealloc(void *where, unsigned size, Memory_Type type); + +static inline void /* XXX was extern, fix for non-gcc compilers */ +free_str(const char *s) +{ + if (delref(s) == 0) + myfree((void *) s, M_STRING); +} #endif /* Storage_h */ /* $Log$ -/* Revision 1.2 1997/03/03 04:19:27 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:55 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.4 1997/05/29 20:47:33 nop + * Stupid hack to allow non-gcc compilers to use -Dinline= to make the server + * compile. + * + * Revision 1.2.2.3 1997/05/20 03:01:34 nop + * parse_into_words was allocating pointers to strings as strings. Predictably, + * the refcount prepend code was not prepared for this, causing unaligned memory + * access on the Alpha. Added new M_STRING_PTRS allocation class that could + * be renamed to something better, perhaps. + * + * Revision 1.2.2.2 1997/03/21 15:19:24 bjj + * add myrealloc interface, inline free_str + * + * Revision 1.2.2.1 1997/03/20 07:26:04 nop + * First pass at the new verb cache. Some ugly code inside. + * + * Revision 1.2 1997/03/03 04:19:27 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:45:04 nop * LambdaMOO 1.8.0p5 * diff --git a/structures.h b/structures.h index c76bae8..d6ff260 100644 --- a/structures.h +++ b/structures.h @@ -48,19 +48,49 @@ enum error { * raw form in the DB. */ typedef enum { - TYPE_INT, TYPE_OBJ, TYPE_STR, TYPE_ERR, TYPE_LIST, /* user-visible */ + TYPE_INT, TYPE_OBJ, _TYPE_STR, TYPE_ERR, _TYPE_LIST, /* user-visible */ TYPE_CLEAR, /* in clear properties' value slot */ TYPE_NONE, /* in uninitialized MOO variables */ TYPE_CATCH, /* on-stack marker for an exception handler */ TYPE_FINALLY, /* on-stack marker for a TRY-FINALLY clause */ - TYPE_FLOAT /* floating-point number; user-visible */ + _TYPE_FLOAT /* floating-point number; user-visible */ } var_type; +/* Types which have external data should be marked with the TYPE_COMPLEX_FLAG + * so that free_var/var_ref/var_dup can recognize them easily. This flag is + * only set in memory. The original _TYPE values are used in the database + * file and returned to verbs calling typeof(). This allows the inlines to + * be extremely cheap (both in space and time) for simple types like oids + * and ints. + */ +#define TYPE_DB_MASK 0x7f +#define TYPE_COMPLEX_FLAG 0x80 + +#define TYPE_STR (_TYPE_STR | TYPE_COMPLEX_FLAG) +#define TYPE_FLOAT (_TYPE_FLOAT | TYPE_COMPLEX_FLAG) +#define TYPE_LIST (_TYPE_LIST | TYPE_COMPLEX_FLAG) + #define TYPE_ANY ((var_type) -1) /* wildcard for use in declaring built-ins */ #define TYPE_NUMERIC ((var_type) -2) /* wildcard for (integer or float) */ typedef struct Var Var; +/* Experimental. On the Alpha, DEC cc allows us to specify certain + * pointers to be 32 bits, but only if we compile and link with "-taso + * -xtaso" in CFLAGS, which limits us to a 31-bit address space. This + * could be a win if your server is thrashing. Running JHM's db, SIZE + * went from 50M to 42M. No doubt these pragmas could be applied + * elsewhere as well, but I know this at least manages to load and run + * a non-trivial db. + */ + +/* #define SHORT_ALPHA_VAR_POINTERS 1 */ + +#ifdef SHORT_ALPHA_VAR_POINTERS +#pragma pointer_size save +#pragma pointer_size short +#endif + struct Var { union { const char *str; /* STR */ @@ -73,14 +103,30 @@ struct Var { var_type type; }; +#ifdef SHORT_ALPHA_VAR_POINTERS +#pragma pointer_size restore +#endif + extern Var zero; /* useful constant */ #endif /* !Structures_h */ /* $Log$ -/* Revision 1.2 1997/03/03 04:19:29 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:55 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.2 1997/05/23 07:01:30 nop + * Added experimental support for 32-bit pointer model on Alpha with DEC cc. + * + * Revision 1.2.2.1 1997/03/20 18:07:52 bjj + * Add a flag to the in-memory type identifier so that inlines can cheaply + * identify Vars that need actual work done to ref/free/dup them. Add the + * appropriate inlines to utils.h and replace old functions in utils.c with + * complex_* functions which only handle the types with external storage. + * + * Revision 1.2 1997/03/03 04:19:29 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:45:04 nop * LambdaMOO 1.8.0p5 * @@ -319,9 +319,12 @@ free_task(task * t, int strong) free_str(t->t.input.string); break; case TASK_FORKED: - if (strong) + if (strong) { free_rt_env(t->t.forked.rt_env, t->t.forked.program->num_var_names); + free_str(t->t.forked.a.verb); + free_str(t->t.forked.a.verbname); + } free_program(t->t.forked.program); break; case TASK_SUSPENDED: @@ -1937,9 +1940,15 @@ register_tasks(void) char rcsid_tasks[] = "$Id$"; /* $Log$ -/* Revision 1.3 1997/03/08 06:25:43 nop -/* 1.8.0p6 merge by hand. +/* Revision 1.4 1997/07/07 03:24:55 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.3.2.1 1997/05/21 03:41:34 bjj + * Fix a memleak when a forked task was killed before it ever started. + * + * Revision 1.3 1997/03/08 06:25:43 nop + * 1.8.0p6 merge by hand. + * * Revision 1.2 1997/03/03 04:19:31 nop * GNU Indent normalization * @@ -133,7 +133,7 @@ str_hash(const char *s) } void -free_var(Var v) +complex_free_var(Var v) { int i; @@ -144,8 +144,10 @@ free_var(Var v) break; case TYPE_LIST: if (delref(v.v.list) == 0) { - for (i = 1; i <= v.v.list[0].v.num; i++) - free_var(v.v.list[i]); + Var *pv; + + for (i = v.v.list[0].v.num, pv = v.v.list + 1; i > 0; i--, pv++) + free_var(*pv); myfree(v.v.list, M_LIST); } break; @@ -153,22 +155,11 @@ free_var(Var v) if (delref(v.v.fnum) == 0) myfree(v.v.fnum, M_FLOAT); break; - case TYPE_INT: - case TYPE_OBJ: - case TYPE_ERR: - case TYPE_CLEAR: - case TYPE_NONE: - case TYPE_CATCH: - case TYPE_FINALLY: - break; - default: - panic("FREE_VAR: Unknown value type"); - break; } } Var -var_ref(Var v) +complex_var_ref(Var v) { switch ((int) v.type) { case TYPE_STR: @@ -180,22 +171,12 @@ var_ref(Var v) case TYPE_FLOAT: addref(v.v.fnum); break; - case TYPE_INT: - case TYPE_OBJ: - case TYPE_ERR: - case TYPE_CLEAR: - case TYPE_NONE: - case TYPE_CATCH: - case TYPE_FINALLY: - break; - default: - panic("VAR_REF: Unknown value type"); } return v; } Var -var_dup(Var v) +complex_var_dup(Var v) { int i; Var newlist; @@ -214,19 +195,30 @@ var_dup(Var v) case TYPE_FLOAT: v = new_float(*v.v.fnum); break; - case TYPE_INT: - case TYPE_OBJ: - case TYPE_ERR: - case TYPE_NONE: - case TYPE_CATCH: - case TYPE_FINALLY: - break; - default: - panic("VAR_DUP: Unknown value type"); } return v; } +/* could be inlined and use complex_etc like the others, but this should + * usually be called in a context where we already konw the type. + */ +int +var_refcount(Var v) +{ + switch ((int) v.type) { + case TYPE_STR: + return refcount(v.v.str); + break; + case TYPE_LIST: + return refcount(v.v.list); + break; + case TYPE_FLOAT: + return refcount(v.v.fnum); + break; + } + return 1; +} + int is_true(Var v) { @@ -444,9 +436,24 @@ binary_to_raw_bytes(const char *binary, int *buflen) char rcsid_utils[] = "$Id$"; /* $Log$ -/* Revision 1.2 1997/03/03 04:19:36 nop -/* GNU Indent normalization +/* Revision 1.3 1997/07/07 03:24:55 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.2.2.3 1997/03/21 15:11:22 bjj + * add var_refcount interface + * + * Revision 1.2.2.2 1997/03/21 14:29:03 bjj + * Some code bumming in complex_free_var (3rd most expensive function!) + * + * Revision 1.2.2.1 1997/03/20 18:07:48 bjj + * Add a flag to the in-memory type identifier so that inlines can cheaply + * identify Vars that need actual work done to ref/free/dup them. Add the + * appropriate inlines to utils.h and replace old functions in utils.c with + * complex_* functions which only handle the types with external storage. + * + * Revision 1.2 1997/03/03 04:19:36 nop + * GNU Indent normalization + * * Revision 1.1.1.1 1997/03/03 03:45:01 nop * LambdaMOO 1.8.0p5 * @@ -37,9 +37,35 @@ extern int verbcasecmp(const char *verb, const char *word); extern unsigned str_hash(const char *); -extern void free_var(Var); -extern Var var_dup(Var); -extern Var var_ref(Var); +extern void complex_free_var(Var); +extern Var complex_var_ref(Var); +extern Var complex_var_dup(Var); +extern int var_refcount(Var); + +static inline void +free_var(Var v) +{ + if (v.type & TYPE_COMPLEX_FLAG) + complex_free_var(v); +} + +static inline Var +var_ref(Var v) +{ + if (v.type & TYPE_COMPLEX_FLAG) + return complex_var_ref(v); + else + return v; +} + +static inline Var +var_dup(Var v) +{ + if (v.type & TYPE_COMPLEX_FLAG) + return complex_var_dup(v); + else + return v; +} extern int equality(Var lhs, Var rhs, int case_matters); extern int is_true(Var v); @@ -59,10 +85,22 @@ extern const char *binary_to_raw_bytes(const char *binary, int *rawlen); #endif /* $Log$ -/* Revision 1.4 1997/03/05 08:20:51 bjj -/* With 1.2 (oops) add MIN/MAX macros that do the obvious thing, with undef to -/* avoid clashing with system definitions. +/* Revision 1.5 1997/07/07 03:24:55 nop +/* Merge UNSAFE_OPTS (r5) after extensive testing. /* + * Revision 1.4.2.2 1997/03/21 15:11:22 bjj + * add var_refcount interface + * + * Revision 1.4.2.1 1997/03/20 18:07:49 bjj + * Add a flag to the in-memory type identifier so that inlines can cheaply + * identify Vars that need actual work done to ref/free/dup them. Add the + * appropriate inlines to utils.h and replace old functions in utils.c with + * complex_* functions which only handle the types with external storage. + * + * Revision 1.4 1997/03/05 08:20:51 bjj + * With 1.2 (oops) add MIN/MAX macros that do the obvious thing, with undef to + * avoid clashing with system definitions. + * * Revision 1.3 1997/03/05 08:15:55 bjj * *** empty log message *** * @@ -40,7 +40,7 @@ #include "config.h" #include "version.h" -const char *server_version = "1.8.0p6"; +const char *server_version = "1.8.0r3"; int check_version(DB_Version version) |