Skip to content
This repository
Fetching contributors…

Cannot retrieve contributors at this time

executable file 171 lines (138 sloc) 4.154 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
#include "master.hpp"

namespace factor
{

cell factor_vm::search_lookup_alist(cell table, cell klass)
{
array *elements = untag<array>(table);
fixnum index = array_capacity(elements) - 2;
while(index >= 0)
{
if(array_nth(elements,index) == klass)
return array_nth(elements,index + 1);
else
index -= 2;
}

return false_object;
}

cell factor_vm::search_lookup_hash(cell table, cell klass, cell hashcode)
{
array *buckets = untag<array>(table);
cell bucket = array_nth(buckets,hashcode & (array_capacity(buckets) - 1));
if(TAG(bucket) == ARRAY_TYPE)
return search_lookup_alist(bucket,klass);
else
return bucket;
}

cell factor_vm::nth_superclass(tuple_layout *layout, fixnum echelon)
{
cell *ptr = (cell *)(layout + 1);
return ptr[echelon * 2];
}

cell factor_vm::nth_hashcode(tuple_layout *layout, fixnum echelon)
{
cell *ptr = (cell *)(layout + 1);
return ptr[echelon * 2 + 1];
}

cell factor_vm::lookup_tuple_method(cell obj, cell methods)
{
tuple_layout *layout = untag<tuple_layout>(untag<tuple>(obj)->layout);

array *echelons = untag<array>(methods);

fixnum echelon = std::min(untag_fixnum(layout->echelon),(fixnum)array_capacity(echelons) - 1);

while(echelon >= 0)
{
cell echelon_methods = array_nth(echelons,echelon);

if(tagged<object>(echelon_methods).type_p(WORD_TYPE))
return echelon_methods;
else if(to_boolean(echelon_methods))
{
cell klass = nth_superclass(layout,echelon);
cell hashcode = untag_fixnum(nth_hashcode(layout,echelon));
cell result = search_lookup_hash(echelon_methods,klass,hashcode);
if(to_boolean(result))
return result;
}

echelon--;
}

critical_error("Cannot find tuple method",methods);
return false_object;
}

cell factor_vm::lookup_method(cell obj, cell methods)
{
cell tag = TAG(obj);
cell method = array_nth(untag<array>(methods),tag);

if(tag == TUPLE_TYPE)
{
if(TAG(method) == ARRAY_TYPE)
return lookup_tuple_method(obj,method);
else
return method;
}
else
return method;
}

void factor_vm::primitive_lookup_method()
{
cell methods = ctx->pop();
cell obj = ctx->pop();
ctx->push(lookup_method(obj,methods));
}

cell factor_vm::object_class(cell obj)
{
cell tag = TAG(obj);
if(tag == TUPLE_TYPE)
return untag<tuple>(obj)->layout;
else
return tag_fixnum(tag);
}

cell factor_vm::method_cache_hashcode(cell klass, array *array)
{
cell capacity = (array_capacity(array) >> 1) - 1;
return ((klass >> TAG_BITS) & capacity) << 1;
}

void factor_vm::update_method_cache(cell cache, cell klass, cell method)
{
array *cache_elements = untag<array>(cache);
cell hashcode = method_cache_hashcode(klass,cache_elements);
set_array_nth(cache_elements,hashcode,klass);
set_array_nth(cache_elements,hashcode + 1,method);
}

void factor_vm::primitive_mega_cache_miss()
{
dispatch_stats.megamorphic_cache_misses++;

cell cache = ctx->pop();
fixnum index = untag_fixnum(ctx->pop());
cell methods = ctx->pop();

cell object = ((cell *)ctx->datastack)[-index];
cell klass = object_class(object);
cell method = lookup_method(object,methods);

update_method_cache(cache,klass,method);

ctx->push(method);
}

void factor_vm::primitive_reset_dispatch_stats()
{
memset(&dispatch_stats,0,sizeof(dispatch_statistics));
}

void factor_vm::primitive_dispatch_stats()
{
ctx->push(tag<byte_array>(byte_array_from_value(&dispatch_stats)));
}

void quotation_jit::emit_mega_cache_lookup(cell methods_, fixnum index, cell cache_)
{
data_root<array> methods(methods_,parent);
data_root<array> cache(cache_,parent);

/* The object must be on the top of the datastack at this point. */

/* Do a cache lookup. */
emit_with_literal(parent->special_objects[MEGA_LOOKUP],cache.value());

/* If we end up here, the cache missed. */
emit(parent->special_objects[JIT_PROLOG]);

/* Push index, method table and cache on the stack. */
push(methods.value());
push(tag_fixnum(index));
push(cache.value());
word_call(parent->special_objects[MEGA_MISS_WORD]);

/* Now the new method has been stored into the cache, and its on
the stack. */
emit(parent->special_objects[JIT_EPILOG]);
emit(parent->special_objects[JIT_EXECUTE]);
}

}
Something went wrong with that request. Please try again.