Special variable bindings using a thread-local array instead of a hash table.
authorJuan Jose Garcia Ripoll <jjgarcia@jjgr-2.local>
Fri, 22 Jan 2010 16:47:10 +0000 (17:47 +0100)
committerJuan Jose Garcia Ripoll <jjgarcia@jjgr-2.local>
Fri, 22 Jan 2010 16:47:10 +0000 (17:47 +0100)
src/c/all_symbols.d
src/c/alloc_2.d
src/c/main.d
src/c/stacks.d
src/c/symbol.d
src/c/threads.d
src/c/unixint.d
src/h/external.h
src/h/object.h

index 58949ad..bd94b5a 100644 (file)
@@ -192,6 +192,9 @@ make_this_symbol(int i, cl_object s, int code, const char *name,
        }
        s->symbol.t = t_symbol;
        s->symbol.dynamic = 0;
+#ifdef ECL_THREADS
+       s->symbol.binding = 0;
+#endif
        ECL_SET(s, OBJNULL);
        SYM_FUN(s) = Cnil;
        s->symbol.plist = Cnil;
index 1f9a49f..b461b74 100644 (file)
@@ -493,6 +493,14 @@ standard_finalizer(cl_object o)
                break;
        }
 #endif
+#ifdef ECL_THREADS
+        case t_symbol: {
+                THREAD_OP_LOCK();
+                cl_core.reused_indices = CONS(MAKE_FIXNUM(o->symbol.binding),
+                                              cl_core.reused_indices);
+                THREAD_OP_UNLOCK();
+        }
+#endif
        default:;
        }
 }
index 9ae3b2f..c4a9f9f 100644 (file)
@@ -440,6 +440,9 @@ cl_boot(int argc, char **argv)
        Cnil_symbol->symbol.plist = Cnil;
        Cnil_symbol->symbol.hpack = Cnil;
        Cnil_symbol->symbol.stype = stp_constant;
+#ifdef ECL_THREADS
+       Cnil_symbol->symbol.binding = 0;
+#endif
        cl_num_symbols_in_core=1;
 
        Ct->symbol.t = (short)t_symbol;
@@ -450,6 +453,9 @@ cl_boot(int argc, char **argv)
        Ct->symbol.plist = Cnil;
        Ct->symbol.hpack = Cnil;
        Ct->symbol.stype = stp_constant;
+#ifdef ECL_THREADS
+       Ct->symbol.binding = 0;
+#endif
        cl_num_symbols_in_core=2;
 
 #ifdef NO_PATH_MAX
@@ -622,10 +628,11 @@ cl_boot(int argc, char **argv)
        init_unixtime();
 
 #ifdef ECL_THREADS
-       env->bindings_hash = cl__make_hash_table(@'eq', MAKE_FIXNUM(1024),
-                                                  ecl_make_singlefloat(1.5f),
-                                                  ecl_make_singlefloat(0.75f),
-                                                  Cnil); /* no locking */
+        cl_core.last_var_index = 0;
+        cl_core.reused_indices = Cnil;
+       env->bindings_hash = si_make_vector(Ct, MAKE_FIXNUM(256),
+                                            Cnil, Cnil, Cnil, Cnil);
+        si_fill_array_with_elt(env->bindings_hash, OBJNULL, MAKE_FIXNUM(0), Cnil);
        ECL_SET(@'mp::*current-process*', env->own_process);
 #endif
 
index d9c5dbf..8affa96 100644 (file)
@@ -104,71 +104,84 @@ ecl_cs_set_org(cl_env_ptr env)
 /********************* BINDING STACK ************************/
 
 #ifdef ECL_THREADS
