Merge branch 'master' of git://factorcode.org/git/factor

db4
Doug Coleman 2009-10-16 12:51:25 -05:00
commit 7d43abe49b
43 changed files with 388 additions and 146 deletions

View File

@ -37,6 +37,7 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
vm/bignum.o \ vm/bignum.o \
vm/booleans.o \ vm/booleans.o \
vm/byte_arrays.o \ vm/byte_arrays.o \
vm/callbacks.o \
vm/callstack.o \ vm/callstack.o \
vm/code_block.o \ vm/code_block.o \
vm/code_heap.o \ vm/code_heap.o \

View File

@ -83,7 +83,7 @@ M: string resolve-pointer-type
: parse-array-type ( name -- dims c-type ) : parse-array-type ( name -- dims c-type )
"[" split unclip "[" split unclip
[ [ "]" ?tail drop string>number ] map ] dip ; [ [ "]" ?tail drop parse-word ] map ] dip ;
M: string c-type ( name -- c-type ) M: string c-type ( name -- c-type )
CHAR: ] over member? [ CHAR: ] over member? [

View File

@ -8,6 +8,8 @@ TYPEDEF: char char2
SYMBOL: not-c-type SYMBOL: not-c-type
CONSTANT: eleven 11
[ [
"alien.parser.tests" use-vocab "alien.parser.tests" use-vocab
"alien.c-types" use-vocab "alien.c-types" use-vocab
@ -15,6 +17,7 @@ SYMBOL: not-c-type
[ int ] [ "int" parse-c-type ] unit-test [ int ] [ "int" parse-c-type ] unit-test
[ { int 5 } ] [ "int[5]" parse-c-type ] unit-test [ { int 5 } ] [ "int[5]" parse-c-type ] unit-test
[ { int 5 10 11 } ] [ "int[5][10][11]" parse-c-type ] unit-test [ { int 5 10 11 } ] [ "int[5][10][11]" parse-c-type ] unit-test
[ { int 5 10 eleven } ] [ "int[5][10][eleven]" parse-c-type ] unit-test
[ void* ] [ "int*" parse-c-type ] unit-test [ void* ] [ "int*" parse-c-type ] unit-test
[ void* ] [ "int**" parse-c-type ] unit-test [ void* ] [ "int**" parse-c-type ] unit-test
[ void* ] [ "int***" parse-c-type ] unit-test [ void* ] [ "int***" parse-c-type ] unit-test

View File

@ -172,6 +172,8 @@ USERENV: jit-execute-jump 42
USERENV: jit-execute-call 43 USERENV: jit-execute-call 43
USERENV: jit-declare-word 44 USERENV: jit-declare-word 44
USERENV: callback-stub 45
! PIC stubs ! PIC stubs
USERENV: pic-load 47 USERENV: pic-load 47
USERENV: pic-tag 48 USERENV: pic-tag 48

View File

@ -355,16 +355,12 @@ FUNCTION: ulonglong ffi_test_38 ( ulonglong x, ulonglong y ) ;
"testing" callback-5 callback_test_1 "testing" callback-5 callback_test_1
] unit-test ] unit-test
: callback-5a ( -- callback ) : callback-5b ( -- callback )
"void" { } "cdecl" [ 8000000 f <array> drop ] alien-callback ; "void" { } "cdecl" [ compact-gc ] alien-callback ;
! Hack; if we're on ARM, we probably don't have much RAM, so [ "testing" ] [
! skip this test. "testing" callback-5b callback_test_1
! cpu "arm" = [ ] unit-test
! [ "testing" ] [
! "testing" callback-5a callback_test_1
! ] unit-test
! ] unless
: callback-6 ( -- callback ) : callback-6 ( -- callback )
"void" { } "cdecl" [ [ continue ] callcc0 ] alien-callback ; "void" { } "cdecl" [ [ continue ] callcc0 ] alien-callback ;
@ -593,3 +589,4 @@ FUNCTION: short ffi_test_48 ( bool-field-test x ) ;
FUNCTION: void this_does_not_exist ( ) ; FUNCTION: void this_does_not_exist ( ) ;
[ this_does_not_exist ] [ { "kernel-error" 10 f f } = ] must-fail-with [ this_does_not_exist ] [ { "kernel-error" 10 f f } = ] must-fail-with

View File

@ -249,6 +249,12 @@ CONSTANT: rs-reg 14
! fall-through on miss ! fall-through on miss
] mega-lookup jit-define ] mega-lookup jit-define
[
0 2 LOAD32 rc-absolute-ppc-2/2 rt-xt jit-rel
2 MTCTR
BCTR
] callback-stub jit-define
! ! ! Sub-primitives ! ! ! Sub-primitives
! Quotations and words ! Quotations and words

View File

@ -715,7 +715,9 @@ M: ppc %box-small-struct ( c-type -- )
3 3 0 LWZ ; 3 3 0 LWZ ;
M: ppc %nest-stacks ( -- ) M: ppc %nest-stacks ( -- )
3 %load-vm-addr ! Save current frame. See comment in vm/contexts.hpp
3 1 stack-frame get total-size>> 2 cells - ADDI
4 %load-vm-addr
"nest_stacks" f %alien-invoke ; "nest_stacks" f %alien-invoke ;
M: ppc %unnest-stacks ( -- ) M: ppc %unnest-stacks ( -- )

View File

