6 cell megamorphic_cache_hits;
7 cell megamorphic_cache_misses;
9 cell factorvm::search_lookup_alist(cell table, cell klass)
11 array *elements = untag<array>(table);
12 fixnum index = array_capacity(elements) - 2;
15 if(array_nth(elements,index) == klass)
16 return array_nth(elements,index + 1);
24 cell search_lookup_alist(cell table, cell klass)
26 return vm->search_lookup_alist(table,klass);
29 cell factorvm::search_lookup_hash(cell table, cell klass, cell hashcode)
31 array *buckets = untag<array>(table);
32 cell bucket = array_nth(buckets,hashcode & (array_capacity(buckets) - 1));
33 if(tagged<object>(bucket).type_p(WORD_TYPE) || bucket == F)
36 return search_lookup_alist(bucket,klass);
39 cell search_lookup_hash(cell table, cell klass, cell hashcode)
41 return vm->search_lookup_hash(table,klass,hashcode);
44 cell factorvm::nth_superclass(tuple_layout *layout, fixnum echelon)
46 cell *ptr = (cell *)(layout + 1);
47 return ptr[echelon * 2];
50 cell nth_superclass(tuple_layout *layout, fixnum echelon)
52 return vm->nth_superclass(layout,echelon);
55 cell factorvm::nth_hashcode(tuple_layout *layout, fixnum echelon)
57 cell *ptr = (cell *)(layout + 1);
58 return ptr[echelon * 2 + 1];
61 cell nth_hashcode(tuple_layout *layout, fixnum echelon)
63 return vm->nth_hashcode(layout,echelon);
66 cell factorvm::lookup_tuple_method(cell obj, cell methods)
68 tuple_layout *layout = untag<tuple_layout>(untag<tuple>(obj)->layout);
70 array *echelons = untag<array>(methods);
72 fixnum echelon = untag_fixnum(layout->echelon);
73 fixnum max_echelon = array_capacity(echelons) - 1;
74 if(echelon > max_echelon) echelon = max_echelon;
78 cell echelon_methods = array_nth(echelons,echelon);
80 if(tagged<object>(echelon_methods).type_p(WORD_TYPE))
81 return echelon_methods;
82 else if(echelon_methods != F)
84 cell klass = nth_superclass(layout,echelon);
85 cell hashcode = untag_fixnum(nth_hashcode(layout,echelon));
86 cell result = search_lookup_hash(echelon_methods,klass,hashcode);
94 critical_error("Cannot find tuple method",methods);
98 cell lookup_tuple_method(cell obj, cell methods)
100 return vm->lookup_tuple_method(obj,methods);
103 cell factorvm::lookup_hi_tag_method(cell obj, cell methods)
105 array *hi_tag_methods = untag<array>(methods);
106 cell tag = untag<object>(obj)->h.hi_tag() - HEADER_TYPE;
108 assert(tag < TYPE_COUNT - HEADER_TYPE);
110 return array_nth(hi_tag_methods,tag);
113 cell lookup_hi_tag_method(cell obj, cell methods)
115 return vm->lookup_hi_tag_method(obj,methods);
118 cell factorvm::lookup_hairy_method(cell obj, cell methods)
120 cell method = array_nth(untag<array>(methods),TAG(obj));
121 if(tagged<object>(method).type_p(WORD_TYPE))
128 return lookup_tuple_method(obj,method);
131 return lookup_hi_tag_method(obj,method);
134 critical_error("Bad methods array",methods);
140 cell lookup_hairy_method(cell obj, cell methods)
142 return vm->lookup_hairy_method(obj,methods);
145 cell factorvm::lookup_method(cell obj, cell methods)
148 if(tag == TUPLE_TYPE || tag == OBJECT_TYPE)
149 return lookup_hairy_method(obj,methods);
151 return array_nth(untag<array>(methods),TAG(obj));
154 cell lookup_method(cell obj, cell methods)
156 return vm->lookup_method(obj,methods);
159 inline void factorvm::vmprim_lookup_method()
161 cell methods = dpop();
163 dpush(lookup_method(obj,methods));
166 PRIMITIVE(lookup_method)
168 PRIMITIVE_GETVM()->vmprim_lookup_method();
171 cell factorvm::object_class(cell obj)
176 return untag<tuple>(obj)->layout;
178 return untag<object>(obj)->h.value;
180 return tag_fixnum(TAG(obj));
184 cell object_class(cell obj)
186 return vm->object_class(obj);
189 cell factorvm::method_cache_hashcode(cell klass, array *array)
191 cell capacity = (array_capacity(array) >> 1) - 1;
192 return ((klass >> TAG_BITS) & capacity) << 1;
195 cell method_cache_hashcode(cell klass, array *array)
197 return vm->method_cache_hashcode(klass,array);
200 void factorvm::update_method_cache(cell cache, cell klass, cell method)
202 array *cache_elements = untag<array>(cache);
203 cell hashcode = method_cache_hashcode(klass,cache_elements);
204 set_array_nth(cache_elements,hashcode,klass);
205 set_array_nth(cache_elements,hashcode + 1,method);
208 void update_method_cache(cell cache, cell klass, cell method)
210 return vm->update_method_cache(cache,klass,method);
213 inline void factorvm::vmprim_mega_cache_miss()
215 megamorphic_cache_misses++;
218 fixnum index = untag_fixnum(dpop());
219 cell methods = dpop();
221 cell object = ((cell *)ds)[-index];
222 cell klass = object_class(object);
223 cell method = lookup_method(object,methods);
225 update_method_cache(cache,klass,method);
230 PRIMITIVE(mega_cache_miss)
232 PRIMITIVE_GETVM()->vmprim_mega_cache_miss();
235 inline void factorvm::vmprim_reset_dispatch_stats()
237 megamorphic_cache_hits = megamorphic_cache_misses = 0;
240 PRIMITIVE(reset_dispatch_stats)
242 PRIMITIVE_GETVM()->vmprim_reset_dispatch_stats();
245 inline void factorvm::vmprim_dispatch_stats()
247 growable_array stats;
248 stats.add(allot_cell(megamorphic_cache_hits));
249 stats.add(allot_cell(megamorphic_cache_misses));
251 dpush(stats.elements.value());
254 PRIMITIVE(dispatch_stats)
256 PRIMITIVE_GETVM()->vmprim_dispatch_stats();
259 void quotation_jit::emit_mega_cache_lookup(cell methods_, fixnum index, cell cache_)
261 gc_root<array> methods(methods_);
262 gc_root<array> cache(cache_);
264 /* Generate machine code to determine the object's class. */
265 emit_class_lookup(index,PIC_HI_TAG_TUPLE);
267 /* Do a cache lookup. */
268 emit_with(userenv[MEGA_LOOKUP],cache.value());
270 /* If we end up here, the cache missed. */
271 emit(userenv[JIT_PROLOG]);
273 /* Push index, method table and cache on the stack. */
274 push(methods.value());
275 push(tag_fixnum(index));
277 word_call(userenv[MEGA_MISS_WORD]);
279 /* Now the new method has been stored into the cache, and its on
281 emit(userenv[JIT_EPILOG]);
282 emit(userenv[JIT_EXECUTE_JUMP]);