Working on new method dispatch system

db4
Slava Pestov 2009-04-24 15:31:06 -05:00
parent b1c790da41
commit 8c5b0373a8
11 changed files with 296 additions and 4 deletions

View File

@ -35,6 +35,7 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
vm/data_gc.o \ vm/data_gc.o \
vm/data_heap.o \ vm/data_heap.o \
vm/debug.o \ vm/debug.o \
vm/dispatch.o \
vm/errors.o \ vm/errors.o \
vm/factor.o \ vm/factor.o \
vm/image.o \ vm/image.o \
@ -182,5 +183,5 @@ vm/ffi_test.o: vm/ffi_test.c
.m.o: .m.o:
$(CC) -c $(CFLAGS) -o $@ $< $(CC) -c $(CFLAGS) -o $@ $<
.PHONY: factor .PHONY: factor

View File

@ -12,6 +12,7 @@ classes.tuple.private vectors vectors.private words definitions
words.private assocs summary compiler.units system.private words.private assocs summary compiler.units system.private
combinators locals locals.backend locals.types words.private combinators locals locals.backend locals.types words.private
quotations.private combinators.private stack-checker.values quotations.private combinators.private stack-checker.values
generic.standard.private
alien.libraries alien.libraries
stack-checker.alien stack-checker.alien
stack-checker.state stack-checker.state
@ -676,3 +677,5 @@ M: object infer-call*
\ gc-stats { } { array } define-primitive \ gc-stats { } { array } define-primitive
\ jit-compile { quotation } { } define-primitive \ jit-compile { quotation } { } define-primitive
\ lookup-method { object array } { word } define-primitive

View File

