diff options
Diffstat (limited to 'libguile/eval.i.c')
-rw-r--r-- | libguile/eval.i.c | 137 |
1 files changed, 4 insertions, 133 deletions
diff --git a/libguile/eval.i.c b/libguile/eval.i.c index 5b4604a7a..03eb2cd82 100644 --- a/libguile/eval.i.c +++ b/libguile/eval.i.c @@ -744,139 +744,10 @@ dispatch: * (c.f. objects.c:scm_mcache_compute_cmethod) since that * cuts down execution time for type dispatch to 50%. */ type_dispatch: /* inputs: x, arg1 */ - /* Type dispatch means to determine from the types of the function - * arguments (i. e. the 'signature' of the call), which method from - * a generic function is to be called. This process of selecting - * the right method takes some time. To speed it up, guile uses - * caching: Together with the macro call to dispatch the signatures - * of some previous calls to that generic function from the same - * place are stored (in the code!) in a cache that we call the - * 'method cache'. This is done since it is likely, that - * consecutive calls to dispatch from that position in the code will - * have the same signature. Thus, the type dispatch works as - * follows: First, determine a hash value from the signature of the - * actual arguments. Second, use this hash value as an index to - * find that same signature in the method cache stored at this - * position in the code. If found, you have also found the - * corresponding method that belongs to that signature. If the - * signature is not found in the method cache, you have to perform a - * full search over all signatures stored with the generic - * function. */ - { - unsigned long int specializers; - unsigned long int hash_value; - unsigned long int cache_end_pos; - unsigned long int mask; - SCM method_cache; - - { - SCM z = SCM_CDDR (x); - SCM tmp = SCM_CADR (z); - specializers = scm_to_ulong (SCM_CAR (z)); - - /* Compute a hash value for searching the method cache. There - * are two variants for computing the hash value, a (rather) - * complicated one, and a simple one. For the complicated one - * explained below, tmp holds a number that is used in the - * computation. */ - if (scm_is_simple_vector (tmp)) - { - /* This method of determining the hash value is much - * simpler: Set the hash value to zero and just perform a - * linear search through the method cache. */ - method_cache = tmp; - mask = (unsigned long int) ((long) -1); - hash_value = 0; - cache_end_pos = SCM_SIMPLE_VECTOR_LENGTH (method_cache); - } - else - { - /* Use the signature of the actual arguments to determine - * the hash value. This is done as follows: Each class has - * an array of random numbers, that are determined when the - * class is created. The integer 'hashset' is an index into - * that array of random numbers. Now, from all classes that - * are part of the signature of the actual arguments, the - * random numbers at index 'hashset' are taken and summed - * up, giving the hash value. The value of 'hashset' is - * stored at the call to dispatch. This allows to have - * different 'formulas' for calculating the hash value at - * different places where dispatch is called. This allows - * to optimize the hash formula at every individual place - * where dispatch is called, such that hopefully the hash - * value that is computed will directly point to the right - * method in the method cache. */ - unsigned long int hashset = scm_to_ulong (tmp); - unsigned long int counter = specializers + 1; - SCM tmp_arg = arg1; - hash_value = 0; - while (!scm_is_null (tmp_arg) && counter != 0) - { - SCM class = scm_class_of (SCM_CAR (tmp_arg)); - hash_value += SCM_INSTANCE_HASH (class, hashset); - tmp_arg = SCM_CDR (tmp_arg); - counter--; - } - z = SCM_CDDR (z); - method_cache = SCM_CADR (z); - mask = scm_to_ulong (SCM_CAR (z)); - hash_value &= mask; - cache_end_pos = hash_value; - } - } - - { - /* Search the method cache for a method with a matching - * signature. Start the search at position 'hash_value'. The - * hashing implementation uses linear probing for conflict - * resolution, that is, if the signature in question is not - * found at the starting index in the hash table, the next table - * entry is tried, and so on, until in the worst case the whole - * cache has been searched, but still the signature has not been - * found. */ - SCM z; - do - { - SCM args = arg1; /* list of arguments */ - z = SCM_SIMPLE_VECTOR_REF (method_cache, hash_value); - while (!scm_is_null (args)) - { - /* More arguments than specifiers => CLASS != ENV */ - SCM class_of_arg = scm_class_of (SCM_CAR (args)); - if (!scm_is_eq (class_of_arg, SCM_CAR (z))) - goto next_method; - args = SCM_CDR (args); - z = SCM_CDR (z); - } - /* Fewer arguments than specifiers => CAR != CLASS */ - if (!scm_is_pair (z)) - goto apply_vm_cmethod; - else if (!SCM_CLASSP (SCM_CAR (z)) - && !scm_is_symbol (SCM_CAR (z))) - goto apply_memoized_cmethod; - next_method: - hash_value = (hash_value + 1) & mask; - } while (hash_value != cache_end_pos); - - /* No appropriate method was found in the cache. */ - z = scm_memoize_method (x, arg1); - - if (scm_is_pair (z)) - goto apply_memoized_cmethod; - - apply_vm_cmethod: - proc = z; - PREP_APPLY (proc, arg1); - goto apply_proc; - - apply_memoized_cmethod: /* inputs: z, arg1 */ - { - SCM formals = SCM_CMETHOD_FORMALS (z); - env = SCM_EXTEND_ENV (formals, arg1, SCM_CMETHOD_ENV (z)); - x = SCM_CMETHOD_BODY (z); - goto nontoplevel_begin; - } - } + { + proc = scm_mcache_compute_cmethod (x, arg1); + PREP_APPLY (proc, arg1); + goto apply_proc; } |