void inline_cache_jit::emit_check(cell klass) { cell code_template; if(TAG(klass) == FIXNUM_TYPE && untag_fixnum(klass) < HEADER_TYPE) code_template = parent->userenv[PIC_CHECK_TAG]; else code_template = parent->userenv[PIC_CHECK]; emit_with(code_template,klass); }
/* index: 0 = top of stack, 1 = item underneath, etc cache_entries: array of class/method pairs */ void inline_cache_jit::compile_inline_cache(fixnum index, cell generic_word_, cell methods_, cell cache_entries_, bool tail_call_p) { gc_root<word> generic_word(generic_word_,parent); gc_root<array> methods(methods_,parent); gc_root<array> cache_entries(cache_entries_,parent); cell inline_cache_type = parent->determine_inline_cache_type(cache_entries.untagged()); parent->update_pic_count(inline_cache_type); /* Generate machine code to determine the object's class. */ emit_class_lookup(index,inline_cache_type); /* Generate machine code to check, in turn, if the class is one of the cached entries. */ cell i; for(i = 0; i < array_capacity(cache_entries.untagged()); i += 2) { /* Class equal? */ cell klass = array_nth(cache_entries.untagged(),i); emit_check(klass); /* Yes? Jump to method */ cell method = array_nth(cache_entries.untagged(),i + 1); emit_with(parent->userenv[PIC_HIT],method); } /* Generate machine code to handle a cache miss, which ultimately results in this function being called again. The inline-cache-miss primitive call receives enough information to reconstruct the PIC. */ push(generic_word.value()); push(methods.value()); push(tag_fixnum(index)); push(cache_entries.value()); word_special(parent->userenv[tail_call_p ? PIC_MISS_TAIL_WORD : PIC_MISS_WORD]); }
void word_special(cell word) { emit_with(parent->userenv[JIT_WORD_SPECIAL],word); }
void word_call(cell word) { emit_with(parent->userenv[JIT_WORD_CALL],word); }
void push(cell literal) { emit_with(parent->userenv[JIT_PUSH_IMMEDIATE],literal); }
void jit::emit_class_lookup(fixnum index, cell type) { emit_with(parent_vm->userenv[PIC_LOAD],tag_fixnum(-index * sizeof(cell))); emit(parent_vm->userenv[type]); }