@ -120,11 +120,9 @@ M: x86.32 %save-param-reg 3drop ;
#! parameter being passed to a callback from C. #! parameter being passed to a callback from C.
over [ load-return-reg ] [ 2drop ] if ; over [ load-return-reg ] [ 2drop ] if ;
CONSTANT: vm-ptr-size 4
M:: x86.32 %box ( n rep func -- ) M:: x86.32 %box ( n rep func -- )
n rep (%box) n rep (%box)
rep rep-size vm-ptr-size + [ rep rep-size cell + [
push-vm-ptr push-vm-ptr
rep push-return-reg rep push-return-reg
func f %alien-invoke func f %alien-invoke
@ -138,7 +136,7 @@ M:: x86.32 %box ( n rep func -- )
M: x86.32 %box-long-long ( n func -- ) M: x86.32 %box-long-long ( n func -- )
[ (%box-long-long) ] dip [ (%box-long-long) ] dip
8 vm-ptr-size + [ 12 [
push-vm-ptr push-vm-ptr
EDX PUSH EDX PUSH
EAX PUSH EAX PUSH
@ -148,7 +146,7 @@ M: x86.32 %box-long-long ( n func -- )
M:: x86.32 %box-large-struct ( n c-type -- ) M:: x86.32 %box-large-struct ( n c-type -- )
! Compute destination address ! Compute destination address
EDX n struct-return@ LEA EDX n struct-return@ LEA
8 vm-ptr-size + [ 12 [
push-vm-ptr push-vm-ptr
! Push struct size ! Push struct size
c-type heap-size PUSH c-type heap-size PUSH
@ -166,7 +164,7 @@ M: x86.32 %prepare-box-struct ( -- )
M: x86.32 %box-small-struct ( c-type -- ) M: x86.32 %box-small-struct ( c-type -- )
#! Box a <= 8-byte struct returned in EAX:EDX. OS X only. #! Box a <= 8-byte struct returned in EAX:EDX. OS X only.
12 vm-ptr-size + [ 16 [
push-vm-ptr push-vm-ptr
heap-size PUSH heap-size PUSH
EDX PUSH EDX PUSH
@ -208,7 +206,7 @@ M: x86.32 %unbox-long-long ( n func -- )
: %unbox-struct-1 ( -- ) : %unbox-struct-1 ( -- )
#! Alien must be in EAX. #! Alien must be in EAX.
4 vm-ptr-size + [ 8 [
push-vm-ptr push-vm-ptr
EAX PUSH EAX PUSH
"alien_offset" f %alien-invoke "alien_offset" f %alien-invoke
@ -218,7 +216,7 @@ M: x86.32 %unbox-long-long ( n func -- )
: %unbox-struct-2 ( -- ) : %unbox-struct-2 ( -- )
#! Alien must be in EAX. #! Alien must be in EAX.
4 vm-ptr-size + [ 8 [
push-vm-ptr push-vm-ptr
EAX PUSH EAX PUSH
"alien_offset" f %alien-invoke "alien_offset" f %alien-invoke
@ -239,7 +237,7 @@ M:: x86.32 %unbox-large-struct ( n c-type -- )
! Alien must be in EAX. ! Alien must be in EAX.
! Compute destination address ! Compute destination address
EDX n stack@ LEA EDX n stack@ LEA
12 vm-ptr-size + [ 16 [
push-vm-ptr push-vm-ptr
! Push struct size ! Push struct size
c-type heap-size PUSH c-type heap-size PUSH
@ -252,8 +250,11 @@ M:: x86.32 %unbox-large-struct ( n c-type -- )
] with-aligned-stack ; ] with-aligned-stack ;
M: x86.32 %nest-stacks ( -- ) M: x86.32 %nest-stacks ( -- )
4 [ 8 [
push-vm-ptr push-vm-ptr
! Save current frame. See comment in vm/contexts.hpp
EAX stack-reg stack-frame get total-size>> [+] LEA
EAX PUSH
"nest_stacks" f %alien-invoke "nest_stacks" f %alien-invoke
] with-aligned-stack ; ] with-aligned-stack ;

View File

@ -17,6 +17,7 @@ IN: bootstrap.x86
: temp1 ( -- reg ) EDX ; : temp1 ( -- reg ) EDX ;
: temp2 ( -- reg ) ECX ; : temp2 ( -- reg ) ECX ;
: temp3 ( -- reg ) EBX ; : temp3 ( -- reg ) EBX ;
: safe-reg ( -- reg ) EAX ;
: stack-reg ( -- reg ) ESP ; : stack-reg ( -- reg ) ESP ;
: ds-reg ( -- reg ) ESI ; : ds-reg ( -- reg ) ESI ;
: rs-reg ( -- reg ) EDI ; : rs-reg ( -- reg ) EDI ;

View File

@ -194,7 +194,9 @@ M: x86.64 %alien-invoke
R11 CALL ; R11 CALL ;
M: x86.64 %nest-stacks ( -- ) M: x86.64 %nest-stacks ( -- )
param-reg-1 %mov-vm-ptr ! Save current frame. See comment in vm/contexts.hpp
param-reg-1 stack-reg stack-frame get total-size>> 3 cells - [+] LEA
param-reg-2 %mov-vm-ptr
"nest_stacks" f %alien-invoke ; "nest_stacks" f %alien-invoke ;
M: x86.64 %unnest-stacks ( -- ) M: x86.64 %unnest-stacks ( -- )

View File

@ -14,6 +14,7 @@ IN: bootstrap.x86
: temp1 ( -- reg ) RSI ; : temp1 ( -- reg ) RSI ;
: temp2 ( -- reg ) RDX ; : temp2 ( -- reg ) RDX ;
: temp3 ( -- reg ) RBX ; : temp3 ( -- reg ) RBX ;
: safe-reg ( -- reg ) RAX ;
: stack-reg ( -- reg ) RSP ; : stack-reg ( -- reg ) RSP ;
: ds-reg ( -- reg ) R14 ; : ds-reg ( -- reg ) R14 ;
: rs-reg ( -- reg ) R15 ; : rs-reg ( -- reg ) R15 ;

View File

@ -243,6 +243,11 @@ big-endian off
! fall-through on miss ! fall-through on miss
] mega-lookup jit-define ] mega-lookup jit-define
[
safe-reg 0 MOV rc-absolute-cell rt-xt jit-rel
safe-reg JMP
] callback-stub jit-define
! ! ! Sub-primitives ! ! ! Sub-primitives
! Quotations and words ! Quotations and words

View File

@ -1,8 +1,7 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences accessors combinators math namespaces USING: kernel sequences accessors combinators math namespaces
init sets words alien.libraries init sets words assocs alien.libraries alien alien.c-types
alien alien.c-types
stack-checker.backend stack-checker.errors stack-checker.visitor ; stack-checker.backend stack-checker.errors stack-checker.visitor ;
IN: stack-checker.alien IN: stack-checker.alien
@ -58,11 +57,11 @@ TUPLE: alien-callback-params < alien-node-params quot xt ;
! Quotation which coerces return value to required type ! Quotation which coerces return value to required type
return-prep-quot infer-quot-here ; return-prep-quot infer-quot-here ;
: register-callback ( word -- ) callbacks get conjoin ; : callback-xt ( word -- alien )
callbacks get [ <callback> ] cache ;
: callback-bottom ( params -- ) : callback-bottom ( params -- )
xt>> [ [ register-callback ] [ word-xt drop <alien> ] bi ] curry xt>> [ callback-xt ] curry infer-quot-here ;
infer-quot-here ;
: infer-alien-callback ( -- ) : infer-alien-callback ( -- )
alien-callback-params new alien-callback-params new
@ -70,6 +69,6 @@ TUPLE: alien-callback-params < alien-node-params quot xt ;
pop-literal nip >>abi pop-literal nip >>abi
pop-literal nip >>parameters pop-literal nip >>parameters
pop-literal nip >>return pop-literal nip >>return
gensym >>xt "( callback )" f <word> >>xt
dup callback-bottom dup callback-bottom
#alien-callback, ; #alien-callback, ;

View File

@ -495,8 +495,12 @@ M: bad-executable summary
\ (exists?) { string } { object } define-primitive \ (exists?) { string } { object } define-primitive
\ minor-gc { } { } define-primitive
\ gc { } { } define-primitive \ gc { } { } define-primitive
\ compact-gc { } { } define-primitive
\ gc-stats { } { array } define-primitive \ gc-stats { } { array } define-primitive
\ (save-image) { byte-array } { } define-primitive \ (save-image) { byte-array } { } define-primitive
@ -711,3 +715,7 @@ M: bad-executable summary
\ inline-cache-stats { } { array } define-primitive \ inline-cache-stats { } { array } define-primitive
\ optimized? { word } { object } define-primitive \ optimized? { word } { object } define-primitive
\ strip-stack-traces { } { } define-primitive
\ <callback> { word } { alien } define-primitive

View File

@ -175,13 +175,6 @@ HELP: alien-invoke-error
} }
} ; } ;
ARTICLE: "alien-callback-gc" "Callbacks and code GC"
"A callback consits of two parts; the callback word, which pushes the address of the callback on the stack when executed, and the callback body itself. If the callback word is redefined, removed from the dictionary using " { $link forget } ", or recompiled, the callback body will not be reclaimed by the garbage collector, since potentially C code may be holding a reference to the callback body."
$nl
"This is the safest approach, however it can lead to code heap leaks when repeatedly reloading code which defines callbacks. If you are " { $emphasis "completely sure" } " that no running C code is holding a reference to any callbacks, you can blow them all away:"
{ $code "USE: alien callbacks get clear-hash gc" }
"This will reclaim all callback bodies which are otherwise unreachable from the dictionary (that is, their associated callback words have since been redefined, recompiled or forgotten)." ;
ARTICLE: "alien-callback" "Calling Factor from C" ARTICLE: "alien-callback" "Calling Factor from C"
"Callbacks can be defined and passed to C code as function pointers; the C code can then invoke the callback and run Factor code:" "Callbacks can be defined and passed to C code as function pointers; the C code can then invoke the callback and run Factor code:"
{ $subsections { $subsections
@ -189,7 +182,6 @@ ARTICLE: "alien-callback" "Calling Factor from C"
POSTPONE: CALLBACK: POSTPONE: CALLBACK:
} }
"There are some caveats concerning the conversion of Factor objects to C values, and vice versa. See " { $link "c-data" } "." "There are some caveats concerning the conversion of Factor objects to C values, and vice versa. See " { $link "c-data" } "."
{ $subsections "alien-callback-gc" }
{ $see-also "byte-arrays-gc" } ; { $see-also "byte-arrays-gc" } ;
ARTICLE: "alien-globals" "Accessing C global variables" ARTICLE: "alien-globals" "Accessing C global variables"

View File

@ -66,8 +66,10 @@ ERROR: alien-invoke-error library symbol ;
: alien-invoke ( ... return library function parameters -- ... ) : alien-invoke ( ... return library function parameters -- ... )
2over alien-invoke-error ; 2over alien-invoke-error ;
! Callbacks are registered in a global hashtable. If you clear ! Callbacks are registered in a global hashtable. Note that they
! this hashtable, they will all be blown away by code GC, beware. ! are also pinned in a special callback area, so clearing this
! hashtable will not reclaim callbacks. It should only be
! cleared on startup.
SYMBOL: callbacks SYMBOL: callbacks
[ H{ } clone callbacks set-global ] "alien" add-init-hook [ H{ } clone callbacks set-global ] "alien" add-init-hook

View File

@ -420,7 +420,9 @@ tuple
{ "getenv" "kernel.private" (( n -- obj )) } { "getenv" "kernel.private" (( n -- obj )) }
{ "setenv" "kernel.private" (( obj n -- )) } { "setenv" "kernel.private" (( obj n -- )) }
{ "(exists?)" "io.files.private" (( path -- ? )) } { "(exists?)" "io.files.private" (( path -- ? )) }
{ "minor-gc" "memory" (( -- )) }
{ "gc" "memory" (( -- )) } { "gc" "memory" (( -- )) }
{ "compact-gc" "memory" (( -- )) }
{ "gc-stats" "memory" f } { "gc-stats" "memory" f }
{ "(save-image)" "memory.private" (( path -- )) } { "(save-image)" "memory.private" (( path -- )) }
{ "(save-image-and-exit)" "memory.private" (( path -- )) } { "(save-image-and-exit)" "memory.private" (( path -- )) }
@ -523,6 +525,7 @@ tuple
{ "quot-compiled?" "quotations" (( quot -- ? )) } { "quot-compiled?" "quotations" (( quot -- ? )) }
{ "vm-ptr" "vm" (( -- ptr )) } { "vm-ptr" "vm" (( -- ptr )) }
{ "strip-stack-traces" "kernel.private" (( -- )) } { "strip-stack-traces" "kernel.private" (( -- )) }
{ "<callback>" "alien" (( word -- alien )) }
} [ [ first3 ] dip swap make-primitive ] each-index } [ [ first3 ] dip swap make-primitive ] each-index
! Bump build number ! Bump build number

View File

@ -140,12 +140,20 @@ HELP: no-word
{ $values { "name" string } { "newword" word } } { $values { "name" string } { "newword" word } }
{ $description "Throws a " { $link no-word-error } "." } ; { $description "Throws a " { $link no-word-error } "." } ;
HELP: parse-word
{ $values { "string" string } { "word/number" "a word or number" } }
{ $description "If " { $snippet "string" } " is a valid number literal, it is converted to a number, otherwise the current vocabulary search path is searched for a word named by the string." }
{ $errors "Throws an error if the token does not name a word, and does not parse as a number." }
{ $notes "This word is used to implement " { $link scan-word } "." } ;
HELP: scan-word HELP: scan-word
{ $values { "word/number/f" "a word, number or " { $link f } } } { $values { "word/number/f" "a word, number or " { $link f } } }
{ $description "Reads the next token from parser input. If the token is a valid number literal, it is converted to a number, otherwise the dictionary is searched for a word named by the token. Outputs " { $link f } " if the end of the input has been reached." } { $description "Reads the next token from parser input. If the token is a valid number literal, it is converted to a number, otherwise the vocabulary search path is searched for a word named by the token. Outputs " { $link f } " if the end of the input has been reached." }
{ $errors "Throws an error if the token does not name a word, and does not parse as a number." } { $errors "Throws an error if the token does not name a word, and does not parse as a number." }
$parsing-note ; $parsing-note ;
{ scan-word parse-word } related-words
HELP: parse-step HELP: parse-step
{ $values { "accum" vector } { "end" word } { "?" "a boolean" } } { $values { "accum" vector } { "end" word } { "?" "a boolean" } }
{ $description "Parses a token. If the token is a number or an ordinary word, it is added to the accumulator. If it is a parsing word, calls the parsing word with the accumulator on the stack. Outputs " { $link f } " if " { $snippet "end" } " is encountered, " { $link t } " otherwise." } { $description "Parses a token. If the token is a number or an ordinary word, it is added to the accumulator. If it is a parsing word, calls the parsing word with the accumulator on the stack. Outputs " { $link f } " if " { $snippet "end" } " is encountered, " { $link t } " otherwise." }

View File

@ -40,12 +40,13 @@ SYMBOL: auto-use?
[ <no-word-error> throw-restarts no-word-restarted ] [ <no-word-error> throw-restarts no-word-restarted ]
if ; if ;
: scan-word ( -- word/number/f ) : parse-word ( string -- word/number )
scan dup [
dup search [ ] [ dup search [ ] [
dup string>number [ ] [ no-word ] ?if dup string>number [ ] [ no-word ] ?if
] ?if ] ?if ;
] when ;
: scan-word ( -- word/number/f )
scan dup [ parse-word ] when ;
ERROR: staging-violation word ; ERROR: staging-violation word ;

View File

@ -92,9 +92,11 @@ IN: alien.data.map.tests
: vmerge-transpose ( a b c d -- ac bd ac bd ) : vmerge-transpose ( a b c d -- ac bd ac bd )
[ (vmerge) ] bi-curry@ bi* ; inline [ (vmerge) ] bi-curry@ bi* ; inline
CONSTANT: plane-count 4
: fold-rgba-planes ( r g b a -- rgba ) : fold-rgba-planes ( r g b a -- rgba )
[ vmerge-transpose vmerge-transpose ] [ vmerge-transpose vmerge-transpose ]
data-map( uchar-16 uchar-16 uchar-16 uchar-16 -- uchar-16[4] ) ; data-map( uchar-16 uchar-16 uchar-16 uchar-16 -- uchar-16[plane-count] ) ;
[ [
B{ B{

View File

@ -2,6 +2,7 @@
USING: accessors alien alien.c-types alien.data alien.parser arrays USING: accessors alien alien.c-types alien.data alien.parser arrays
byte-arrays combinators effects.parser fry generalizations kernel byte-arrays combinators effects.parser fry generalizations kernel
lexer locals macros make math math.ranges parser sequences sequences.private ; lexer locals macros make math math.ranges parser sequences sequences.private ;
FROM: alien.arrays => array-length ;
IN: alien.data.map IN: alien.data.map
ERROR: bad-data-map-input-length byte-length iter-size remainder ; ERROR: bad-data-map-input-length byte-length iter-size remainder ;
@ -36,7 +37,7 @@ M: data-map-param nth-unsafe
INSTANCE: data-map-param immutable-sequence INSTANCE: data-map-param immutable-sequence
: c-type-count ( in/out -- c-type count iter-length ) : c-type-count ( in/out -- c-type count iter-length )
dup array? [ unclip swap product >fixnum ] [ 1 ] if dup array? [ unclip swap array-length >fixnum ] [ 1 ] if
2dup swap heap-size * >fixnum ; inline 2dup swap heap-size * >fixnum ; inline
MACRO: >param ( in -- quot: ( array -- param ) ) MACRO: >param ( in -- quot: ( array -- param ) )

66
vm/callbacks.cpp Normal file
View File

@ -0,0 +1,66 @@
#include "master.hpp"
namespace factor
{
callback_heap::callback_heap(cell size, factor_vm *myvm_) :
seg(new segment(size,true)),
here(seg->start),
myvm(myvm_) {}
callback_heap::~callback_heap()
{
delete seg;
seg = NULL;
}
void factor_vm::init_callbacks(cell size)
{
callbacks = new callback_heap(size,this);
}
void callback_heap::update(callback *stub)
{
tagged<array> code_template(myvm->userenv[CALLBACK_STUB]);
cell rel_class = untag_fixnum(array_nth(code_template.untagged(),1));
cell offset = untag_fixnum(array_nth(code_template.untagged(),3));
myvm->store_address_in_code_block(rel_class,
(cell)(stub + 1) + offset,
(cell)(stub->compiled + 1));
flush_icache((cell)stub,stub->size);
}
callback *callback_heap::add(code_block *compiled)
{
tagged<array> code_template(myvm->userenv[CALLBACK_STUB]);
tagged<byte_array> insns(array_nth(code_template.untagged(),0));
cell size = array_capacity(insns.untagged());
cell bump = align8(size) + sizeof(callback);
if(here + bump > seg->end) fatal_error("Out of callback space",0);
callback *stub = (callback *)here;
stub->compiled = compiled;
memcpy(stub + 1,insns->data<void>(),size);
stub->size = align8(size);
here += bump;
update(stub);
return stub;
}
void factor_vm::primitive_callback()
{
tagged<word> w(dpop());
w.untag_check(this);
callback *stub = callbacks->add(w->code);
box_alien(stub + 1);
}
}

38
vm/callbacks.hpp Normal file
View File

@ -0,0 +1,38 @@
namespace factor
{
struct callback {
cell size;
code_block *compiled;
void *code() { return (void *)(this + 1); }
};
struct callback_heap {
segment *seg;
cell here;
factor_vm *myvm;
explicit callback_heap(cell size, factor_vm *myvm);
~callback_heap();
callback *add(code_block *compiled);
void update(callback *stub);
callback *next(callback *stub)
{
return (callback *)((cell)stub + stub->size + sizeof(callback));
}
template<typename Iterator> void iterate(Iterator &iter)
{
callback *scan = (callback *)seg->start;
callback *end = (callback *)here;
while(scan < end)
{
iter(scan);
scan = next(scan);
}
}
};
}

View File

@ -37,19 +37,16 @@ called by continuation implementation, and user code shouldn't
be calling it at all, so we leave it as it is for now. */ be calling it at all, so we leave it as it is for now. */
stack_frame *factor_vm::capture_start() stack_frame *factor_vm::capture_start()
{ {
stack_frame *frame = stack_chain->callstack_bottom - 1; stack_frame *frame = ctx->callstack_bottom - 1;
while(frame >= stack_chain->callstack_top while(frame >= ctx->callstack_top && frame_successor(frame) >= ctx->callstack_top)
&& frame_successor(frame) >= stack_chain->callstack_top)
{
frame = frame_successor(frame); frame = frame_successor(frame);
}
return frame + 1; return frame + 1;
} }
void factor_vm::primitive_callstack() void factor_vm::primitive_callstack()
{ {
stack_frame *top = capture_start(); stack_frame *top = capture_start();
stack_frame *bottom = stack_chain->callstack_bottom; stack_frame *bottom = ctx->callstack_bottom;
fixnum size = (cell)bottom - (cell)top; fixnum size = (cell)bottom - (cell)top;
if(size < 0) if(size < 0)
@ -64,7 +61,7 @@ void factor_vm::primitive_set_callstack()
{ {
callstack *stack = untag_check<callstack>(dpop()); callstack *stack = untag_check<callstack>(dpop());
set_callstack(stack_chain->callstack_bottom, set_callstack(ctx->callstack_bottom,
stack->top(), stack->top(),
untag_fixnum(stack->length), untag_fixnum(stack->length),
memcpy); memcpy);
@ -204,7 +201,7 @@ void factor_vm::primitive_set_innermost_stack_frame_quot()
/* called before entry into Factor code. */ /* called before entry into Factor code. */
void factor_vm::save_callstack_bottom(stack_frame *callstack_bottom) void factor_vm::save_callstack_bottom(stack_frame *callstack_bottom)
{ {
stack_chain->callstack_bottom = callstack_bottom; ctx->callstack_bottom = callstack_bottom;
} }
VM_ASM_API void save_callstack_bottom(stack_frame *callstack_bottom, factor_vm *myvm) VM_ASM_API void save_callstack_bottom(stack_frame *callstack_bottom, factor_vm *myvm)

View File

@ -39,7 +39,7 @@ int factor_vm::number_of_parameters(relocation_type type)
case RT_DLSYM: case RT_DLSYM:
return 2; return 2;
case RT_THIS: case RT_THIS:
case RT_STACK_CHAIN: case RT_CONTEXT:
case RT_MEGAMORPHIC_CACHE_HITS: case RT_MEGAMORPHIC_CACHE_HITS:
case RT_CARDS_OFFSET: case RT_CARDS_OFFSET:
case RT_DECKS_OFFSET: case RT_DECKS_OFFSET:
@ -174,8 +174,8 @@ cell factor_vm::compute_relocation(relocation_entry rel, cell index, code_block
} }
case RT_THIS: case RT_THIS:
return (cell)(compiled + 1); return (cell)(compiled + 1);
case RT_STACK_CHAIN: case RT_CONTEXT:
return (cell)&stack_chain; return (cell)&ctx;
case RT_UNTAGGED: case RT_UNTAGGED:
return untag_fixnum(ARG); return untag_fixnum(ARG);
case RT_MEGAMORPHIC_CACHE_HITS: case RT_MEGAMORPHIC_CACHE_HITS:
@ -441,10 +441,14 @@ code_block *factor_vm::allot_code_block(cell size, cell type)
{ {
heap_block *block = code->heap_allot(size + sizeof(code_block),type); heap_block *block = code->heap_allot(size + sizeof(code_block),type);
/* If allocation failed, do a code GC */ /* If allocation failed, do a full GC and compact the code heap.
A full GC that occurs as a result of the data heap filling up does not
trigger a compaction. This setup ensures that most GCs do not compact
the code heap, but if the code fills up, it probably means it will be
fragmented after GC anyway, so its best to compact. */
if(block == NULL) if(block == NULL)
{ {
primitive_full_gc(); primitive_compact_gc();
block = code->heap_allot(size + sizeof(code_block),type); block = code->heap_allot(size + sizeof(code_block),type);
/* Insufficient room even after code GC, give up */ /* Insufficient room even after code GC, give up */

View File

@ -20,8 +20,8 @@ enum relocation_type {
RT_THIS, RT_THIS,
/* immediate literal */ /* immediate literal */
RT_IMMEDIATE, RT_IMMEDIATE,
/* address of stack_chain var */ /* address of ctx var */
RT_STACK_CHAIN, RT_CONTEXT,
/* untagged fixnum literal */ /* untagged fixnum literal */
RT_UNTAGGED, RT_UNTAGGED,
/* address of megamorphic_cache_hits var */ /* address of megamorphic_cache_hits var */

View File

@ -207,15 +207,29 @@ void factor_vm::forward_object_xts()
} }
void factor_vm::forward_context_xts() void factor_vm::forward_context_xts()
{
context *ctx = stack_chain;
while(ctx)
{ {
callframe_forwarder forwarder(this); callframe_forwarder forwarder(this);
iterate_callstack(ctx,forwarder); iterate_active_frames(forwarder);
ctx = ctx->next;
} }
struct callback_forwarder {
code_heap *code;
callback_heap *callbacks;
callback_forwarder(code_heap *code_, callback_heap *callbacks_) :
code(code_), callbacks(callbacks_) {}
void operator()(callback *stub)
{
stub->compiled = code->forward_code_block(stub->compiled);
callbacks->update(stub);
}
};
void factor_vm::forward_callback_xts()
{
callback_forwarder forwarder(code,callbacks);
callbacks->iterate(forwarder);
} }
/* Move all free space to the end of the code heap. Live blocks must be marked /* Move all free space to the end of the code heap. Live blocks must be marked
@ -225,7 +239,11 @@ void factor_vm::compact_code_heap(bool trace_contexts_p)
{ {
code->compact_heap(); code->compact_heap();
forward_object_xts(); forward_object_xts();
if(trace_contexts_p) forward_context_xts(); if(trace_contexts_p)
{
forward_context_xts();
forward_callback_xts();
}
} }
struct stack_trace_stripper { struct stack_trace_stripper {

View File

@ -132,7 +132,7 @@ template<typename TargetGeneration, typename Policy> struct collector {
void trace_contexts() void trace_contexts()
{ {
context *ctx = myvm->stack_chain; context *ctx = myvm->ctx;
while(ctx) while(ctx)
{ {

View File

@ -25,10 +25,10 @@ void factor_vm::fix_stacks()
be stored in registers, so callbacks must save and restore the correct values */ be stored in registers, so callbacks must save and restore the correct values */
void factor_vm::save_stacks() void factor_vm::save_stacks()
{ {
if(stack_chain) if(ctx)
{ {
stack_chain->datastack = ds; ctx->datastack = ds;
stack_chain->retainstack = rs; ctx->retainstack = rs;
} }
} }
@ -58,12 +58,12 @@ void factor_vm::dealloc_context(context *old_context)
} }
/* called on entry into a compiled callback */ /* called on entry into a compiled callback */
void factor_vm::nest_stacks() void factor_vm::nest_stacks(stack_frame *magic_frame)
{ {
context *new_context = alloc_context(); context *new_ctx = alloc_context();
new_context->callstack_bottom = (stack_frame *)-1; new_ctx->callstack_bottom = (stack_frame *)-1;
new_context->callstack_top = (stack_frame *)-1; new_ctx->callstack_top = (stack_frame *)-1;
/* note that these register values are not necessarily valid stack /* note that these register values are not necessarily valid stack
pointers. they are merely saved non-volatile registers, and are pointers. they are merely saved non-volatile registers, and are
@ -75,37 +75,39 @@ void factor_vm::nest_stacks()
- Factor callback returns - Factor callback returns
- C function restores registers - C function restores registers
- C function returns to Factor code */ - C function returns to Factor code */
new_context->datastack_save = ds; new_ctx->datastack_save = ds;
new_context->retainstack_save = rs; new_ctx->retainstack_save = rs;
new_ctx->magic_frame = magic_frame;
/* save per-callback userenv */ /* save per-callback userenv */
new_context->current_callback_save = userenv[CURRENT_CALLBACK_ENV]; new_ctx->current_callback_save = userenv[CURRENT_CALLBACK_ENV];
new_context->catchstack_save = userenv[CATCHSTACK_ENV]; new_ctx->catchstack_save = userenv[CATCHSTACK_ENV];
new_context->next = stack_chain; new_ctx->next = ctx;
stack_chain = new_context; ctx = new_ctx;
reset_datastack(); reset_datastack();
reset_retainstack(); reset_retainstack();
} }
void nest_stacks(factor_vm *myvm) void nest_stacks(stack_frame *magic_frame, factor_vm *myvm)
{ {
return myvm->nest_stacks(); return myvm->nest_stacks(magic_frame);
} }
/* called when leaving a compiled callback */ /* called when leaving a compiled callback */
void factor_vm::unnest_stacks() void factor_vm::unnest_stacks()
{ {
ds = stack_chain->datastack_save; ds = ctx->datastack_save;
rs = stack_chain->retainstack_save; rs = ctx->retainstack_save;
/* restore per-callback userenv */ /* restore per-callback userenv */
userenv[CURRENT_CALLBACK_ENV] = stack_chain->current_callback_save; userenv[CURRENT_CALLBACK_ENV] = ctx->current_callback_save;
userenv[CATCHSTACK_ENV] = stack_chain->catchstack_save; userenv[CATCHSTACK_ENV] = ctx->catchstack_save;
context *old_ctx = stack_chain; context *old_ctx = ctx;
stack_chain = old_ctx->next; ctx = old_ctx->next;
dealloc_context(old_ctx); dealloc_context(old_ctx);
} }
@ -119,7 +121,7 @@ void factor_vm::init_stacks(cell ds_size_, cell rs_size_)
{ {
ds_size = ds_size_; ds_size = ds_size_;
rs_size = rs_size_; rs_size = rs_size_;
stack_chain = NULL; ctx = NULL;
unused_contexts = NULL; unused_contexts = NULL;
} }

View File

@ -23,6 +23,18 @@ struct context {
/* saved contents of rs register on entry to callback */ /* saved contents of rs register on entry to callback */
cell retainstack_save; cell retainstack_save;
/* callback-bottom stack frame, or NULL for top-level context.
When nest_stacks() is called, callstack layout with callbacks
is as follows:
[ C function ]
[ callback stub in code heap ] <-- this is the magic frame
[ native frame: c_to_factor() ]
[ callback quotation frame ] <-- first call frame in call stack
magic frame is retained so that it's XT can be traced and forwarded. */
stack_frame *magic_frame;
/* memory region holding current datastack */ /* memory region holding current datastack */
segment *datastack_region; segment *datastack_region;
@ -36,15 +48,15 @@ struct context {
context *next; context *next;
}; };
#define ds_bot (stack_chain->datastack_region->start) #define ds_bot (ctx->datastack_region->start)
#define ds_top (stack_chain->datastack_region->end) #define ds_top (ctx->datastack_region->end)
#define rs_bot (stack_chain->retainstack_region->start) #define rs_bot (ctx->retainstack_region->start)
#define rs_top (stack_chain->retainstack_region->end) #define rs_top (ctx->retainstack_region->end)
DEFPUSHPOP(d,ds) DEFPUSHPOP(d,ds)
DEFPUSHPOP(r,rs) DEFPUSHPOP(r,rs)
VM_C_API void nest_stacks(factor_vm *vm); VM_C_API void nest_stacks(stack_frame *magic_frame, factor_vm *vm);
VM_C_API void unnest_stacks(factor_vm *vm); VM_C_API void unnest_stacks(factor_vm *vm);
} }

View File

@ -190,7 +190,7 @@ void factor_vm::print_callstack()
{ {
print_string("==== CALL STACK:\n"); print_string("==== CALL STACK:\n");
stack_frame_printer printer(this); stack_frame_printer printer(this);
iterate_callstack(stack_chain,printer); iterate_callstack(ctx,printer);
} }
void factor_vm::dump_cell(cell x) void factor_vm::dump_cell(cell x)

View File

@ -49,12 +49,9 @@ void factor_vm::throw_error(cell error, stack_frame *callstack_top)
actual stack pointer at the time, since the saved pointer is actual stack pointer at the time, since the saved pointer is
not necessarily up to date at that point. */ not necessarily up to date at that point. */
if(callstack_top) if(callstack_top)
{ callstack_top = fix_callstack_top(callstack_top,ctx->callstack_bottom);
callstack_top = fix_callstack_top(callstack_top,
stack_chain->callstack_bottom);
}
else else
callstack_top = stack_chain->callstack_top; callstack_top = ctx->callstack_top;
throw_impl(userenv[BREAK_ENV],callstack_top,this); throw_impl(userenv[BREAK_ENV],callstack_top,this);
} }
@ -130,7 +127,7 @@ void factor_vm::fp_trap_error(unsigned int fpu_status, stack_frame *signal_calls
void factor_vm::primitive_call_clear() void factor_vm::primitive_call_clear()
{ {
throw_impl(dpop(),stack_chain->callstack_bottom,this); throw_impl(dpop(),ctx->callstack_bottom,this);
} }
/* For testing purposes */ /* For testing purposes */

View File

@ -39,6 +39,7 @@ void factor_vm::default_parameters(vm_parameters *p)
p->secure_gc = false; p->secure_gc = false;
p->fep = false; p->fep = false;
p->signals = true;
#ifdef WINDOWS #ifdef WINDOWS
p->console = false; p->console = false;
@ -49,6 +50,8 @@ void factor_vm::default_parameters(vm_parameters *p)
p->console = false; p->console = false;
#endif #endif
p->callback_size = 256;
} }
bool factor_vm::factor_arg(const vm_char* str, const vm_char* arg, cell* value) bool factor_vm::factor_arg(const vm_char* str, const vm_char* arg, cell* value)
@ -72,17 +75,21 @@ void factor_vm::init_parameters_from_args(vm_parameters *p, int argc, vm_char **
for(i = 1; i < argc; i++) for(i = 1; i < argc; i++)
{ {
if(factor_arg(argv[i],STRING_LITERAL("-datastack=%d"),&p->ds_size)); vm_char *arg = argv[i];
else if(factor_arg(argv[i],STRING_LITERAL("-retainstack=%d"),&p->rs_size)); if(STRCMP(arg,STRING_LITERAL("--")) == 0) break;
else if(factor_arg(argv[i],STRING_LITERAL("-young=%d"),&p->young_size)); else if(factor_arg(arg,STRING_LITERAL("-datastack=%d"),&p->ds_size));
else if(factor_arg(argv[i],STRING_LITERAL("-aging=%d"),&p->aging_size)); else if(factor_arg(arg,STRING_LITERAL("-retainstack=%d"),&p->rs_size));
else if(factor_arg(argv[i],STRING_LITERAL("-tenured=%d"),&p->tenured_size)); else if(factor_arg(arg,STRING_LITERAL("-young=%d"),&p->young_size));
else if(factor_arg(argv[i],STRING_LITERAL("-codeheap=%d"),&p->code_size)); else if(factor_arg(arg,STRING_LITERAL("-aging=%d"),&p->aging_size));
else if(factor_arg(argv[i],STRING_LITERAL("-pic=%d"),&p->max_pic_size)); else if(factor_arg(arg,STRING_LITERAL("-tenured=%d"),&p->tenured_size));
else if(STRCMP(argv[i],STRING_LITERAL("-securegc")) == 0) p->secure_gc = true; else if(factor_arg(arg,STRING_LITERAL("-codeheap=%d"),&p->code_size));
else if(STRCMP(argv[i],STRING_LITERAL("-fep")) == 0) p->fep = true; else if(factor_arg(arg,STRING_LITERAL("-pic=%d"),&p->max_pic_size));
else if(STRNCMP(argv[i],STRING_LITERAL("-i="),3) == 0) p->image_path = argv[i] + 3; else if(factor_arg(arg,STRING_LITERAL("-callbacks=%d"),&p->callback_size));
else if(STRCMP(argv[i],STRING_LITERAL("-console")) == 0) p->console = true; else if(STRCMP(arg,STRING_LITERAL("-securegc")) == 0) p->secure_gc = true;
else if(STRCMP(arg,STRING_LITERAL("-fep")) == 0) p->fep = true;
else if(STRCMP(arg,STRING_LITERAL("-nosignals")) == 0) p->signals = false;
else if(STRNCMP(arg,STRING_LITERAL("-i="),3) == 0) p->image_path = arg + 3;
else if(STRCMP(arg,STRING_LITERAL("-console")) == 0) p->console = true;
} }
} }
@ -104,6 +111,7 @@ void factor_vm::init_factor(vm_parameters *p)
/* Kilobytes */ /* Kilobytes */
p->ds_size = align_page(p->ds_size << 10); p->ds_size = align_page(p->ds_size << 10);
p->rs_size = align_page(p->rs_size << 10); p->rs_size = align_page(p->rs_size << 10);
p->callback_size = align_page(p->callback_size << 10);
/* Megabytes */ /* Megabytes */
p->young_size <<= 20; p->young_size <<= 20;
@ -128,9 +136,11 @@ void factor_vm::init_factor(vm_parameters *p)
srand(current_micros()); srand(current_micros());
init_ffi(); init_ffi();
init_stacks(p->ds_size,p->rs_size); init_stacks(p->ds_size,p->rs_size);
init_callbacks(p->callback_size);
load_image(p); load_image(p);
init_c_io(); init_c_io();
init_inline_caching(p->max_pic_size); init_inline_caching(p->max_pic_size);
if(p->signals)
init_signals(); init_signals();
if(p->console) if(p->console)
@ -170,7 +180,7 @@ void factor_vm::start_factor(vm_parameters *p)
{ {
if(p->fep) factorbug(); if(p->fep) factorbug();
nest_stacks(); nest_stacks(NULL);
c_to_factor_toplevel(userenv[BOOT_ENV]); c_to_factor_toplevel(userenv[BOOT_ENV]);
unnest_stacks(); unnest_stacks();
} }

View File

@ -25,15 +25,9 @@ struct stack_frame_marker {
/* Mark code blocks executing in currently active stack frames. */ /* Mark code blocks executing in currently active stack frames. */
void full_collector::mark_active_blocks() void full_collector::mark_active_blocks()
{
context *ctx = this->myvm->stack_chain;
while(ctx)
{ {
stack_frame_marker marker(this); stack_frame_marker marker(this);
myvm->iterate_callstack(ctx,marker); myvm->iterate_active_frames(marker);
ctx = ctx->next;
}
} }
void full_collector::mark_object_code_block(object *obj) void full_collector::mark_object_code_block(object *obj)
@ -66,6 +60,23 @@ void full_collector::mark_object_code_block(object *obj)
} }
} }
struct callback_tracer {
full_collector *collector;
callback_tracer(full_collector *collector_) : collector(collector_) {}
void operator()(callback *stub)
{
collector->mark_code_block(stub->compiled);
}
};
void full_collector::trace_callbacks()
{
callback_tracer tracer(this);
myvm->callbacks->iterate(tracer);
}
/* Trace all literals referenced from a code block. Only for aging and nursery collections */ /* Trace all literals referenced from a code block. Only for aging and nursery collections */
void full_collector::trace_literal_references(code_block *compiled) void full_collector::trace_literal_references(code_block *compiled)
{ {
@ -95,10 +106,10 @@ void full_collector::cheneys_algorithm()
/* After growing the heap, we have to perform a full relocation to update /* After growing the heap, we have to perform a full relocation to update
references to card and deck arrays. */ references to card and deck arrays. */
struct after_growing_heap_updater { struct big_code_heap_updater {
factor_vm *myvm; factor_vm *myvm;
after_growing_heap_updater(factor_vm *myvm_) : myvm(myvm_) {} big_code_heap_updater(factor_vm *myvm_) : myvm(myvm_) {}
void operator()(heap_block *block) void operator()(heap_block *block)
{ {
@ -108,10 +119,10 @@ struct after_growing_heap_updater {
/* After a full GC that did not grow the heap, we have to update references /* After a full GC that did not grow the heap, we have to update references
to literals and other words. */ to literals and other words. */
struct after_full_updater { struct small_code_heap_updater {
factor_vm *myvm; factor_vm *myvm;
after_full_updater(factor_vm *myvm_) : myvm(myvm_) {} small_code_heap_updater(factor_vm *myvm_) : myvm(myvm_) {}
void operator()(heap_block *block) void operator()(heap_block *block)
{ {
@ -128,6 +139,7 @@ void factor_vm::collect_full_impl(bool trace_contexts_p)
{ {
collector.trace_contexts(); collector.trace_contexts();
collector.mark_active_blocks(); collector.mark_active_blocks();
collector.trace_callbacks();
} }
collector.cheneys_algorithm(); collector.cheneys_algorithm();
@ -139,6 +151,13 @@ void factor_vm::collect_full_impl(bool trace_contexts_p)
/* In both cases, compact code heap before updating code blocks so that /* In both cases, compact code heap before updating code blocks so that
XTs are correct after */ XTs are correct after */
void factor_vm::big_code_heap_update()
{
big_code_heap_updater updater(this);
code->free_unmarked(updater);
code->clear_remembered_set();
}
void factor_vm::collect_growing_heap(cell requested_bytes, void factor_vm::collect_growing_heap(cell requested_bytes,
bool trace_contexts_p, bool trace_contexts_p,
bool compact_code_heap_p) bool compact_code_heap_p)
@ -151,7 +170,12 @@ void factor_vm::collect_growing_heap(cell requested_bytes,
if(compact_code_heap_p) compact_code_heap(trace_contexts_p); if(compact_code_heap_p) compact_code_heap(trace_contexts_p);
after_growing_heap_updater updater(this); big_code_heap_update();
}
void factor_vm::small_code_heap_update()
{
small_code_heap_updater updater(this);
code->free_unmarked(updater); code->free_unmarked(updater);
code->clear_remembered_set(); code->clear_remembered_set();
} }
@ -163,11 +187,13 @@ void factor_vm::collect_full(bool trace_contexts_p, bool compact_code_heap_p)
reset_generation(data->tenured); reset_generation(data->tenured);
collect_full_impl(trace_contexts_p); collect_full_impl(trace_contexts_p);
if(compact_code_heap_p) compact_code_heap(trace_contexts_p); if(compact_code_heap_p)
{
after_full_updater updater(this); compact_code_heap(trace_contexts_p);
code->free_unmarked(updater); big_code_heap_update();
code->clear_remembered_set(); }
else
small_code_heap_update();
} }
} }

View File

@ -19,6 +19,7 @@ struct full_collector : copying_collector<tenured_space,full_policy> {
full_collector(factor_vm *myvm_); full_collector(factor_vm *myvm_);
void mark_active_blocks(); void mark_active_blocks();
void mark_object_code_block(object *object); void mark_object_code_block(object *object);
void trace_callbacks();
void trace_literal_references(code_block *compiled); void trace_literal_references(code_block *compiled);
void mark_code_block(code_block *compiled); void mark_code_block(code_block *compiled);
void cheneys_algorithm(); void cheneys_algorithm();

View File

@ -96,17 +96,17 @@ void factor_vm::gc(gc_op op,
current_gc = NULL; current_gc = NULL;
} }
void factor_vm::primitive_full_gc() void factor_vm::primitive_minor_gc()
{ {
gc(collect_full_op, gc(collect_nursery_op,
0, /* requested size */ 0, /* requested size */
true, /* trace contexts? */ true, /* trace contexts? */
false /* compact code heap? */); false /* compact code heap? */);
} }
void factor_vm::primitive_minor_gc() void factor_vm::primitive_full_gc()
{ {
gc(collect_nursery_op, gc(collect_full_op,
0, /* requested size */ 0, /* requested size */
true, /* trace contexts? */ true, /* trace contexts? */
false /* compact code heap? */); false /* compact code heap? */);

View File

@ -114,7 +114,7 @@ bool factor_vm::save_image(const vm_char *filename)
void factor_vm::primitive_save_image() void factor_vm::primitive_save_image()
{ {
/* do a full GC to push everything into tenured space */ /* do a full GC to push everything into tenured space */
primitive_full_gc(); primitive_compact_gc();
gc_root<byte_array> path(dpop(),this); gc_root<byte_array> path(dpop(),this);
path.untag_check(this); path.untag_check(this);

View File

@ -37,7 +37,9 @@ struct vm_parameters {
bool secure_gc; bool secure_gc;
bool fep; bool fep;
bool console; bool console;
bool signals;
cell max_pic_size; cell max_pic_size;
cell callback_size;
}; };
} }

View File

@ -82,6 +82,7 @@ namespace factor
#include "image.hpp" #include "image.hpp"
#include "alien.hpp" #include "alien.hpp"
#include "code_heap.hpp" #include "code_heap.hpp"
#include "callbacks.hpp"
#include "vm.hpp" #include "vm.hpp"
#include "tagged.hpp" #include "tagged.hpp"
#include "local_roots.hpp" #include "local_roots.hpp"

View File

@ -52,7 +52,9 @@ PRIMITIVE_FORWARD(word_xt)
PRIMITIVE_FORWARD(getenv) PRIMITIVE_FORWARD(getenv)
PRIMITIVE_FORWARD(setenv) PRIMITIVE_FORWARD(setenv)
PRIMITIVE_FORWARD(existsp) PRIMITIVE_FORWARD(existsp)
PRIMITIVE_FORWARD(minor_gc)
PRIMITIVE_FORWARD(full_gc) PRIMITIVE_FORWARD(full_gc)
PRIMITIVE_FORWARD(compact_gc)
PRIMITIVE_FORWARD(gc_stats) PRIMITIVE_FORWARD(gc_stats)
PRIMITIVE_FORWARD(save_image) PRIMITIVE_FORWARD(save_image)
PRIMITIVE_FORWARD(save_image_and_exit) PRIMITIVE_FORWARD(save_image_and_exit)
@ -127,6 +129,7 @@ PRIMITIVE_FORWARD(optimized_p)
PRIMITIVE_FORWARD(quot_compiled_p) PRIMITIVE_FORWARD(quot_compiled_p)
PRIMITIVE_FORWARD(vm_ptr) PRIMITIVE_FORWARD(vm_ptr)
PRIMITIVE_FORWARD(strip_stack_traces) PRIMITIVE_FORWARD(strip_stack_traces)
PRIMITIVE_FORWARD(callback)
const primitive_type primitives[] = { const primitive_type primitives[] = {
primitive_bignum_to_fixnum, primitive_bignum_to_fixnum,
@ -187,7 +190,9 @@ const primitive_type primitives[] = {
primitive_getenv, primitive_getenv,
primitive_setenv, primitive_setenv,
primitive_existsp, primitive_existsp,
primitive_minor_gc,
primitive_full_gc, primitive_full_gc,
primitive_compact_gc,
primitive_gc_stats, primitive_gc_stats,
primitive_save_image, primitive_save_image,
primitive_save_image_and_exit, primitive_save_image_and_exit,
@ -290,6 +295,7 @@ const primitive_type primitives[] = {
primitive_quot_compiled_p, primitive_quot_compiled_p,
primitive_vm_ptr, primitive_vm_ptr,
primitive_strip_stack_traces, primitive_strip_stack_traces,
primitive_callback,
}; };
} }

View File

@ -362,7 +362,7 @@ fixnum factor_vm::quot_code_offset_to_scan(cell quot_, cell offset)
cell factor_vm::lazy_jit_compile_impl(cell quot_, stack_frame *stack) cell factor_vm::lazy_jit_compile_impl(cell quot_, stack_frame *stack)
{ {
gc_root<quotation> quot(quot_,this); gc_root<quotation> quot(quot_,this);
stack_chain->callstack_top = stack; ctx->callstack_top = stack;
jit_compile(quot.value(),true); jit_compile(quot.value(),true);
return quot.value(); return quot.value();
} }

View File

@ -59,6 +59,9 @@ enum special_object {
JIT_EXECUTE_CALL, JIT_EXECUTE_CALL,
JIT_DECLARE_WORD, JIT_DECLARE_WORD,
/* Callback stub generation in callbacks.c */
CALLBACK_STUB = 45,
/* Polymorphic inline cache generation in inline_cache.c */ /* Polymorphic inline cache generation in inline_cache.c */
PIC_LOAD = 47, PIC_LOAD = 47,
PIC_TAG, PIC_TAG,

View File

@ -8,7 +8,7 @@ struct factor_vm
// First five fields accessed directly by assembler. See vm.factor // First five fields accessed directly by assembler. See vm.factor
/* Current stacks */ /* Current stacks */
context *stack_chain; context *ctx;
/* New objects are allocated here */ /* New objects are allocated here */
zone nursery; zone nursery;
@ -55,6 +55,9 @@ struct factor_vm
/* Code heap */ /* Code heap */
code_heap *code; code_heap *code;
/* Pinned callback stubs */
callback_heap *callbacks;
/* Only set if we're performing a GC */ /* Only set if we're performing a GC */
gc_state *current_gc; gc_state *current_gc;
@ -96,7 +99,7 @@ struct factor_vm
void save_stacks(); void save_stacks();
context *alloc_context(); context *alloc_context();
void dealloc_context(context *old_context); void dealloc_context(context *old_context);
void nest_stacks(); void nest_stacks(stack_frame *magic_frame);
void unnest_stacks(); void unnest_stacks();
void init_stacks(cell ds_size_, cell rs_size_); void init_stacks(cell ds_size_, cell rs_size_);
bool stack_to_array(cell bottom, cell top); bool stack_to_array(cell bottom, cell top);
@ -107,6 +110,18 @@ struct factor_vm
void primitive_set_retainstack(); void primitive_set_retainstack();
void primitive_check_datastack(); void primitive_check_datastack();
template<typename Iterator> void iterate_active_frames(Iterator &iter)
{
context *ctx = this->ctx;
while(ctx)
{
iterate_callstack(ctx,iter);
if(ctx->magic_frame) iter(ctx->magic_frame);
ctx = ctx->next;
}
}
// run // run
void primitive_getenv(); void primitive_getenv();
void primitive_setenv(); void primitive_setenv();
@ -238,13 +253,15 @@ struct factor_vm
void collect_nursery(); void collect_nursery();
void collect_aging(); void collect_aging();
void collect_to_tenured(); void collect_to_tenured();
void big_code_heap_update();
void small_code_heap_update();
void collect_full_impl(bool trace_contexts_p); void collect_full_impl(bool trace_contexts_p);
void collect_growing_heap(cell requested_bytes, bool trace_contexts_p, bool compact_code_heap_p); void collect_growing_heap(cell requested_bytes, bool trace_contexts_p, bool compact_code_heap_p);
void collect_full(bool trace_contexts_p, bool compact_code_heap_p); void collect_full(bool trace_contexts_p, bool compact_code_heap_p);
void record_gc_stats(generation_statistics *stats); void record_gc_stats(generation_statistics *stats);
void gc(gc_op op, cell requested_bytes, bool trace_contexts_p, bool compact_code_heap_p); void gc(gc_op op, cell requested_bytes, bool trace_contexts_p, bool compact_code_heap_p);
void primitive_full_gc();
void primitive_minor_gc(); void primitive_minor_gc();
void primitive_full_gc();
void primitive_compact_gc(); void primitive_compact_gc();
void primitive_gc_stats(); void primitive_gc_stats();
void clear_gc_stats(); void clear_gc_stats();
@ -502,6 +519,7 @@ struct factor_vm
void primitive_code_room(); void primitive_code_room();
void forward_object_xts(); void forward_object_xts();
void forward_context_xts(); void forward_context_xts();
void forward_callback_xts();
void compact_code_heap(bool trace_contexts_p); void compact_code_heap(bool trace_contexts_p);
void primitive_strip_stack_traces(); void primitive_strip_stack_traces();
@ -518,6 +536,10 @@ struct factor_vm
} }
} }
//callbacks
void init_callbacks(cell size);
void primitive_callback();
//image //image
void init_objects(image_header *h); void init_objects(image_header *h);
void load_data_heap(FILE *file, image_header *h, vm_parameters *p); void load_data_heap(FILE *file, image_header *h, vm_parameters *p);