aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornop <nop>1997-07-07 03:24:53 +0000
committernop <nop>1997-07-07 03:24:53 +0000
commit4e8941e8c27ace0e64bb27e06cd955e2137f2ac8 (patch)
tree37904929fb883595e143fe48a51a0f4c554b79ec
parent5b0b8d4d456c535f60f2034a57097567a3d0d75f (diff)
downloadmoo-4e8941e8c27ace0e64bb27e06cd955e2137f2ac8.tar.gz
moo-4e8941e8c27ace0e64bb27e06cd955e2137f2ac8.tar.xz
moo-4e8941e8c27ace0e64bb27e06cd955e2137f2ac8.zip
Merge UNSAFE_OPTS (r5) after extensive testing.
-rw-r--r--code_gen.c16
-rw-r--r--db_io.c24
-rw-r--r--db_objects.c31
-rw-r--r--db_private.h32
-rw-r--r--db_tune.h6
-rw-r--r--db_verbs.c250
-rw-r--r--decompile.c20
-rw-r--r--eval_env.c23
-rw-r--r--execute.c28
-rw-r--r--extensions.c55
-rw-r--r--functions.c19
-rw-r--r--list.c33
-rw-r--r--objects.c15
-rw-r--r--parse_cmd.c23
-rw-r--r--program.c13
-rw-r--r--program.h14
-rw-r--r--ref_count.c15
-rw-r--r--ref_count.h18
-rw-r--r--storage.c103
-rw-r--r--storage.h35
-rw-r--r--structures.h54
-rw-r--r--tasks.c15
-rw-r--r--utils.c81
-rw-r--r--utils.h50
-rw-r--r--version.c2
25 files changed, 835 insertions, 140 deletions
diff --git a/code_gen.c b/code_gen.c
index 1501db0..5d9a388 100644
--- a/code_gen.c
+++ b/code_gen.c
@@ -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
*
diff --git a/db_io.c b/db_io.c
index 2083493..a29603e 100644
--- a/db_io.c
+++ b/db_io.c
@@ -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);
diff --git a/db_verbs.c b/db_verbs.c
index 5090c46..c626728 100644
--- a/db_verbs.c
+++ b/db_verbs.c
@@ -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
*
diff --git a/eval_env.c b/eval_env.c
index 7b28ac6..0cc627f 100644
--- a/eval_env.c
+++ b/eval_env.c
@@ -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
*
diff --git a/execute.c b/execute.c
index cbd7bd0..2e41b6c 100644
--- a/execute.c
+++ b/execute.c
@@ -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
*
diff --git a/list.c b/list.c
index 2af4ded..18fce9a 100644
--- a/list.c
+++ b/list.c
@@ -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
*
diff --git a/objects.c b/objects.c
index 76c3ac5..830266e 100644
--- a/objects.c
+++ b/objects.c
@@ -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
*
diff --git a/program.c b/program.c
index cb8de18..f6397e1 100644
--- a/program.c
+++ b/program.c
@@ -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
*
diff --git a/program.h b/program.h
index 7042301..d76abb3 100644
--- a/program.h
+++ b/program.h
@@ -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
*
diff --git a/storage.c b/storage.c
index 74a66c4..5fc74df 100644
--- a/storage.c
+++ b/storage.c
@@ -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
*
diff --git a/storage.h b/storage.h
index 1402e10..44ee986 100644
--- a/storage.h
+++ b/storage.h
@@ -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
*
diff --git a/tasks.c b/tasks.c
index 4ad2013..6a7db7e 100644
--- a/tasks.c
+++ b/tasks.c
@@ -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
*
diff --git a/utils.c b/utils.c
index 6534c62..af18f4f 100644
--- a/utils.c
+++ b/utils.c
@@ -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
*
diff --git a/utils.h b/utils.h
index d8dc08f..a462f9f 100644
--- a/utils.h
+++ b/utils.h
@@ -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 ***
*
diff --git a/version.c b/version.c
index cf4b372..c731e82 100644
--- a/version.c
+++ b/version.c
@@ -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)