From 85165d989a563abdf0e31e14ece2e97b5d821187 Mon Sep 17 00:00:00 2001 From: Stas Boukarev Date: Sat, 27 Sep 2014 00:46:35 +0400 Subject: [PATCH] Fix eql-specializer dispatch caching. When the EQL specializer is a class it may clash with a class specializer, since the class specializer is cached as a class object. Use twice as much space for cache, the cache entry itself and a bit, 1 if it's an eql-specializer, 0 if it's a class specializer. Fixes #295 --- src/c/gfun.d | 16 +++++++++++----- src/c/main.d | 4 +++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/c/gfun.d b/src/c/gfun.d index 165fb54e3..140fc72c8 100644 --- a/src/c/gfun.d +++ b/src/c/gfun.d @@ -129,11 +129,17 @@ fill_spec_vector(cl_object vector, cl_object frame, cl_object gf) FEwrong_num_arguments(gf); unlikely_if (spec_no >= vector->vector.dim) ecl_internal_error("Too many arguments to fill_spec_vector()"); - argtype[spec_no++] = - (!ECL_LISTP(spec_type) || - Null(ecl_memql(args[spec_position], spec_type))) ? - cl_class_of(args[spec_position]) : - args[spec_position]; + /* Need to differentiate between EQL specializers and + class specializers, because the EQL value can be a + class, and may classh with a class specializer. */ + if (ECL_LISTP(spec_type) && ecl_memql(args[spec_position], spec_type)) { + argtype[spec_no++] = args[spec_position]; + argtype[spec_no++] = 1; + } else { + argtype[spec_no++] = cl_class_of(args[spec_position]); + argtype[spec_no++] = 0; + } + } end_loop_for_on_unsafe(spec_how_list); vector->vector.fillp = spec_no; return vector; diff --git a/src/c/main.d b/src/c/main.d index 8cbe6e848..53091d1ba 100755 --- a/src/c/main.d +++ b/src/c/main.d @@ -160,7 +160,9 @@ ecl_init_env(cl_env_ptr env) #endif #ifdef CLOS - env->method_cache = ecl_make_cache(64, 4096); + /* Needs 128 elements for 64 entries to differentiate between + EQL specializers and class specializers */ + env->method_cache = ecl_make_cache(128, 4096); env->slot_cache = ecl_make_cache(3, 4096); #endif env->pending_interrupt = ECL_NIL;