Make execute( faster, add execute-unsafe( and make effect tuple slots read only

db4
Slava Pestov 2009-03-01 20:12:35 -06:00
parent c57dbf8d48
commit 03cb32ad9c
10 changed files with 82 additions and 33 deletions

View File

@ -1,19 +1,25 @@
! Copyright (C) 2009 Daniel Ehrenberg. ! Copyright (C) 2009 Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax quotations effects words ; USING: help.markup help.syntax quotations effects words call.private ;
IN: call IN: call
ABOUT: "call" ABOUT: "call"
ARTICLE: "call" "Calling code with known stack effects" ARTICLE: "call" "Calling code with known stack effects"
"The " { $vocab-link "call" } " vocabulary allows for arbitrary quotations to be called from code accepted by the optimizing compiler. This is done by specifying the stack effect of the quotation literally. It is checked at runtime that the stack effect is accurate." "The " { $vocab-link "call" } " vocabulary allows for arbitrary quotations to be called from code accepted by the optimizing compiler. This is done by specifying the stack effect of the quotation literally. It is checked at runtime that the stack effect is accurate."
$nl
"Quotations:"
{ $subsection POSTPONE: call( } { $subsection POSTPONE: call( }
{ $subsection POSTPONE: execute( }
{ $subsection call-effect } { $subsection call-effect }
{ $subsection execute-effect } ; "Words:"
{ $subsection POSTPONE: execute( }
{ $subsection execute-effect }
"Unsafe calls:"
{ $subsection POSTPONE: execute-unsafe( }
{ $subsection execute-effect-unsafe } ;
HELP: call( HELP: call(
{ $syntax "[ ] call( foo -- bar )" } { $syntax "call( stack -- effect )" }
{ $description "Calls the quotation on the top of the stack, asserting that it has the given stack effect. The quotation does not need to be known at compile time." } ; { $description "Calls the quotation on the top of the stack, asserting that it has the given stack effect. The quotation does not need to be known at compile time." } ;
HELP: call-effect HELP: call-effect
@ -21,12 +27,21 @@ HELP: call-effect
{ $description "Given a quotation and a stack effect, calls the quotation, asserting at runtime that it has the given stack effect. This is a macro which expands given a literal effect parameter, and an arbitrary quotation which is not required at compile time." } ; { $description "Given a quotation and a stack effect, calls the quotation, asserting at runtime that it has the given stack effect. This is a macro which expands given a literal effect parameter, and an arbitrary quotation which is not required at compile time." } ;
HELP: execute( HELP: execute(
{ $syntax "word execute( foo -- bar )" } { $syntax "execute( stack -- effect )" }
{ $description "Calls the word on the top of the stack, aserting that it has the given stack effect. The word does not need to be known at compile time." } ; { $description "Calls the word on the top of the stack, asserting that it has the given stack effect. The word does not need to be known at compile time." } ;
HELP: execute-effect HELP: execute-effect
{ $values { "word" word } { "effect" effect } } { $values { "word" word } { "effect" effect } }
{ $description "Given a word and a stack effect, executes the word, asserting at runtime that it has the given stack effect. This is a macro which expands given a literal effect parameter, and an arbitrary word which is not required at compile time." } ; { $description "Given a word and a stack effect, executes the word, asserting at runtime that it has the given stack effect. This is a macro which expands given a literal effect parameter, and an arbitrary word which is not required at compile time." } ;
{ execute-effect call-effect } related-words HELP: execute-unsafe(
{ POSTPONE: call( POSTPONE: execute( } related-words { $syntax "execute-unsafe( stack -- effect )" }
{ $description "Calls the word on the top of the stack, blindly declaring that it has the given stack effect. The word does not need to be known at compile time." }
{ $warning "If the word being executed has an incorrect stack effect, undefined behavior will result. User code should use " { $link POSTPONE: execute( } " instead." } ;
HELP: execute-effect-unsafe
{ $values { "word" word } { "effect" effect } }
{ $description "Given a word and a stack effect, executes the word, blindly declaring at runtime that it has the given stack effect. This is a macro which expands given a literal effect parameter, and an arbitrary word which is not required at compile time." }
{ $warning "If the word being executed has an incorrect stack effect, undefined behavior will result. User code should use " { $link execute-effect-unsafe } " instead." } ;
{ call-effect execute-effect execute-effect-unsafe } related-words
{ POSTPONE: call( POSTPONE: execute( POSTPONE: execute-unsafe( } related-words

View File

@ -1,6 +1,6 @@
! Copyright (C) 2009 Daniel Ehrenberg. ! Copyright (C) 2009 Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: math tools.test call kernel ; USING: math tools.test call call.private kernel accessors ;
IN: call.tests IN: call.tests
[ 3 ] [ 1 2 [ + ] call( x y -- z ) ] unit-test [ 3 ] [ 1 2 [ + ] call( x y -- z ) ] unit-test
@ -13,3 +13,13 @@ IN: call.tests
[ 1 2 \ + execute( -- z ) ] must-fail [ 1 2 \ + execute( -- z ) ] must-fail
[ 1 2 \ + execute( x y -- z a ) ] must-fail [ 1 2 \ + execute( x y -- z a ) ] must-fail
[ \ + execute( x y -- z ) ] must-infer [ \ + execute( x y -- z ) ] must-infer
[ t ] [ \ + (( a b -- c )) execute-effect-unsafe? ] unit-test
[ t ] [ \ + (( a b c -- d e )) execute-effect-unsafe? ] unit-test
[ f ] [ \ + (( a b c -- d )) execute-effect-unsafe? ] unit-test
[ f ] [ \ call (( x -- )) execute-effect-unsafe? ] unit-test
: compile-execute(-test ( a b -- c ) \ + execute( a b -- c ) ;
[ t ] [ \ compile-execute(-test optimized>> ] unit-test
[ 4 ] [ 1 3 compile-execute(-test ] unit-test

View File

@ -1,7 +1,7 @@
! Copyright (C) 2009 Daniel Ehrenberg. ! Copyright (C) 2009 Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel macros fry summary sequences generalizations accessors USING: kernel macros fry summary sequences generalizations accessors
continuations effects.parser parser words ; continuations effects effects.parser parser words ;
IN: call IN: call
ERROR: wrong-values values quot length-required ; ERROR: wrong-values values quot length-required ;
@ -14,17 +14,29 @@ M: wrong-values summary
: firstn-safe ( array quot n -- ... ) : firstn-safe ( array quot n -- ... )
3dup nip swap length = [ nip firstn ] [ wrong-values ] if ; inline 3dup nip swap length = [ nip firstn ] [ wrong-values ] if ; inline
: execute-effect-unsafe ( word effect -- )
drop execute ;
: execute-effect-unsafe? ( word effect -- ? )
swap dup optimized>> [ stack-effect swap effect<= ] [ 2drop f ] if ; inline
: parse-call( ( accum word -- accum )
[ ")" parse-effect parsed ] dip parsed ;
: execute-unsafe( \ execute-effect-unsafe parse-call( ; parsing
PRIVATE> PRIVATE>
MACRO: call-effect ( effect -- quot ) MACRO: call-effect ( effect -- quot )
[ in>> length ] [ out>> length ] bi [ in>> length ] [ out>> length ] bi
'[ [ _ narray ] dip [ with-datastack ] keep _ firstn-safe ] ; '[ [ _ narray ] dip [ with-datastack ] keep _ firstn-safe ] ;
: call( : call( \ call-effect parse-call( ; parsing
")" parse-effect parsed \ call-effect parsed ; parsing
: execute-effect ( word effect -- ) : execute-effect ( word effect -- )
[ [ execute ] curry ] dip call-effect ; inline 2dup execute-effect-unsafe?
[ execute-effect-unsafe ]
[ [ [ execute ] curry ] dip call-effect ]
if ; inline
: execute( : execute( \ execute-effect parse-call( ; parsing
")" parse-effect parsed \ execute-effect parsed ; parsing

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: classes.tuple classes.tuple.parser kernel words USING: classes.tuple classes.tuple.parser kernel words
make fry sequences parser accessors ; make fry sequences parser accessors effects ;
IN: compiler.cfg.instructions.syntax IN: compiler.cfg.instructions.syntax
: insn-word ( -- word ) : insn-word ( -- word )
@ -11,7 +11,7 @@ IN: compiler.cfg.instructions.syntax
"insn" "compiler.cfg.instructions" lookup ; "insn" "compiler.cfg.instructions" lookup ;
: insn-effect ( word -- effect ) : insn-effect ( word -- effect )
boa-effect [ but-last ] change-in { } >>out ; boa-effect in>> but-last f <effect> ;
: INSN: : INSN:
parse-tuple-definition "regs" suffix parse-tuple-definition "regs" suffix

View File

@ -177,6 +177,9 @@ SYMBOL: history
: always-inline-word? ( word -- ? ) : always-inline-word? ( word -- ? )
{ curry compose } memq? ; { curry compose } memq? ;
: never-inline-word? ( word -- ? )
[ deferred? ] [ { call execute } memq? ] bi or ;
: custom-inlining? ( word -- ? ) : custom-inlining? ( word -- ? )
"custom-inlining" word-prop ; "custom-inlining" word-prop ;
@ -199,7 +202,7 @@ SYMBOL: history
#! calls the compiler at parse time (doing so is #! calls the compiler at parse time (doing so is
#! discouraged, but it should still work.) #! discouraged, but it should still work.)
{ {
{ [ dup deferred? ] [ 2drop f ] } { [ dup never-inline-word? ] [ 2drop f ] }
{ [ dup \ instance? eq? ] [ inline-instance-check ] } { [ dup \ instance? eq? ] [ inline-instance-check ] }
{ [ dup always-inline-word? ] [ inline-word ] } { [ dup always-inline-word? ] [ inline-word ] }
{ [ dup standard-generic? ] [ inline-standard-method ] } { [ dup standard-generic? ] [ inline-standard-method ] }

View File

@ -1,4 +1,4 @@
! Copyright (C) 2004, 2008 Slava Pestov. ! Copyright (C) 2004, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: fry accessors alien alien.accessors arrays byte-arrays USING: fry accessors alien alien.accessors arrays byte-arrays
classes sequences.private continuations.private effects generic classes sequences.private continuations.private effects generic
@ -11,7 +11,7 @@ strings.private system threads.private classes.tuple
classes.tuple.private vectors vectors.private words definitions 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 stack-checker.values quotations.private call call.private stack-checker.values
stack-checker.alien stack-checker.alien
stack-checker.state stack-checker.state
stack-checker.errors stack-checker.errors
@ -137,7 +137,14 @@ M: object infer-call*
: infer-(throw) ( -- ) : infer-(throw) ( -- )
\ (throw) \ (throw)
peek-d literal value>> 2 + f <effect> t >>terminated? peek-d literal value>> 2 + { "*" } <effect>
apply-word/effect ;
: infer-execute-effect-unsafe ( -- )
\ execute
pop-literal nip
[ in>> "word" suffix ] [ out>> ] [ terminated?>> ] tri
effect boa
apply-word/effect ; apply-word/effect ;
: infer-exit ( -- ) : infer-exit ( -- )
@ -178,6 +185,7 @@ M: object infer-call*
{ \ compose [ infer-compose ] } { \ compose [ infer-compose ] }
{ \ execute [ infer-execute ] } { \ execute [ infer-execute ] }
{ \ (execute) [ infer-execute ] } { \ (execute) [ infer-execute ] }
{ \ execute-effect-unsafe [ infer-execute-effect-unsafe ] }
{ \ if [ infer-if ] } { \ if [ infer-if ] }
{ \ dispatch [ infer-dispatch ] } { \ dispatch [ infer-dispatch ] }
{ \ <tuple-boa> [ infer-<tuple-boa> ] } { \ <tuple-boa> [ infer-<tuple-boa> ] }
@ -203,10 +211,10 @@ M: object infer-call*
"local-word-def" word-prop infer-quot-here ; "local-word-def" word-prop infer-quot-here ;
{ {
declare call (call) slip 2slip 3slip dip 2dip 3dip declare call (call) slip 2slip 3slip dip 2dip 3dip curry compose
curry compose execute (execute) if dispatch <tuple-boa> execute (execute) execute-effect-unsafe if dispatch <tuple-boa>
(throw) exit load-local load-locals get-local drop-locals do-primitive (throw) exit load-local load-locals get-local drop-locals
alien-invoke alien-indirect alien-callback do-primitive alien-invoke alien-indirect alien-callback
} [ t "special" set-word-prop ] each } [ t "special" set-word-prop ] each
{ call execute dispatch load-locals get-local drop-locals } { call execute dispatch load-locals get-local drop-locals }

View File

@ -37,9 +37,7 @@ SYMBOL: literals
: current-stack-height ( -- n ) meta-d length d-in get - ; : current-stack-height ( -- n ) meta-d length d-in get - ;
: current-effect ( -- effect ) : current-effect ( -- effect )
d-in get d-in get meta-d length terminated? get effect boa ;
meta-d length <effect>
terminated? get >>terminated? ;
: init-inference ( -- ) : init-inference ( -- )
terminated? off terminated? off

View File

@ -278,7 +278,7 @@ M: tuple-class (define-tuple-class)
[ 3drop ] [ redefine-tuple-class ] if ; [ 3drop ] [ redefine-tuple-class ] if ;
: thrower-effect ( slots -- effect ) : thrower-effect ( slots -- effect )
[ dup array? [ first ] when ] map f <effect> t >>terminated? ; [ dup array? [ first ] when ] map { "*" } <effect> ;
: define-error-class ( class superclass slots -- ) : define-error-class ( class superclass slots -- )
[ define-tuple-class ] [ define-tuple-class ]

View File

@ -4,14 +4,14 @@ USING: kernel math math.parser namespaces make sequences strings
words assocs combinators accessors arrays ; words assocs combinators accessors arrays ;
IN: effects IN: effects
TUPLE: effect in out terminated? ; TUPLE: effect { in read-only } { out read-only } { terminated? read-only } ;
: <effect> ( in out -- effect ) : <effect> ( in out -- effect )
dup { "*" } sequence= [ drop { } t ] [ f ] if dup { "*" } sequence= [ drop { } t ] [ f ] if
effect boa ; effect boa ;
: effect-height ( effect -- n ) : effect-height ( effect -- n )
[ out>> length ] [ in>> length ] bi - ; [ out>> length ] [ in>> length ] bi - ; inline
: effect<= ( eff1 eff2 -- ? ) : effect<= ( eff1 eff2 -- ? )
{ {
@ -20,7 +20,7 @@ TUPLE: effect in out terminated? ;
{ [ 2dup [ in>> length ] bi@ > ] [ f ] } { [ 2dup [ in>> length ] bi@ > ] [ f ] }
{ [ 2dup [ effect-height ] bi@ = not ] [ f ] } { [ 2dup [ effect-height ] bi@ = not ] [ f ] }
[ t ] [ t ]
} cond 2nip ; } cond 2nip ; inline
GENERIC: effect>string ( obj -- str ) GENERIC: effect>string ( obj -- str )
M: string effect>string ; M: string effect>string ;

View File

@ -77,7 +77,10 @@ PREDICATE: engine-word < word
M: engine-word stack-effect M: engine-word stack-effect
"tuple-dispatch-generic" word-prop "tuple-dispatch-generic" word-prop
[ extra-values ] [ stack-effect ] bi [ extra-values ] [ stack-effect ] bi
dup [ clone [ length + ] change-in ] [ 2drop f ] if ; dup [
[ in>> length + ] [ out>> ] [ terminated?>> ] tri
effect boa
] [ 2drop f ] if ;
M: engine-word crossref? "forgotten" word-prop not ; M: engine-word crossref? "forgotten" word-prop not ;