Add new check-datastack primitive and re-implement call( with it, instead of using with-datastack. call( is now 5x faster
parent
58d997de5c
commit
1559b74640
|
@ -6,7 +6,7 @@ IN: call.tests
|
||||||
[ 3 ] [ 1 2 [ + ] call( x y -- z ) ] unit-test
|
[ 3 ] [ 1 2 [ + ] call( x y -- z ) ] unit-test
|
||||||
[ 1 2 [ + ] call( -- z ) ] must-fail
|
[ 1 2 [ + ] call( -- z ) ] must-fail
|
||||||
[ 1 2 [ + ] call( x y -- z a ) ] must-fail
|
[ 1 2 [ + ] call( x y -- z a ) ] must-fail
|
||||||
[ 1 2 3 { 4 } ] [ 1 2 3 4 [ datastack nip ] call( x -- y ) ] unit-test
|
[ 1 2 3 { 1 2 3 4 } ] [ 1 2 3 4 [ datastack nip ] call( x -- y ) ] unit-test
|
||||||
[ [ + ] call( x y -- z ) ] must-infer
|
[ [ + ] call( x y -- z ) ] must-infer
|
||||||
|
|
||||||
[ 3 ] [ 1 2 \ + execute( x y -- z ) ] unit-test
|
[ 3 ] [ 1 2 \ + execute( x y -- z ) ] unit-test
|
||||||
|
|
|
@ -1,28 +1,39 @@
|
||||||
! Copyright (C) 2009 Daniel Ehrenberg, Slava Pestov.
|
! Copyright (C) 2009 Daniel Ehrenberg, Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: kernel macros fry summary sequences sequences.private
|
USING: kernel kernel.private macros fry summary sequences
|
||||||
generalizations accessors continuations effects effects.parser
|
sequences.private accessors effects effects.parser parser words
|
||||||
parser words ;
|
make ;
|
||||||
IN: call
|
IN: call
|
||||||
|
|
||||||
ERROR: wrong-values values quot length-required ;
|
ERROR: wrong-values effect ;
|
||||||
|
|
||||||
M: wrong-values summary
|
M: wrong-values summary drop "Quotation called with stack effect" ;
|
||||||
drop "Wrong number of values returned from quotation" ;
|
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
|
||||||
: firstn-safe ( array quot n -- ... )
|
|
||||||
3dup nip swap length = [ nip firstn ] [ wrong-values ] if ; inline
|
|
||||||
|
|
||||||
: parse-call( ( accum word -- accum )
|
: parse-call( ( accum word -- accum )
|
||||||
[ ")" parse-effect parsed ] dip parsed ;
|
[ ")" parse-effect parsed ] dip parsed ;
|
||||||
|
|
||||||
|
: call-effect-unsafe ( quot effect -- )
|
||||||
|
drop call ;
|
||||||
|
|
||||||
|
: call-unsafe( \ call-effect-unsafe parse-call( ; parsing
|
||||||
|
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
|
: (call-effect>quot) ( in out effect -- quot )
|
||||||
|
[
|
||||||
|
[ [ datastack ] dip dip ] %
|
||||||
|
[ [ , ] bi@ \ check-datastack , ] dip [ wrong-values ] curry , \ unless ,
|
||||||
|
] [ ] make ;
|
||||||
|
|
||||||
|
: call-effect>quot ( effect -- quot )
|
||||||
|
[ in>> length ] [ out>> length ] [ ] tri
|
||||||
|
[ (call-effect>quot) ] keep add-effect-input
|
||||||
|
[ call-effect-unsafe ] 2curry ;
|
||||||
|
|
||||||
MACRO: call-effect ( effect -- quot )
|
MACRO: call-effect ( effect -- quot )
|
||||||
[ in>> length ] [ out>> length ] bi
|
call-effect>quot ;
|
||||||
'[ [ _ narray ] dip [ with-datastack ] keep _ firstn-safe ] ;
|
|
||||||
|
|
||||||
: call( \ call-effect parse-call( ; parsing
|
: call( \ call-effect parse-call( ; parsing
|
||||||
|
|
||||||
|
@ -44,17 +55,20 @@ MACRO: call-effect ( effect -- quot )
|
||||||
over optimized>> [ [ stack-effect ] dip effect<= ] [ 2drop f ] if ; inline
|
over optimized>> [ [ stack-effect ] dip effect<= ] [ 2drop f ] if ; inline
|
||||||
|
|
||||||
: cache-miss ( word effect ic -- )
|
: cache-miss ( word effect ic -- )
|
||||||
[ 2dup execute-effect-unsafe? ] dip
|
2over execute-effect-unsafe?
|
||||||
'[ [ drop _ set-first ] [ execute-effect-unsafe ] 2bi ]
|
[ [ nip set-first ] [ drop execute-effect-unsafe ] 3bi ]
|
||||||
[ execute-effect-slow ] if ; inline
|
[ execute-effect-slow ] if ; inline
|
||||||
|
|
||||||
: execute-effect-ic ( word effect ic -- )
|
: execute-effect-ic ( word effect ic -- )
|
||||||
#! ic is a mutable cell { effect }
|
#! ic is a mutable cell { effect }
|
||||||
3dup nip cache-hit? [ cache-hit ] [ cache-miss ] if ; inline
|
3dup nip cache-hit? [ cache-hit ] [ cache-miss ] if ; inline
|
||||||
|
|
||||||
|
: execute-effect>quot ( effect -- quot )
|
||||||
|
{ f } clone [ execute-effect-ic ] 2curry ;
|
||||||
|
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
MACRO: execute-effect ( effect -- )
|
MACRO: execute-effect ( effect -- )
|
||||||
{ f } clone '[ _ _ execute-effect-ic ] ;
|
execute-effect>quot ;
|
||||||
|
|
||||||
: execute( \ execute-effect parse-call( ; parsing
|
: execute( \ execute-effect parse-call( ; parsing
|
||||||
|
|
|
@ -140,13 +140,17 @@ M: object infer-call*
|
||||||
peek-d literal value>> 2 + { "*" } <effect>
|
peek-d literal value>> 2 + { "*" } <effect>
|
||||||
apply-word/effect ;
|
apply-word/effect ;
|
||||||
|
|
||||||
: infer-execute-effect-unsafe ( -- )
|
: infer-effect-unsafe ( word -- )
|
||||||
\ execute
|
|
||||||
pop-literal nip
|
pop-literal nip
|
||||||
[ in>> "word" suffix ] [ out>> ] [ terminated?>> ] tri
|
add-effect-input
|
||||||
effect boa
|
|
||||||
apply-word/effect ;
|
apply-word/effect ;
|
||||||
|
|
||||||
|
: infer-execute-effect-unsafe ( -- )
|
||||||
|
\ execute infer-effect-unsafe ;
|
||||||
|
|
||||||
|
: infer-call-effect-unsafe ( -- )
|
||||||
|
\ call infer-effect-unsafe ;
|
||||||
|
|
||||||
: infer-exit ( -- )
|
: infer-exit ( -- )
|
||||||
\ exit (( n -- * )) apply-word/effect ;
|
\ exit (( n -- * )) apply-word/effect ;
|
||||||
|
|
||||||
|
@ -186,6 +190,7 @@ M: object infer-call*
|
||||||
{ \ execute [ infer-execute ] }
|
{ \ execute [ infer-execute ] }
|
||||||
{ \ (execute) [ infer-execute ] }
|
{ \ (execute) [ infer-execute ] }
|
||||||
{ \ execute-effect-unsafe [ infer-execute-effect-unsafe ] }
|
{ \ execute-effect-unsafe [ infer-execute-effect-unsafe ] }
|
||||||
|
{ \ call-effect-unsafe [ infer-call-effect-unsafe ] }
|
||||||
{ \ if [ infer-if ] }
|
{ \ if [ infer-if ] }
|
||||||
{ \ dispatch [ infer-dispatch ] }
|
{ \ dispatch [ infer-dispatch ] }
|
||||||
{ \ <tuple-boa> [ infer-<tuple-boa> ] }
|
{ \ <tuple-boa> [ infer-<tuple-boa> ] }
|
||||||
|
@ -212,9 +217,10 @@ M: object infer-call*
|
||||||
|
|
||||||
{
|
{
|
||||||
declare call (call) slip 2slip 3slip dip 2dip 3dip curry compose
|
declare call (call) slip 2slip 3slip dip 2dip 3dip curry compose
|
||||||
execute (execute) execute-effect-unsafe if dispatch <tuple-boa>
|
execute (execute) call-effect-unsafe execute-effect-unsafe if
|
||||||
(throw) exit load-local load-locals get-local drop-locals
|
dispatch <tuple-boa> (throw) exit load-local load-locals get-local
|
||||||
do-primitive alien-invoke alien-indirect alien-callback
|
drop-locals 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 }
|
||||||
|
@ -627,6 +633,9 @@ M: object infer-call*
|
||||||
\ datastack { } { array } define-primitive
|
\ datastack { } { array } define-primitive
|
||||||
\ datastack make-flushable
|
\ datastack make-flushable
|
||||||
|
|
||||||
|
\ check-datastack { array integer integer } { object } define-primitive
|
||||||
|
\ check-datastack make-flushable
|
||||||
|
|
||||||
\ retainstack { } { array } define-primitive
|
\ retainstack { } { array } define-primitive
|
||||||
\ retainstack make-flushable
|
\ retainstack make-flushable
|
||||||
|
|
||||||
|
|
|
@ -533,6 +533,7 @@ tuple
|
||||||
{ "gc-reset" "memory" }
|
{ "gc-reset" "memory" }
|
||||||
{ "jit-compile" "quotations" }
|
{ "jit-compile" "quotations" }
|
||||||
{ "load-locals" "locals.backend" }
|
{ "load-locals" "locals.backend" }
|
||||||
|
{ "check-datastack" "kernel.private" }
|
||||||
}
|
}
|
||||||
[ [ first2 ] dip make-primitive ] each-index
|
[ [ first2 ] dip make-primitive ] each-index
|
||||||
|
|
||||||
|
|
|
@ -63,3 +63,6 @@ M: effect clone
|
||||||
|
|
||||||
: shuffle ( stack shuffle -- newstack )
|
: shuffle ( stack shuffle -- newstack )
|
||||||
shuffle-mapping swap nths ;
|
shuffle-mapping swap nths ;
|
||||||
|
|
||||||
|
: add-effect-input ( effect -- effect' )
|
||||||
|
[ in>> "obj" suffix ] [ out>> ] [ terminated?>> ] tri effect boa ;
|
||||||
|
|
|
@ -14,8 +14,6 @@ CELL frame_scan(F_STACK_FRAME *frame);
|
||||||
CELL frame_type(F_STACK_FRAME *frame);
|
CELL frame_type(F_STACK_FRAME *frame);
|
||||||
|
|
||||||
void primitive_callstack(void);
|
void primitive_callstack(void);
|
||||||
void primitive_set_datastack(void);
|
|
||||||
void primitive_set_retainstack(void);
|
|
||||||
void primitive_set_callstack(void);
|
void primitive_set_callstack(void);
|
||||||
void primitive_callstack_to_array(void);
|
void primitive_callstack_to_array(void);
|
||||||
void primitive_innermost_stack_frame_quot(void);
|
void primitive_innermost_stack_frame_quot(void);
|
||||||
|
|
|
@ -144,4 +144,5 @@ 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
|
||||||
};
|
};
|
||||||
|
|
26
vm/run.c
26
vm/run.c
|
@ -155,6 +155,32 @@ void primitive_set_retainstack(void)
|
||||||
rs = array_to_stack(untag_array(dpop()),rs_bot);
|
rs = array_to_stack(untag_array(dpop()),rs_bot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Used to implement call( */
|
||||||
|
void primitive_check_datastack(void)
|
||||||
|
{
|
||||||
|
F_FIXNUM out = to_fixnum(dpop());
|
||||||
|
F_FIXNUM in = to_fixnum(dpop());
|
||||||
|
F_FIXNUM height = out - in;
|
||||||
|
F_ARRAY *array = untag_array(dpop());
|
||||||
|
F_FIXNUM length = array_capacity(array);
|
||||||
|
F_FIXNUM depth = (ds - ds_bot + CELLS) / CELLS;
|
||||||
|
if(depth - height != length)
|
||||||
|
dpush(F);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
F_FIXNUM i;
|
||||||
|
for(i = 0; i < length - in; i++)
|
||||||
|
{
|
||||||
|
if(get(ds_bot + i * CELLS) != array_nth(array,i))
|
||||||
|
{
|
||||||
|
dpush(F);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dpush(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void primitive_getenv(void)
|
void primitive_getenv(void)
|
||||||
{
|
{
|
||||||
F_FIXNUM e = untag_fixnum_fast(dpeek());
|
F_FIXNUM e = untag_fixnum_fast(dpeek());
|
||||||
|
|
3
vm/run.h
3
vm/run.h
|
@ -236,6 +236,9 @@ void init_stacks(CELL ds_size, CELL rs_size);
|
||||||
|
|
||||||
void primitive_datastack(void);
|
void primitive_datastack(void);
|
||||||
void primitive_retainstack(void);
|
void primitive_retainstack(void);
|
||||||
|
void primitive_set_datastack(void);
|
||||||
|
void primitive_set_retainstack(void);
|
||||||
|
void primitive_check_datastack(void);
|
||||||
void primitive_getenv(void);
|
void primitive_getenv(void);
|
||||||
void primitive_setenv(void);
|
void primitive_setenv(void);
|
||||||
void primitive_exit(void);
|
void primitive_exit(void);
|
||||||
|
|
Loading…
Reference in New Issue