5 cell factor_vm::search_lookup_alist(cell table, cell klass) {
6 array* elements = untag<array>(table);
7 fixnum index = array_capacity(elements) - 2;
9 if (array_nth(elements, index) == klass)
10 return array_nth(elements, index + 1);
18 cell factor_vm::search_lookup_hash(cell table, cell klass, cell hashcode) {
19 array* buckets = untag<array>(table);
20 cell bucket = array_nth(buckets, hashcode & (array_capacity(buckets) - 1));
21 if (TAG(bucket) == ARRAY_TYPE)
22 return search_lookup_alist(bucket, klass);
26 cell factor_vm::nth_superclass(tuple_layout* layout, fixnum echelon) {
27 cell* ptr = (cell*)(layout + 1);
28 return ptr[echelon * 2];
31 cell factor_vm::nth_hashcode(tuple_layout* layout, fixnum echelon) {
32 cell* ptr = (cell*)(layout + 1);
33 return ptr[echelon * 2 + 1];
36 cell factor_vm::lookup_tuple_method(cell obj, cell methods) {
37 tuple_layout* layout = untag<tuple_layout>(untag<tuple>(obj)->layout);
39 array* echelons = untag<array>(methods);
41 fixnum echelon = std::min(untag_fixnum(layout->echelon),
42 (fixnum)array_capacity(echelons) - 1);
44 while (echelon >= 0) {
45 cell echelon_methods = array_nth(echelons, echelon);
47 if (TAG(echelon_methods) == WORD_TYPE)
48 return echelon_methods;
49 else if (to_boolean(echelon_methods)) {
50 cell klass = nth_superclass(layout, echelon);
51 cell hashcode = untag_fixnum(nth_hashcode(layout, echelon));
52 cell result = search_lookup_hash(echelon_methods, klass, hashcode);
53 if (to_boolean(result))
60 critical_error("Cannot find tuple method", methods);
64 cell factor_vm::lookup_method(cell obj, cell methods) {
66 cell method = array_nth(untag<array>(methods), tag);
68 if (tag == TUPLE_TYPE) {
69 if (TAG(method) == ARRAY_TYPE)
70 return lookup_tuple_method(obj, method);
76 void factor_vm::primitive_lookup_method() {
77 cell methods = ctx->pop();
78 cell obj = ctx->pop();
79 ctx->push(lookup_method(obj, methods));
82 cell factor_vm::object_class(cell obj) {
84 if (tag == TUPLE_TYPE)
85 return untag<tuple>(obj)->layout;
86 return tag_fixnum(tag);
89 cell factor_vm::method_cache_hashcode(cell klass, array* array) {
90 cell capacity = (array_capacity(array) >> 1) - 1;
91 return ((klass >> TAG_BITS) & capacity) << 1;
94 void factor_vm::update_method_cache(cell cache, cell klass, cell method) {
95 array* cache_elements = untag<array>(cache);
96 cell hashcode = method_cache_hashcode(klass, cache_elements);
97 set_array_nth(cache_elements, hashcode, klass);
98 set_array_nth(cache_elements, hashcode + 1, method);
101 void factor_vm::primitive_mega_cache_miss() {
102 dispatch_stats.megamorphic_cache_misses++;
104 cell cache = ctx->pop();
105 fixnum index = untag_fixnum(ctx->pop());
106 cell methods = ctx->pop();
108 cell object = ((cell*)ctx->datastack)[-index];
109 cell klass = object_class(object);
110 cell method = lookup_method(object, methods);
112 update_method_cache(cache, klass, method);
117 void factor_vm::primitive_reset_dispatch_stats() {
118 memset(&dispatch_stats, 0, sizeof(dispatch_statistics));
121 /* Allocates memory */
122 void factor_vm::primitive_dispatch_stats() {
123 ctx->push(tag<byte_array>(byte_array_from_value(&dispatch_stats)));
126 /* Allocates memory */
127 void quotation_jit::emit_mega_cache_lookup(cell methods_, fixnum index,
129 data_root<array> methods(methods_, parent);
130 data_root<array> cache(cache_, parent);
132 /* The object must be on the top of the datastack at this point. */
134 /* Do a cache lookup. */
135 emit_with_literal(parent->special_objects[MEGA_LOOKUP], cache.value());
137 /* If we end up here, the cache missed. */
138 emit(parent->special_objects[JIT_PROLOG]);
140 /* Push index, method table and cache on the stack. */
141 push(methods.value());
142 push(tag_fixnum(index));
144 word_call(parent->special_objects[MEGA_MISS_WORD]);
146 /* Now the new method has been stored into the cache, and its on
148 emit(parent->special_objects[JIT_EPILOG]);
149 emit(parent->special_objects[JIT_EXECUTE]);