PICs now pass the method table around instead of extracting it from the generic word body. This gels better with how compilation units are supposed to work

db4
Slava Pestov 2009-04-29 19:39:43 -05:00
parent deaea55d85
commit 02bd4f3f00
3 changed files with 26 additions and 47 deletions

View File

@ -230,30 +230,28 @@ M: word compile-engine ;
M: f compile-engine ;
: build-decision-tree ( generic -- methods )
{
[ generic-word set ]
[ "engines" word-prop forget-all ]
[ V{ } clone "engines" set-word-prop ]
[
"methods" word-prop clone
[ find-default default set ]
[ <engine> compile-engine ] bi
]
} cleave ;
[ "engines" word-prop forget-all ]
[ V{ } clone "engines" set-word-prop ]
[
"methods" word-prop clone
[ find-default default set ]
[ <engine> compile-engine ] bi
] tri ;
: make-empty-cache ( -- array )
generic-word get "methods" word-prop
assoc-size 2 * next-power-of-2 f <array> ;
HOOK: cold-call-def combination ( word -- quot/f )
HOOK: direct-entry-def combination ( word methods -- quot/f )
M: single-combination cold-call-def drop f ;
M: single-combination direct-entry-def 2drop f ;
: define-cold-call ( word -- )
dup cold-call-def >>direct-entry-def drop ;
: define-direct-entry ( word methods -- )
[ drop ] [ direct-entry-def ] 2bi >>direct-entry-def drop ;
M: single-combination perform-combination
[
dup generic-word set
dup build-decision-tree
[ "decision-tree" set-word-prop ]
[
@ -264,5 +262,5 @@ M: single-combination perform-combination
[ lookup-method (execute) ] %
] [ ] make define
]
[ drop define-cold-call ] 2tri
[ define-direct-entry ] 2tri
] with-combination ;

View File

@ -38,11 +38,11 @@ M: standard-generic effective-method
[ datastack ] dip [ "combination" word-prop #>> swap <reversed> nth ] keep
(effective-method) ;
M: standard-combination cold-call-def
M: standard-combination direct-entry-def ( word methods -- )
#! Direct calls to the generic word (not tail calls or indirect calls)
#! will jump to the inline cache entry point instead of the megamorphic
#! dispatch entry point.
[ f inline-cache-miss ] curry picker prepend ;
picker first [ [ f inline-cache-miss ] 3curry ] keep prefix ;
M: standard-generic definer drop \ GENERIC# f ;

View File

@ -52,7 +52,7 @@ static void update_pic_count(CELL type)
/* picker: one of dup, over, pick
cache_entries: array of class/method pairs */
static F_CODE_BLOCK *compile_inline_cache(CELL picker, CELL generic_word, CELL cache_entries)
static F_CODE_BLOCK *compile_inline_cache(CELL picker, CELL generic_word, CELL methods, CELL cache_entries)
{
#ifdef FACTOR_DEBUG
type_check(WORD_TYPE,picker);
@ -62,6 +62,7 @@ static F_CODE_BLOCK *compile_inline_cache(CELL picker, CELL generic_word, CELL c
REGISTER_ROOT(picker);
REGISTER_ROOT(generic_word);
REGISTER_ROOT(methods);
REGISTER_ROOT(cache_entries);
CELL inline_cache_type = determine_inline_cache_type(cache_entries);
@ -96,6 +97,8 @@ static F_CODE_BLOCK *compile_inline_cache(CELL picker, CELL generic_word, CELL c
object being dispatched on can be popped from the top of the stack. */
jit_emit_subprimitive(&jit,untag_object(picker));
jit_push(&jit,generic_word);
jit_push(&jit,methods);
jit_push(&jit,picker);
jit_push(&jit,cache_entries);
jit_word_jump(&jit,userenv[PIC_MISS_WORD]);
@ -105,6 +108,7 @@ static F_CODE_BLOCK *compile_inline_cache(CELL picker, CELL generic_word, CELL c
jit_dispose(&jit);
UNREGISTER_ROOT(cache_entries);
UNREGISTER_ROOT(methods);
UNREGISTER_ROOT(generic_word);
UNREGISTER_ROOT(picker);
@ -121,28 +125,6 @@ static F_CODE_BLOCK *megamorphic_call_stub(CELL generic_word)
return untag_quotation(word->def)->code;
}
/* Assumes that generic word definitions look like:
[ <picker> <methods> <cache> lookup-method (execute) ]
*/
static void examine_generic_word(CELL generic_word, CELL *picker, CELL *all_methods)
{
CELL def = untag_word(generic_word)->def;
F_QUOTATION *quot = untag_quotation(def);
F_ARRAY *array = untag_object(quot->array);
#ifdef FACTOR_DEBUG
assert(array_capacity(array) == 5);
type_check(WORD_TYPE,array_nth(array,0));
type_check(ARRAY_TYPE,array_nth(array,1));
type_check(ARRAY_TYPE,array_nth(array,2));
type_check(WORD_TYPE,array_nth(array,3));
type_check(WORD_TYPE,array_nth(array,4));
#endif
*picker = array_nth(array,0);
*all_methods = array_nth(array,1);
}
static CELL inline_cache_size(CELL cache_entries)
{
return (cache_entries == F ? 0 : array_capacity(untag_array(cache_entries)) / 2);
@ -181,6 +163,8 @@ XT inline_cache_miss(CELL return_address)
check_code_pointer(return_address);
CELL cache_entries = dpop();
CELL picker = dpop();
CELL methods = dpop();
CELL generic_word = dpop();
CELL object = dpop();
@ -194,21 +178,18 @@ XT inline_cache_miss(CELL return_address)
block = megamorphic_call_stub(generic_word);
else
{
CELL picker, all_methods;
examine_generic_word(generic_word,&picker,&all_methods);
REGISTER_ROOT(generic_word);
REGISTER_ROOT(cache_entries);
REGISTER_ROOT(picker);
REGISTER_ROOT(all_methods);
REGISTER_ROOT(methods);
CELL class = object_class(object);
CELL method = lookup_method(object,all_methods);
CELL method = lookup_method(object,methods);
cache_entries = add_inline_cache_entry(cache_entries,class,method);
block = compile_inline_cache(picker,generic_word,cache_entries);
block = compile_inline_cache(picker,generic_word,methods,cache_entries);
UNREGISTER_ROOT(all_methods);
UNREGISTER_ROOT(methods);
UNREGISTER_ROOT(picker);
UNREGISTER_ROOT(cache_entries);
UNREGISTER_ROOT(generic_word);