+cl_index
+ecl_new_binding_index(cl_object symbol)
+{
+        cl_object pool;
+        cl_index new_index;
+        THREAD_OP_LOCK();
+       symbol->symbol.dynamic |= 1;
+        new_index = symbol->symbol.binding;
+        if (!new_index) {
+                si_set_finalizer(symbol, Ct);
+                pool = cl_core.reused_indices;
+                if (!Null(pool)) {
+                        new_index = fix(ECL_CONS_CAR(pool));
+                        cl_core.reused_indices = ECL_CONS_CDR(pool);
+                } else {
+                        new_index = ++cl_core.last_var_index;
+                }
+        }
+        THREAD_OP_UNLOCK();
+        return new_index;
+}
+
+cl_object
+ecl_extend_bindings_array(cl_object vector)
+{
+        cl_index new_size = cl_core.last_var_index * 1.25;
+        cl_object new_vector = si_make_vector(Ct, MAKE_FIXNUM(new_size), Cnil,
+                                             Cnil, Cnil, Cnil);
+        ecl_copy_subarray(new_vector, 0, vector, 0, vector->vector.dim);
+        return new_vector;
+}
+
 void
 ecl_bds_bind(cl_env_ptr env, cl_object s, cl_object value)
 {
-       cl_object bindings = env->bindings_hash;
-       struct ecl_hashtable_entry *h = bindings->hash.get(s, bindings);
-        cl_object old_value;
-       if (h->key == OBJNULL) {
-               /* The previous binding was at most global */
-               cl_index i = bindings->hash.entries + 1;
-               if (i > bindings->hash.limit) {
-                       env->bindings_hash = bindings = ecl_extend_hashtable(bindings);
-                       h = bindings->hash.get(s, bindings);
-               }
-               bindings->hash.entries = i;
-               h->key = s;
-               h->value = value;
-                old_value = OBJNULL;
-       } else {
-               /* We have to save a dynamic binding */
-                old_value = h->value;
-               h->value = value;
-       }
-        {
-                struct bds_bd *slot = ++env->bds_top;
-                if (slot >= env->bds_limit) {
-                        ecl_bds_overflow();
-                        slot = env->bds_top;
-                }
-               slot->symbol = s;
-               slot->value = old_value;
+        cl_object bindings, *location, old_value;
+        struct bds_bd *slot;
+        cl_index index = s->symbol.binding;
+        if (!index) {
+                s->symbol.binding = index = ecl_new_binding_index(s);
+        }
+       bindings = env->bindings_hash;
+        if (index >= bindings->vector.dim) {
+                bindings = ecl_extend_bindings_array(bindings);
+        }
+        location = bindings->array.self.t + index;
+        slot = ++env->bds_top;
+        if (slot >= env->bds_limit) {
+                ecl_bds_overflow();
+                slot = env->bds_top;
         }
-       s->symbol.dynamic |= 1;
+        slot->symbol = s;
+        slot->value = *location;
+        *location = value;
 }
 
 void
 ecl_bds_push(cl_env_ptr env, cl_object s)
 {
-       cl_object bindings = env->bindings_hash;
-       struct ecl_hashtable_entry *h = bindings->hash.get(s, bindings);
-        cl_object old_value;
-       if (h->key == OBJNULL) {
-               /* The previous binding was at most global */
-               cl_index i = bindings->hash.entries + 1;
-               if (i > bindings->hash.limit) {
-                       env->bindings_hash = bindings = ecl_extend_hashtable(bindings);
-                       h = bindings->hash.get(s, bindings);
-               }
-               bindings->hash.entries = i;
-               h->key = s;
-               h->value = s->symbol.value;
-                old_value = OBJNULL;
-       } else {
-               /* We have to save a dynamic binding */
-                old_value = h->value;
-       }
-        {
-                struct bds_bd *slot = ++env->bds_top;
-                if (slot >= env->bds_limit) {
-                        ecl_bds_overflow();
-                        slot = env->bds_top;
-                }
-               slot->symbol = s;
-               slot->value = old_value;
+        cl_object bindings, *location, old_value;
+        struct bds_bd *slot;
+        cl_index index = s->symbol.binding;
+        if (!index) {
+                s->symbol.binding = index = ecl_new_binding_index(s);
         }
-       s->symbol.dynamic |= 1;
+       bindings = env->bindings_hash;
+        if (index >= bindings->vector.dim) {
+                bindings = ecl_extend_bindings_array(bindings);
+        }
+        location = bindings->array.self.t + index;
+        slot = ++env->bds_top;
+        if (slot >= env->bds_limit) {
+                ecl_bds_overflow();
+                slot = env->bds_top;
+        }
+        slot->symbol = s;
+        slot->value = *location;
+       if (!(*location)) *location = s->symbol.value;
 }
 
 void
@@ -177,41 +190,40 @@ ecl_bds_unwind1(cl_env_ptr env)
        struct bds_bd *slot = env->bds_top--;
        cl_object s = slot->symbol;
        cl_object bindings = env->bindings_hash;
-       struct ecl_hashtable_entry *h = bindings->hash.get(s, bindings);
-       if (slot->value == OBJNULL) {
-               /* We have deleted all dynamic bindings */
-               h->key = OBJNULL;
-               h->value = Cnil;
-               bindings->hash.entries--;
-       } else {
-               /* We restore the previous dynamic binding */
-               h->value = slot->value;
-       }
+        cl_object *location = bindings->vector.self.t + s->symbol.binding;
+        *location = slot->value;
 }
 
 cl_object *
 ecl_symbol_slot(cl_env_ptr env, cl_object s)
 {
-       if (Null(s))
+       if (Null(s)) {
                s = Cnil_symbol;
-       if (s->symbol.dynamic) {
-               cl_object bindings = env->bindings_hash;
-               struct ecl_hashtable_entry *h = bindings->hash.get(s, bindings);
-               if (h->key != OBJNULL)
-                       return &h->value;
-       }
-       return &s->symbol.value;
+        } else {
+                cl_index index = s->symbol.binding;
+                if (index) {
+                        cl_object bindings = env->bindings_hash;
+                        if (index < bindings->vector.dim) {
+                               cl_object *location = bindings->vector.self.t + index;
+                               if (*location)
+                                       return location;
+                        }
+                }
+                return &s->symbol.value;
+        }
 }
 
 cl_object
 ecl_set_symbol(cl_env_ptr env, cl_object s, cl_object value)
 {
-       if (s->symbol.dynamic) {
+        cl_index index = s->symbol.binding;
+       if (index) {
                cl_object bindings = env->bindings_hash;
-               struct ecl_hashtable_entry *h = bindings->hash.get(s, bindings);
-               if (h->key != OBJNULL) {
-                       return (h->value = value);
-               }
+                if (index < bindings->vector.dim) {
+                        cl_object *location = bindings->vector.self.t + index;
+                        if (*location)
+                                return (*location) = value;
+                }
        }
        return (s->symbol.value = value);
 }
index 35b4462..2d36642 100644 (file)
@@ -119,6 +119,9 @@ cl_make_symbol(cl_object str)
        x = ecl_alloc_object(t_symbol);
        x->symbol.name = str;
        x->symbol.dynamic = 0;
+#ifdef ECL_THREADS
+       x->symbol.binding = 0;
+#endif /*  */
        ECL_SET(x,OBJNULL);
        SYM_FUN(x) = Cnil;
        x->symbol.plist = Cnil;
@@ -325,6 +328,9 @@ cl_symbol_name(cl_object x)
                x->symbol.value = sym->symbol.value;
                x->symbol.gfdef = sym->symbol.gfdef;
                x->symbol.plist = cl_copy_list(sym->symbol.plist);
+#ifdef ECL_THREADS
+               x->symbol.binding = 0;
+#endif
                /* FIXME!!! We should also copy the system property list */
        }
        @(return x)
index a1ff6a1..c2eb08e 100644 (file)
@@ -203,7 +203,7 @@ thread_entry_point(void *arg)
 static cl_object
 alloc_process(cl_object name, cl_object initial_bindings)
 {
-       cl_object process = ecl_alloc_object(t_process);
+       cl_object process = ecl_alloc_object(t_process), array;
        process->process.active = 0;
        process->process.name = name;
        process->process.function = Cnil;
@@ -212,16 +212,13 @@ alloc_process(cl_object name, cl_object initial_bindings)
         process->process.exit_values = Cnil;
        process->process.env = NULL;
        if (initial_bindings != OBJNULL) {
-               process->process.initial_bindings
-                       = cl__make_hash_table(@'eq', MAKE_FIXNUM(1024),
-                                             ecl_make_singlefloat(1.5),
-                                             ecl_make_singlefloat(0.7),
-                                             Cnil); /* no need for locking */
+               array = si_make_vector(Ct, MAKE_FIXNUM(256),
+                                       Cnil, Cnil, Cnil, Cnil);
+                si_fill_array_with_elt(array, OBJNULL, MAKE_FIXNUM(0), Cnil);
        } else {
-               cl_env_ptr this_env = ecl_process_env();
-               process->process.initial_bindings
-                       = si_copy_hash_table(this_env->bindings_hash);
+               array = cl_copy_seq(ecl_process_env()->bindings_hash);
        }
+        process->process.initial_bindings = array;
        process->process.exit_lock = mp_make_lock(0);
        return process;
 }
index 77d9e04..2e2d827 100644 (file)
@@ -1186,7 +1186,7 @@ init_unixint(int pass)
                create_signal_queue(ecl_get_option(ECL_OPT_SIGNAL_QUEUE_SIZE));
                create_signal_code_constants();
                install_fpe_signal_handlers();
-               install_signal_handling_thread();
+               /*install_signal_handling_thread();*/
                ECL_SET(@'si::*interrupts-enabled*', Ct);
                ecl_process_env()->disable_interrupts = 0;
        }
index 8e046cd..42edc62 100644 (file)
@@ -39,7 +39,9 @@ struct cl_env_struct {
        struct bds_bd *bds_org;
        struct bds_bd *bds_top;
        struct bds_bd *bds_limit;
+#ifdef ECL_THREADS
        cl_object bindings_hash;
+#endif
 
        /*
         * The Invocation History Stack (IHS) keeps a list of the names of the
@@ -233,6 +235,11 @@ struct cl_core_struct {
        uint8_t *ucd_data;
 #endif
        void *default_sigmask;
+
+#ifdef ECL_THREADS
+        cl_index last_var_index;
+        cl_object reused_indices;
+#endif
 };
 
 extern ECL_API struct cl_core_struct cl_core;
index 51cdfc7..63fbc7d 100644 (file)
@@ -257,6 +257,9 @@ struct ecl_symbol {
        cl_object name;         /*  print name  */
        cl_object hpack;        /*  home package  */
                                /*  Cnil for uninterned symbols  */
+#ifdef ECL_THREADS
+        cl_index binding;      /*  index into the bindings array  */
+#endif
 };
 #define SYM_FUN(sym)   ((sym)->symbol.gfdef)