diff --git a/basis/hints/hints-docs.factor b/basis/hints/hints-docs.factor index 347cfd3ef4..b8bda22ddc 100644 --- a/basis/hints/hints-docs.factor +++ b/basis/hints/hints-docs.factor @@ -1,10 +1,10 @@ IN: hints -USING: help.markup help.syntax words quotations sequences ; +USING: help.markup help.syntax words quotations sequences kernel ; ARTICLE: "hints" "Compiler specialization hints" "Specialization hints help the compiler generate efficient code." $nl -"Specialization hints can help words which call a lot of generic words on the same object - perhaps in a loop - and in most cases, it is anticipated that this object is of a certain class. Using specialization hints, the compiler can be instructed to compile a branch at the beginning of the word; if the branch is taken, the input object has the assumed class, and inlining of generic methods can take place." +"Specialization hints can help words which call a lot of generic words on the same object - perhaps in a loop - and in most cases, it is anticipated that this object is of a certain class, or even " { $link eq? } " to some literal. Using specialization hints, the compiler can be instructed to compile a branch at the beginning of the word; if the branch is taken, the input object has the assumed class or value, and inlining of generic methods can take place." $nl "Specialization hints are not declarations; if the inputs do not match what is specified, the word will still run, possibly slower if the compiled code cannot inline methods because of insufficient static type information." $nl @@ -20,10 +20,10 @@ HELP: specialized-def { $description "Outputs the definition of a word after it has been split into specialized branches. This is the definition which will actually be compiled by the compiler." } ; HELP: HINTS: -{ $values { "defspec" "a definition specifier" } { "hints..." "a list of sequences of classes" } } +{ $values { "defspec" "a definition specifier" } { "hints..." "a list of sequences of classes or literals" } } { $description "Defines specialization hints for a word or a method." $nl -"Each sequence of classes in the list will cause a specialized version of the word to be compiled." } +"Each sequence in the list will cause a specialized version of the word to be compiled. Classes are tested for using their predicate, and literals are tested using " { $link eq? } "." } { $examples "The " { $link append } " word has a specializer for the very common case where two strings or two arrays are appended:" { $code "HINTS: append { string string } { array array } ;" } "Specializers can also be defined on methods:" diff --git a/basis/hints/hints.factor b/basis/hints/hints.factor index 06ca209cae..240acf74b1 100644 --- a/basis/hints/hints.factor +++ b/basis/hints/hints.factor @@ -3,25 +3,34 @@ USING: parser words definitions kernel sequences assocs arrays kernel.private fry combinators accessors vectors strings sbufs byte-arrays byte-vectors io.binary io.streams.string splitting -math generic generic.standard generic.standard.engines ; +math generic generic.standard generic.standard.engines classes ; IN: hints -: (make-specializer) ( class picker -- quot ) - swap "predicate" word-prop append ; +GENERIC: specializer-predicate ( spec -- quot ) -: make-specializer ( classes -- quot ) +M: class specializer-predicate "predicate" word-prop ; + +M: object specializer-predicate '[ _ eq? ] ; + +GENERIC: specializer-declaration ( spec -- class ) + +M: class specializer-declaration ; + +M: object specializer-declaration class ; + +: make-specializer ( specs -- quot ) dup length [ (picker) 2array ] 2map [ drop object eq? not ] assoc-filter [ [ t ] ] [ - [ (make-specializer) ] { } assoc>map + [ swap specializer-predicate append ] { } assoc>map unclip [ swap [ f ] \ if 3array append [ ] like ] reduce ] if-empty ; : specializer-cases ( quot word -- default alist ) dup [ array? ] all? [ 1array ] unless [ [ make-specializer ] keep - '[ _ declare ] pick append + [ specializer-declaration ] map '[ _ declare ] pick append ] { } map>assoc ; : method-declaration ( method -- quot )