@ -69,6 +69,7 @@ bootstrapping? on
"classes.predicate" "classes.predicate"
"compiler.units" "compiler.units"
"continuations.private" "continuations.private"
"generic.standard.private"
"growable" "growable"
"hashtables" "hashtables"
"hashtables.private" "hashtables.private"
@ -532,6 +533,7 @@ tuple
{ "jit-compile" "quotations" (( quot -- )) } { "jit-compile" "quotations" (( quot -- )) }
{ "load-locals" "locals.backend" (( ... n -- )) } { "load-locals" "locals.backend" (( ... n -- )) }
{ "check-datastack" "kernel.private" (( array in# out# -- ? )) } { "check-datastack" "kernel.private" (( array in# out# -- ? )) }
{ "lookup-method" "generic.standard.private" (( object methods -- method )) }
} [ [ first3 ] dip swap make-primitive ] each-index } [ [ first3 ] dip swap make-primitive ] each-index
! Bump build number ! Bump build number

View File

@ -0,0 +1 @@
Slava Pestov

View File

@ -0,0 +1,174 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays assocs classes.algebra math combinators
generic.standard.engines hashtables kernel kernel.private layouts
namespaces sequences words sorting quotations effects
generic.standard.private words.private ;
IN: generic.standard.compiler
! ! ! Build an engine ! ! !
! 1. Flatten methods
TUPLE: predicate-engine methods ;
: <predicate-engine> ( methods -- engine ) predicate-engine boa ;
: push-method ( method specializer atomic assoc -- )
[
[ H{ } clone <predicate-engine> ] unless*
[ methods>> set-at ] keep
] change-at ;
: flatten-method ( class method assoc -- )
[ [ flatten-class keys ] keep ] 2dip [
[ spin ] dip push-method
] 3curry each ;
: flatten-methods ( assoc -- assoc' )
H{ } clone [ [ flatten-method ] curry assoc-each ] keep ;
! 2. Convert methods
: convert-methods ( assoc class word -- assoc' )
over [ split-methods ] 2dip pick assoc-empty?
[ 3drop ] [ [ execute ] dip pick set-at ] if ; inline
! 2.1 Convert tuple methods
TUPLE: echelon-dispatch-engine n methods ;
C: <echelon-dispatch-engine> echelon-dispatch-engine
TUPLE: tuple-dispatch-engine echelons ;
: push-echelon ( class method assoc -- )
[ swap dup "layout" word-prop third ] dip
[ ?set-at ] change-at ;
: echelon-sort ( assoc -- assoc' )
H{ } clone [ [ push-echelon ] curry assoc-each ] keep ;
: <tuple-dispatch-engine> ( methods -- engine )
echelon-sort
[ dupd <echelon-dispatch-engine> ] assoc-map
\ tuple-dispatch-engine boa ;
: convert-tuple-methods ( assoc -- assoc' )
tuple bootstrap-word
\ <tuple-dispatch-engine> convert-methods ;
! 2.2 Convert hi-tag methods
TUPLE: hi-tag-dispatch-engine methods ;
C: <hi-tag-dispatch-engine> hi-tag-dispatch-engine
: convert-hi-tag-methods ( assoc -- assoc' )
\ hi-tag bootstrap-word
\ <hi-tag-dispatch-engine> convert-methods ;
! 3 Tag methods
TUPLE: tag-dispatch-engine methods ;
C: <tag-dispatch-engine> tag-dispatch-engine
: <engine> ( assoc -- engine )
flatten-methods
convert-tuple-methods
convert-hi-tag-methods
<tag-dispatch-engine> ;
! ! ! Compile engine ! ! !
SYMBOL: assumed
SYMBOL: default
SYMBOL: generic-word
GENERIC: compile-engine ( engine -- obj )
: compile-engines ( assoc -- assoc' )
[ compile-engine ] assoc-map ;
: compile-engines* ( assoc -- assoc' )
[ over assumed [ compile-engine ] with-variable ] assoc-map ;
: direct-dispatch-table ( assoc n -- table )
default get <array> [ <enum> swap update ] keep ;
M: tag-dispatch-engine compile-engine
methods>> compile-engines*
[ [ tag-number ] dip ] assoc-map
num-tags get direct-dispatch-table ;
: hi-tag-number ( class -- n ) "type" word-prop ;
: num-hi-tags ( -- n )
num-types get num-tags get - ;
M: hi-tag-dispatch-engine compile-engine
methods>> compile-engines*
[ [ hi-tag-number num-tags get - ] dip ] assoc-map
num-hi-tags direct-dispatch-table ;
: build-fast-hash ( methods -- buckets )
>alist V{ } clone [ hashcode 1array ] distribute-buckets
[ compile-engines* >alist >array ] map ;
M: echelon-dispatch-engine compile-engine
methods>> compile-engines* build-fast-hash ;
M: tuple-dispatch-engine compile-engine
tuple assumed [
echelons>> compile-engines
dup keys supremum f <array> default get prefix
[ <enum> swap update ] keep
] with-variable ;
: sort-methods ( assoc -- assoc' )
>alist [ keys sort-classes ] keep extract-keys ;
: literalize-methods ( assoc -- assoc' )
[ [ ] curry \ drop prefix ] assoc-map ;
: methods-with-default ( engine -- assoc )
methods>> clone default get object bootstrap-word pick set-at ;
: keep-going? ( assoc -- ? )
assumed get swap second first class<= ;
: prune-redundant-predicates ( assoc -- default assoc' )
{
{ [ dup empty? ] [ drop [ "Unreachable" throw ] { } ] }
{ [ dup length 1 = ] [ first second { } ] }
{ [ dup keep-going? ] [ rest-slice prune-redundant-predicates ] }
[ [ first second ] [ rest-slice ] bi ]
} cond ;
: class-predicates ( assoc -- assoc )
[ [ "predicate" word-prop picker prepend ] dip ] assoc-map ;
: predicate-engine-effect ( -- effect )
(dispatch#) get 1+ dup 1+ <effect> ;
: define-predicate-engine ( alist -- word )
[ generic-word get name>> "/predicate-engine" append f <word> dup ] dip
predicate-engine-effect define-declared ;
M: predicate-engine compile-engine
methods-with-default
sort-methods
literalize-methods
prune-redundant-predicates
class-predicates
[ peek wrapped>> ]
[ alist>quot picker prepend define-predicate-engine ] if-empty ;
M: word compile-engine ;
M: f compile-engine ;
: build-engine ( generic combination -- engine )
[
#>> (dispatch#) set
[ generic-word set ]
[ "default-method" word-prop default set ]
[ "methods" word-prop ] tri
<engine> compile-engine 1quotation
picker [ lookup-method ] surround
] with-scope ;

View File

@ -334,7 +334,7 @@ CELL next_object(void)
type = untag_header(value); type = untag_header(value);
heap_scan_ptr += untagged_object_size(heap_scan_ptr); heap_scan_ptr += untagged_object_size(heap_scan_ptr);
return RETAG(obj,type <= HEADER_TYPE ? type : OBJECT_TYPE); return RETAG(obj,type < HEADER_TYPE ? type : OBJECT_TYPE);
} }
/* Push object at heap scan cursor and advance; pushes f when done */ /* Push object at heap scan cursor and advance; pushes f when done */

108
vm/dispatch.c Normal file
View File

@ -0,0 +1,108 @@
#include "master.h"
static CELL search_lookup_alist(CELL table, CELL class)
{
F_ARRAY *pairs = untag_object(table);
F_FIXNUM index = array_capacity(pairs) - 1;
while(index >= 0)
{
F_ARRAY *pair = untag_object(array_nth(pairs,index));
if(array_nth(pair,0) == class)
return array_nth(pair,1);
else
index--;
}
return F;
}
static CELL search_lookup_hash(CELL table, CELL class, CELL hashcode)
{
F_ARRAY *buckets = untag_object(table);
CELL bucket = array_nth(buckets,hashcode & (array_capacity(buckets) - 1));
if(type_of(bucket) == WORD_TYPE || bucket == F)
return bucket;
else
return search_lookup_alist(bucket,class);
}
static CELL nth_superclass(F_TUPLE_LAYOUT *layout, F_FIXNUM echelon)
{
CELL *ptr = (CELL *)(layout + 1);
return ptr[echelon * 2];
}
static CELL nth_hashcode(F_TUPLE_LAYOUT *layout, F_FIXNUM echelon)
{
CELL *ptr = (CELL *)(layout + 1);
return ptr[echelon * 2 + 1];
}
static CELL lookup_tuple_method(CELL object, CELL methods)
{
F_ARRAY *echelons = untag_object(methods);
F_TUPLE *tuple = untag_object(object);
F_TUPLE_LAYOUT *layout = untag_object(tuple->layout);
F_FIXNUM echelon = untag_fixnum_fast(layout->echelon);
F_FIXNUM max_echelon = array_capacity(echelons) - 1;
if(echelon > max_echelon) echelon = max_echelon;
while(echelon >= 0)
{
CELL echelon_methods = array_nth(echelons,echelon);
if(type_of(echelon_methods) == WORD_TYPE)
return echelon_methods;
else if(echelon_methods != F)
{
CELL class = nth_superclass(layout,echelon);
CELL hashcode = untag_fixnum_fast(nth_hashcode(layout,echelon));
CELL result = search_lookup_hash(echelon_methods,class,hashcode);
if(result != F)
return result;
}
echelon--;
}
critical_error("Cannot find tuple method",object);
return F;
}
static CELL lookup_hi_tag_method(CELL object, CELL methods)
{
F_ARRAY *hi_tag_methods = untag_object(methods);
CELL hi_tag = object_type(object);
return array_nth(hi_tag_methods,hi_tag - HEADER_TYPE);
}
static CELL lookup_method(CELL object, CELL methods)
{
F_ARRAY *tag_methods = untag_object(methods);
CELL tag = TAG(object);
CELL element = array_nth(tag_methods,tag);
if(type_of(element) == WORD_TYPE)
return element;
else
{
switch(tag)
{
case TUPLE_TYPE:
return lookup_tuple_method(object,element);
case OBJECT_TYPE:
return lookup_hi_tag_method(object,element);
default:
critical_error("Bad methods array",methods);
return F;
}
}
}
void primitive_lookup_method(void)
{
CELL methods = dpop();
CELL object = dpop();
dpush(lookup_method(object,methods));
}

1
vm/dispatch.h Normal file
View File

@ -0,0 +1 @@
void primitive_lookup_method(void);

View File

@ -42,7 +42,7 @@ typedef signed long long s64;
#define F_TYPE 7 #define F_TYPE 7
#define F F_TYPE #define F F_TYPE
#define HEADER_TYPE 7 /* anything less than or equal to this is a tag */ #define HEADER_TYPE 8 /* anything less than this is a tag */
#define GC_COLLECTED 5 /* See gc.c */ #define GC_COLLECTED 5 /* See gc.c */

View File

@ -41,6 +41,7 @@
#include "callstack.h" #include "callstack.h"
#include "alien.h" #include "alien.h"
#include "quotations.h" #include "quotations.h"
#include "dispatch.h"
#include "factor.h" #include "factor.h"
#include "utilities.h" #include "utilities.h"

View File

@ -144,5 +144,6 @@ void *primitives[] = {
primitive_clear_gc_stats, primitive_clear_gc_stats,
primitive_jit_compile, primitive_jit_compile,
primitive_load_locals, primitive_load_locals,
primitive_check_datastack primitive_check_datastack,
primitive_lookup_method
}; };