Merge git://factorcode.org/git/factor

release
Doug Coleman 2007-10-29 08:58:23 -05:00
commit 5ca4f88188
51 changed files with 425 additions and 377 deletions

View File

@ -38,7 +38,8 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
vm/types.o \ vm/types.o \
vm/quotations.o \ vm/quotations.o \
vm/utilities.o \ vm/utilities.o \
vm/errors.o vm/errors.o \
vm/profiler.o
EXE_OBJS = $(PLAF_EXE_OBJS) EXE_OBJS = $(PLAF_EXE_OBJS)

View File

@ -383,8 +383,11 @@ TUPLE: callback-context ;
: generate-callback ( node -- ) : generate-callback ( node -- )
dup alien-callback-xt dup rot [ dup alien-callback-xt dup rot [
dup alien-stack-frame [
init-templates init-templates
generate-profiler-prologue
%save-xt
%prologue-later
dup alien-stack-frame [
dup registers>objects dup registers>objects
dup wrap-callback-quot %alien-callback dup wrap-callback-quot %alien-callback
%callback-return %callback-return

View File

@ -98,9 +98,9 @@ M: assoc assoc-clone-like ( assoc exemplar -- newassoc )
2dup subassoc? >r swap subassoc? r> and ; 2dup subassoc? >r swap subassoc? r> and ;
: assoc-hashcode ( n assoc -- code ) : assoc-hashcode ( n assoc -- code )
swap [ [
tuck swap hashcode* >r swap hashcode* 2/ r> bitxor >r over r> hashcode* 2/ >r dupd hashcode* r> bitxor
] curry { } assoc>map hashcode ; ] { } assoc>map hashcode* ;
: intersect ( assoc1 assoc2 -- intersection ) : intersect ( assoc1 assoc2 -- intersection )
swap [ nip key? ] curry assoc-subset ; swap [ nip key? ] curry assoc-subset ;

View File

@ -1,16 +1,17 @@
USING: compiler vocabs.loader system sequences namespaces USING: compiler cpu.architecture vocabs.loader system sequences
parser kernel kernel.private classes classes.private namespaces parser kernel kernel.private classes classes.private
arrays hashtables vectors tuples sbufs inference.dataflow arrays hashtables vectors tuples sbufs inference.dataflow
hashtables.private sequences.private math tuples.private hashtables.private sequences.private math tuples.private
growable namespaces.private alien.remote-control assocs growable namespaces.private alien.remote-control assocs words
words generator command-line vocabs io prettyprint libc ; generator command-line vocabs io prettyprint libc ;
"cpu." cpu append require "cpu." cpu append require
global [ { "compiler" } add-use ] bind global [ { "compiler" } add-use ] bind
"-no-stack-traces" cli-args member? [ "-no-stack-traces" cli-args member? [
f compiled-stack-traces set-global f compiled-stack-traces? set-global
0 set-profiler-prologues
] when ] when
! Compile a set of words ahead of our general ! Compile a set of words ahead of our general

View File

@ -210,8 +210,9 @@ M: f '
dup word-def ' , dup word-def ' ,
dup word-props ' , dup word-props ' ,
f ' , f ' ,
0 , 0 , ! count
0 , 0 , ! xt
0 , ! code
] { } make ] { } make
\ word type-number object tag-number \ word type-number object tag-number
[ emit-seq ] emit-object [ emit-seq ] emit-object
@ -307,7 +308,8 @@ M: quotation '
quotation type-number object tag-number [ quotation type-number object tag-number [
emit ! array emit ! array
f ' emit ! compiled? f ' emit ! compiled?
0 emit ! XT 0 emit ! xt
0 emit ! code
] emit-object ] emit-object
] cache ; ] cache ;

View File

@ -4,7 +4,7 @@ math.constants math.private sequences strings tools.test words
continuations sequences.private hashtables.private byte-arrays continuations sequences.private hashtables.private byte-arrays
strings.private system random layouts vectors.private strings.private system random layouts vectors.private
sbufs.private strings.private slots.private alien alien.c-types sbufs.private strings.private slots.private alien alien.c-types
alien.syntax namespaces libc ; alien.syntax namespaces libc combinators.private ;
! Make sure that intrinsic ops compile to correct code. ! Make sure that intrinsic ops compile to correct code.
[ ] [ 1 [ drop ] compile-1 ] unit-test [ ] [ 1 [ drop ] compile-1 ] unit-test
@ -433,3 +433,13 @@ cell 8 = [
[ [
B{ 0 0 0 0 } [ { c-ptr } declare <void*> ] compile-1 B{ 0 0 0 0 } [ { c-ptr } declare <void*> ] compile-1
] unit-test-fails ] unit-test-fails
[
4 5
] [
3 [
[
{ [ 4444 ] [ 444 ] [ 44 ] [ 4 ] } dispatch
] keep 2 fixnum+fast
] compile-1
] unit-test

View File

@ -5,6 +5,9 @@ namespaces sequences layouts system hashtables classes alien
byte-arrays bit-arrays float-arrays combinators words ; byte-arrays bit-arrays float-arrays combinators words ;
IN: cpu.architecture IN: cpu.architecture
: set-profiler-prologues ( n -- )
39 setenv ;
SYMBOL: compiler-backend SYMBOL: compiler-backend
! A pseudo-register class for parameters spilled on the stack ! A pseudo-register class for parameters spilled on the stack

View File

@ -1,9 +1,9 @@
! Copyright (C) 2007 Slava Pestov. ! Copyright (C) 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types arrays cpu.arm.assembler compiler USING: alien alien.c-types arrays cpu.arm.assembler compiler
kernel kernel.private math namespaces words kernel kernel.private math namespaces words words.private
words.private generator.registers generator.fixup generator generator.registers generator.fixup generator cpu.architecture
cpu.architecture system layouts ; system layouts ;
IN: cpu.arm.architecture IN: cpu.arm.architecture
TUPLE: arm-backend ; TUPLE: arm-backend ;
@ -67,7 +67,7 @@ M: arm-backend stack-frame ( n -- i )
factor-area-size + 8 align ; factor-area-size + 8 align ;
M: arm-backend %save-xt ( -- ) M: arm-backend %save-xt ( -- )
R12 PC 8 SUB ; R12 PC 9 cells SUB ;
M: arm-backend %prologue ( n -- ) M: arm-backend %prologue ( n -- )
SP SP pick SUB SP SP pick SUB
@ -86,18 +86,13 @@ M: arm-backend %epilogue ( n -- )
: %alien-global ( symbol dll reg -- ) : %alien-global ( symbol dll reg -- )
[ compile-dlsym ] keep dup 0 <+> LDR ; [ compile-dlsym ] keep dup 0 <+> LDR ;
M: arm-backend %profiler-prologue ( word -- ) M: arm-backend %profiler-prologue ( -- )
#! We can clobber R0 here since it is undefined at the start #! We can clobber R0 here since it is undefined at the start
#! of a word. #! of a word.
"end" define-label
"profiling" f R12 %alien-global
R12 0 CMP
"end" get EQ B
R12 load-indirect R12 load-indirect
R0 R12 profile-count-offset <+> LDR R0 R12 profile-count-offset <+> LDR
R0 R0 1 v>operand ADD R0 R0 1 v>operand ADD
R0 R12 profile-count-offset <+> STR R0 R12 profile-count-offset <+> STR ;
"end" resolve-label ;
M: arm-backend %call-label ( label -- ) BL ; M: arm-backend %call-label ( label -- ) BL ;

View File

@ -52,3 +52,5 @@ T{ arm-backend } compiler-backend set-global
"arm-variant" get "arm5" = [ "arm-variant" get "arm5" = [
t have-BLX? set-global t have-BLX? set-global
] when ] when
7 cells set-profiler-prologue

View File

@ -55,10 +55,10 @@ IN: cpu.arm.intrinsics
: %write-barrier ( -- ) : %write-barrier ( -- )
"val" get operand-immediate? "obj" get fresh-object? or [ "val" get operand-immediate? "obj" get fresh-object? or [
"cards_offset" f R12 %alien-global "cards_offset" f R12 %alien-global
"scratch" operand R12 "scratch" operand card-bits <LSR> ADD "scratch" operand R12 "obj" operand card-bits <LSR> ADD
"val" operand "scratch" operand 0 LDRB "val" operand "scratch" operand 0 <+> LDRB
"val" operand dup card-mark ORR "val" operand dup card-mark ORR
"val" operand "scratch" operand 0 STRB "val" operand "scratch" operand 0 <+> STRB
] unless ; ] unless ;
\ set-slot { \ set-slot {
@ -315,12 +315,12 @@ IN: cpu.arm.intrinsics
! Store class ! Store class
"class" operand 2 %set-slot "class" operand 2 %set-slot
! Zero out the rest of the tuple ! Zero out the rest of the tuple
R12 f v>operand MOV "initial" operand f v>operand MOV
"n" get 1- [ 1+ R12 %fill-array ] each "n" get 1- [ 1+ "initial" operand %fill-array ] each
"out" get object %store-tagged "out" get tuple %store-tagged
] H{ ] H{
{ +input+ { { f "class" } { [ inline-array? ] "n" } } } { +input+ { { f "class" } { [ inline-array? ] "n" } } }
{ +scratch+ { { f "out" } } } { +scratch+ { { f "out" } { f "initial" } } }
{ +output+ { "out" } } { +output+ { "out" } }
} define-intrinsic } define-intrinsic

View File

@ -76,11 +76,8 @@ M: ppc-backend load-indirect ( obj reg -- )
[ 0 swap LOAD32 rc-absolute-ppc-2/2 rel-literal ] keep [ 0 swap LOAD32 rc-absolute-ppc-2/2 rel-literal ] keep
dup 0 LWZ ; dup 0 LWZ ;
: %load-xt ( word reg -- )
0 swap LOAD32 rc-absolute-ppc-2/2 rel-word ;
M: ppc-backend %save-xt ( -- ) M: ppc-backend %save-xt ( -- )
compiling-label get 11 %load-xt ; 0 11 LOAD32 rc-absolute-ppc-2/2 rel-current-word ;
M: ppc-backend %prologue ( n -- ) M: ppc-backend %prologue ( n -- )
0 MFLR 0 MFLR
@ -103,16 +100,10 @@ M: ppc-backend %epilogue ( n -- )
0 swap LOAD32 rc-absolute-ppc-2/2 rel-dlsym ; 0 swap LOAD32 rc-absolute-ppc-2/2 rel-dlsym ;
M: ppc-backend %profiler-prologue ( word -- ) M: ppc-backend %profiler-prologue ( word -- )
"end" define-label
"profiling" f 3 %load-dlsym
3 3 0 LWZ
0 3 0 CMPI
"end" get BEQ
3 load-indirect 3 load-indirect
4 3 profile-count-offset LWZ 4 3 profile-count-offset LWZ
4 4 1 v>operand ADDI 4 4 1 v>operand ADDI
4 3 profile-count-offset STW 4 3 profile-count-offset STW ;
"end" resolve-label ;
M: ppc-backend %call-label ( label -- ) BL ; M: ppc-backend %call-label ( label -- ) BL ;
@ -120,7 +111,9 @@ M: ppc-backend %jump-label ( label -- ) B ;
: %prepare-primitive ( word -- ) : %prepare-primitive ( word -- )
#! Save stack pointer to stack_chain->callstack_top, load XT #! Save stack pointer to stack_chain->callstack_top, load XT
4 1 MR 11 %load-xt ; 4 1 MR
0 11 LOAD32
rc-absolute-ppc-2/2 rel-word ;
: (%call) 11 MTLR BLRL ; : (%call) 11 MTLR BLRL ;
@ -141,6 +134,7 @@ M: ppc-backend %jump-t ( label -- )
"offset" operand "n" operand 1 SRAWI "offset" operand "n" operand 1 SRAWI
0 11 LOAD32 rc-absolute-ppc-2/2 rel-dispatch 0 11 LOAD32 rc-absolute-ppc-2/2 rel-dispatch
11 dup "offset" operand LWZX 11 dup "offset" operand LWZX
11 dup compiled-header-size ADDI
r> call r> call
] H{ ] H{
{ +input+ { { f "n" } } } { +input+ { { f "n" } } }

View File

@ -13,3 +13,5 @@ namespaces alien.c-types kernel system combinators ;
} cond } cond
T{ ppc-backend } compiler-backend set-global T{ ppc-backend } compiler-backend set-global
6 cells set-profiler-prologues

View File

@ -8,20 +8,23 @@ alien.compiler combinators command-line
compiler io vocabs.loader ; compiler io vocabs.loader ;
IN: cpu.x86.32 IN: cpu.x86.32
PREDICATE: x86-backend x86-32-backend
x86-backend-cell 4 = ;
! We implement the FFI for Linux, OS X and Windows all at once. ! We implement the FFI for Linux, OS X and Windows all at once.
! OS X requires that the stack be 16-byte aligned, and we do ! OS X requires that the stack be 16-byte aligned, and we do
! this on all platforms, sacrificing some stack space for ! this on all platforms, sacrificing some stack space for
! code simplicity. ! code simplicity.
M: x86-backend ds-reg ESI ; M: x86-32-backend ds-reg ESI ;
M: x86-backend rs-reg EDI ; M: x86-32-backend rs-reg EDI ;
M: x86-backend stack-reg ESP ; M: x86-32-backend stack-reg ESP ;
M: x86-backend xt-reg ECX ; M: x86-32-backend xt-reg ECX ;
M: x86-backend stack-save-reg EDX ; M: x86-32-backend stack-save-reg EDX ;
M: temp-reg v>operand drop EBX ; M: temp-reg v>operand drop EBX ;
M: x86-backend %alien-invoke ( symbol dll -- ) M: x86-32-backend %alien-invoke ( symbol dll -- )
(CALL) rel-dlsym ; (CALL) rel-dlsym ;
! On x86, parameters are never passed in registers. ! On x86, parameters are never passed in registers.
@ -58,20 +61,20 @@ M: float-regs store-return-reg load/store-float-return FSTP ;
! On x86, we can always use an address as an operand ! On x86, we can always use an address as an operand
! directly. ! directly.
M: x86-backend address-operand ; M: x86-32-backend address-operand ;
M: x86-backend fixnum>slot@ 1 SHR ; M: x86-32-backend fixnum>slot@ 1 SHR ;
M: x86-backend prepare-division CDQ ; M: x86-32-backend prepare-division CDQ ;
M: x86-backend load-indirect M: x86-32-backend load-indirect
0 [] MOV rc-absolute-cell rel-literal ; 0 [] MOV rc-absolute-cell rel-literal ;
M: object %load-param-reg 3drop ; M: object %load-param-reg 3drop ;
M: object %save-param-reg 3drop ; M: object %save-param-reg 3drop ;
M: x86-backend %prepare-unbox ( -- ) M: x86-32-backend %prepare-unbox ( -- )
#! Move top of data stack to EAX. #! Move top of data stack to EAX.
EAX ESI [] MOV EAX ESI [] MOV
ESI 4 SUB ; ESI 4 SUB ;
@ -84,7 +87,7 @@ M: x86-backend %prepare-unbox ( -- )
f %alien-invoke f %alien-invoke
] with-aligned-stack ; ] with-aligned-stack ;
M: x86-backend %unbox ( n reg-class func -- ) M: x86-32-backend %unbox ( n reg-class func -- )
#! The value being unboxed must already be in EAX. #! The value being unboxed must already be in EAX.
#! If n is f, we're unboxing a return value about to be #! If n is f, we're unboxing a return value about to be
#! returned by the callback. Otherwise, we're unboxing #! returned by the callback. Otherwise, we're unboxing
@ -93,7 +96,7 @@ M: x86-backend %unbox ( n reg-class func -- )
! Store the return value on the C stack ! Store the return value on the C stack
over [ store-return-reg ] [ 2drop ] if ; over [ store-return-reg ] [ 2drop ] if ;
M: x86-backend %unbox-long-long ( n func -- ) M: x86-32-backend %unbox-long-long ( n func -- )
(%unbox) (%unbox)
! Store the return value on the C stack ! Store the return value on the C stack
[ [
@ -101,7 +104,7 @@ M: x86-backend %unbox-long-long ( n func -- )
cell + stack@ EDX MOV cell + stack@ EDX MOV
] when* ; ] when* ;
M: x86-backend %unbox-struct-2 M: x86-32-backend %unbox-struct-2
#! Alien must be in EAX. #! Alien must be in EAX.
4 [ 4 [
EAX PUSH EAX PUSH
@ -112,7 +115,7 @@ M: x86-backend %unbox-struct-2
EAX EAX [] MOV EAX EAX [] MOV
] with-aligned-stack ; ] with-aligned-stack ;
M: x86-backend %unbox-large-struct ( n size -- ) M: x86-32-backend %unbox-large-struct ( n size -- )
#! Alien must be in EAX. #! Alien must be in EAX.
! Compute destination address ! Compute destination address
ECX ESP roll [+] LEA ECX ESP roll [+] LEA
@ -144,7 +147,7 @@ M: x86-backend %unbox-large-struct ( n size -- )
over [ [ box@ ] keep [ load-return-reg ] keep ] [ nip ] if over [ [ box@ ] keep [ load-return-reg ] keep ] [ nip ] if
push-return-reg ; push-return-reg ;
M: x86-backend %box ( n reg-class func -- ) M: x86-32-backend %box ( n reg-class func -- )
over reg-size [ over reg-size [
>r (%box) r> f %alien-invoke >r (%box) r> f %alien-invoke
] with-aligned-stack ; ] with-aligned-stack ;
@ -162,12 +165,12 @@ M: x86-backend %box ( n reg-class func -- )
EDX PUSH EDX PUSH
EAX PUSH ; EAX PUSH ;
M: x86-backend %box-long-long ( n func -- ) M: x86-32-backend %box-long-long ( n func -- )
8 [ 8 [
>r (%box-long-long) r> f %alien-invoke >r (%box-long-long) r> f %alien-invoke
] with-aligned-stack ; ] with-aligned-stack ;
M: x86-backend %box-large-struct ( n size -- ) M: x86-32-backend %box-large-struct ( n size -- )
! Compute destination address ! Compute destination address
[ swap struct-return@ ] keep [ swap struct-return@ ] keep
ECX ESP roll [+] LEA ECX ESP roll [+] LEA
@ -180,13 +183,13 @@ M: x86-backend %box-large-struct ( n size -- )
"box_value_struct" f %alien-invoke "box_value_struct" f %alien-invoke
] with-aligned-stack ; ] with-aligned-stack ;
M: x86-backend %prepare-box-struct ( size -- ) M: x86-32-backend %prepare-box-struct ( size -- )
! Compute target address for value struct return ! Compute target address for value struct return
EAX ESP rot f struct-return@ [+] LEA EAX ESP rot f struct-return@ [+] LEA
! Store it as the first parameter ! Store it as the first parameter
ESP [] EAX MOV ; ESP [] EAX MOV ;
M: x86-backend %unbox-struct-1 M: x86-32-backend %unbox-struct-1
#! Alien must be in EAX. #! Alien must be in EAX.
4 [ 4 [
EAX PUSH EAX PUSH
@ -195,7 +198,7 @@ M: x86-backend %unbox-struct-1
EAX EAX [] MOV EAX EAX [] MOV
] with-aligned-stack ; ] with-aligned-stack ;
M: x86-backend %box-small-struct ( size -- ) M: x86-32-backend %box-small-struct ( size -- )
#! Box a <= 8-byte struct returned in EAX:DX. OS X only. #! Box a <= 8-byte struct returned in EAX:DX. OS X only.
12 [ 12 [
PUSH PUSH
@ -204,21 +207,21 @@ M: x86-backend %box-small-struct ( size -- )
"box_small_struct" f %alien-invoke "box_small_struct" f %alien-invoke
] with-aligned-stack ; ] with-aligned-stack ;
M: x86-backend %prepare-alien-indirect ( -- ) M: x86-32-backend %prepare-alien-indirect ( -- )
"unbox_alien" f %alien-invoke "unbox_alien" f %alien-invoke
cell temp@ EAX MOV ; cell temp@ EAX MOV ;
M: x86-backend %alien-indirect ( -- ) M: x86-32-backend %alien-indirect ( -- )
cell temp@ CALL ; cell temp@ CALL ;
M: x86-backend %alien-callback ( quot -- ) M: x86-32-backend %alien-callback ( quot -- )
4 [ 4 [
EAX load-indirect EAX load-indirect
EAX PUSH EAX PUSH
"c_to_factor" f %alien-invoke "c_to_factor" f %alien-invoke
] with-aligned-stack ; ] with-aligned-stack ;
M: x86-backend %callback-value ( ctype -- ) M: x86-32-backend %callback-value ( ctype -- )
! Align C stack ! Align C stack
ESP 12 SUB ESP 12 SUB
! Save top of data stack ! Save top of data stack
@ -233,7 +236,7 @@ M: x86-backend %callback-value ( ctype -- )
! Unbox EAX ! Unbox EAX
unbox-return ; unbox-return ;
M: x86-backend %cleanup ( alien-node -- ) M: x86-32-backend %cleanup ( alien-node -- )
#! a) If we just called an stdcall function in Windows, it #! a) If we just called an stdcall function in Windows, it
#! cleaned up the stack frame for us. But we don't want that #! cleaned up the stack frame for us. But we don't want that
#! so we 'undo' the cleanup since we do that in %epilogue. #! so we 'undo' the cleanup since we do that in %epilogue.
@ -251,7 +254,7 @@ M: x86-backend %cleanup ( alien-node -- )
} }
} cond ; } cond ;
M: x86-backend %unwind ( n -- ) %epilogue-later RET ; M: x86-32-backend %unwind ( n -- ) %epilogue-later RET ;
windows? [ windows? [
cell "longlong" c-type set-c-type-align cell "longlong" c-type set-c-type-align
@ -272,6 +275,8 @@ T{ x86-backend f 4 } compiler-backend set-global
JNE JNE
] { } define-if-intrinsic ] { } define-if-intrinsic
10 set-profiler-prologues
"-no-sse2" cli-args member? [ "-no-sse2" cli-args member? [
"Checking if your CPU supports SSE2..." print flush "Checking if your CPU supports SSE2..." print flush
[ sse2? ] compile-1 [ [ sse2? ] compile-1 [

View File

@ -204,3 +204,5 @@ M: struct-type flatten-value-type ( type -- seq )
"void*" "double" ? c-type , "void*" "double" ? c-type ,
] each ] each
] if ; ] if ;
14 set-profiler-prologues

View File

@ -45,7 +45,7 @@ M: x86-backend stack-frame ( n -- i )
3 cells + 16 align cell - ; 3 cells + 16 align cell - ;
M: x86-backend %save-xt ( -- ) M: x86-backend %save-xt ( -- )
xt-reg compiling-label get MOV ; xt-reg 0 MOV rc-absolute-cell rel-current-word ;
: factor-area-size 4 cells ; : factor-area-size 4 cells ;
@ -71,13 +71,8 @@ M: x86-backend %prepare-alien-invoke
temp-reg v>operand 3 cells [+] rs-reg MOV ; temp-reg v>operand 3 cells [+] rs-reg MOV ;
M: x86-backend %profiler-prologue ( word -- ) M: x86-backend %profiler-prologue ( word -- )
"end" define-label
"profiling" f temp-reg v>operand %alien-global
temp-reg v>operand 0 CMP
"end" get JE
temp-reg load-literal temp-reg load-literal
temp-reg v>operand profile-count-offset [+] 1 v>operand ADD temp-reg v>operand profile-count-offset [+] 1 v>operand ADD ;
"end" resolve-label ;
M: x86-backend %call-label ( label -- ) CALL ; M: x86-backend %call-label ( label -- ) CALL ;
@ -106,14 +101,16 @@ M: x86-backend %jump-t ( label -- )
! since on AMD64 we have to load a 64-bit immediate. On ! since on AMD64 we have to load a 64-bit immediate. On
! x86, this is redundant. ! x86, this is redundant.
"scratch" operand HEX: ffffffff MOV rc-absolute-cell rel-dispatch "scratch" operand HEX: ffffffff MOV rc-absolute-cell rel-dispatch
"n" operand "scratch" operand ADD ; "n" operand "n" operand "scratch" operand [+] MOV
"n" operand compiled-header-size ADD ;
: dispatch-template ( word-table# quot -- ) : dispatch-template ( word-table# quot -- )
[ [
>r (%dispatch) "n" operand [] r> call >r (%dispatch) "n" operand r> call
] H{ ] H{
{ +input+ { { f "n" } } } { +input+ { { f "n" } } }
{ +scratch+ { { f "scratch" } } } { +scratch+ { { f "scratch" } } }
{ +clobber+ { "n" } }
} with-template ; inline } with-template ; inline
M: x86-backend %call-dispatch ( word-table# -- ) M: x86-backend %call-dispatch ( word-table# -- )

View File

@ -69,7 +69,8 @@ SYMBOL: label-table
: rt-literal 2 ; : rt-literal 2 ;
: rt-dispatch 3 ; : rt-dispatch 3 ;
: rt-xt 4 ; : rt-xt 4 ;
: rt-label 5 ; : rt-xt-profiling 5 ;
: rt-label 6 ;
TUPLE: label-fixup label class ; TUPLE: label-fixup label class ;

View File

@ -5,9 +5,8 @@ IN: generator
ARTICLE: "generator" "Compiled code generator" ARTICLE: "generator" "Compiled code generator"
"Most of the words in the " { $vocab-link "generator" } " vocabulary are internal to the compiler and user code has no reason to call them." "Most of the words in the " { $vocab-link "generator" } " vocabulary are internal to the compiler and user code has no reason to call them."
$nl $nl
"Debugging information can be enabled or disabled; these hooks are used by " { $link "profiling" } " and " { $link "tools.deploy" } ":" "Debugging information can be enabled or disabled; this hook is used by " { $link "tools.deploy" } ":"
{ $subsection profiler-prologues } { $subsection compiled-stack-traces? }
{ $subsection compiled-stack-traces }
"Assembler intrinsics can be defined for low-level optimization:" "Assembler intrinsics can be defined for low-level optimization:"
{ $subsection define-intrinsic } { $subsection define-intrinsic }
{ $subsection define-intrinsics } { $subsection define-intrinsics }
@ -42,11 +41,11 @@ HELP: compiling-word
HELP: compiling-label HELP: compiling-label
{ $var-description "The label currently being compiled, set by " { $link generate-1 } "." } ; { $var-description "The label currently being compiled, set by " { $link generate-1 } "." } ;
HELP: compiled-stack-traces HELP: compiled-stack-traces?
{ $var-description "If set to true, compiled code blocks will retain what word they were compiled from. This information is used by " { $link :c } " to display call stack traces after an error is thrown from compiled code. This variable is on by default; the deployment tool switches it off to save some space in the deployed image." } ; { $var-description "If set to true, compiled code blocks will retain what word they were compiled from. This information is used by " { $link :c } " to display call stack traces after an error is thrown from compiled code. This variable is on by default; the deployment tool switches it off to save some space in the deployed image." } ;
HELP: literal-table HELP: literal-table
{ $var-description "Holds a vector of literal objects referenced from the currently compiling word. If " { $link compiled-stack-traces } " is on, " { $link init-generator } " ensures that the first entry is the word being compiled." } ; { $var-description "Holds a vector of literal objects referenced from the currently compiling word. If " { $link compiled-stack-traces? } " is on, " { $link init-generator } " ensures that the first entry is the word being compiled." } ;
HELP: init-generator HELP: init-generator
{ $values { "word" word } } { $values { "word" word } }
@ -66,9 +65,6 @@ HELP: generate-nodes
{ $description "Recursively generate machine code for a dataflow graph." } { $description "Recursively generate machine code for a dataflow graph." }
{ $notes "This word can only be called from inside the quotation passed to " { $link generate-1 } "." } ; { $notes "This word can only be called from inside the quotation passed to " { $link generate-1 } "." } ;
HELP: profiler-prologue
{ $description "Compiles a prologue which increment's the currently compiling word's call count, if such prologues were enabled by setting " { $link profiler-prologues } " to a true value." } ;
HELP: generate HELP: generate
{ $values { "word" word } { "label" word } { "node" "a dataflow node" } } { $values { "word" word } { "label" word } { "node" "a dataflow node" } }
{ $description "Generates machine code for " { $snippet "label" } " from " { $snippet "node" } ". The value of " { $snippet "word" } " is retained for debugging purposes; it is the word which will appear in a call stack trace if this compiled code block throws an error when run." } ; { $description "Generates machine code for " { $snippet "label" } " from " { $snippet "node" } ". The value of " { $snippet "word" } " is retained for debugging purposes; it is the word which will appear in a call stack trace if this compiled code block throws an error when run." } ;

View File

@ -26,15 +26,14 @@ SYMBOL: compiling-label
! Label of current word, after prologue, makes recursion faster ! Label of current word, after prologue, makes recursion faster
SYMBOL: current-label-start SYMBOL: current-label-start
SYMBOL: compiled-stack-traces SYMBOL: compiled-stack-traces?
t compiled-stack-traces set-global t compiled-stack-traces? set-global
: init-generator ( -- ) : init-generator ( -- )
V{ } clone literal-table set V{ } clone literal-table set
V{ } clone word-table set V{ } clone word-table set
compiled-stack-traces get compiled-stack-traces? get compiling-word get f ?
[ compiling-word get ] [ f ] if
literal-table get push ; literal-table get push ;
: generate-1 ( word label node quot -- ) : generate-1 ( word label node quot -- )
@ -42,29 +41,27 @@ t compiled-stack-traces set-global
roll compiling-word set roll compiling-word set
pick compiling-label set pick compiling-label set
init-generator init-generator
%save-xt
%prologue-later
call call
literal-table get >array literal-table get >array
word-table get >array word-table get >array
] { } make fixup add-compiled-block save-xt ; ] { } make fixup add-compiled-block save-xt ;
: generate-profiler-prologue ( -- )
compiled-stack-traces? get [
compiling-word get %profiler-prologue
] when ;
GENERIC: generate-node ( node -- next ) GENERIC: generate-node ( node -- next )
: generate-nodes ( node -- ) : generate-nodes ( node -- )
[ node@ generate-node ] iterate-nodes end-basic-block ; [ node@ generate-node ] iterate-nodes end-basic-block ;
SYMBOL: profiler-prologues
: profiler-prologue ( -- )
profiler-prologues get-global [
compiling-word get %profiler-prologue
] when ;
: generate ( word label node -- ) : generate ( word label node -- )
[ [
init-templates init-templates
profiler-prologue generate-profiler-prologue
%save-xt
%prologue-later
current-label-start define-label current-label-start define-label
current-label-start resolve-label current-label-start resolve-label
[ generate-nodes ] with-node-iterator [ generate-nodes ] with-node-iterator
@ -183,11 +180,17 @@ M: #if generate-node
with-template with-template
generate-if ; generate-if ;
: rel-current-word ( class -- )
compiling-label get add-word
swap rt-xt-profiling rel-fixup ;
! #dispatch ! #dispatch
: dispatch-branch ( node word -- label ) : dispatch-branch ( node word -- label )
gensym [ gensym [
rot [ rot [
copy-templates copy-templates
%save-xt
%prologue-later
[ generate-nodes ] with-node-iterator [ generate-nodes ] with-node-iterator
] generate-1 ] generate-1
] keep ; ] keep ;
@ -232,11 +235,9 @@ M: #dispatch generate-node
: define-if>boolean-intrinsics ( word intrinsics -- ) : define-if>boolean-intrinsics ( word intrinsics -- )
[ [
first2
>r [ if>boolean-intrinsic ] curry r> >r [ if>boolean-intrinsic ] curry r>
{ { f "if-scratch" } } +scratch+ associate union { { f "if-scratch" } } +scratch+ associate union
2array ] assoc-map "intrinsics" set-word-prop ;
] map "intrinsics" set-word-prop ;
: define-if-intrinsics ( word intrinsics -- ) : define-if-intrinsics ( word intrinsics -- )
[ +input+ associate ] assoc-map [ +input+ associate ] assoc-map
@ -313,3 +314,4 @@ M: #return generate-node drop end-basic-block %return f ;
: tuple-class-offset 2 cells tuple tag-number - ; : tuple-class-offset 2 cells tuple tag-number - ;
: class-hash-offset cell object tag-number - ; : class-hash-offset cell object tag-number - ;
: word-xt-offset 8 cells object tag-number - ; : word-xt-offset 8 cells object tag-number - ;
: compiled-header-size 8 cells ;

View File

@ -168,8 +168,10 @@ M: hashtable equal?
} cond ; } cond ;
M: hashtable hashcode* M: hashtable hashcode*
[
dup assoc-size 1 number= dup assoc-size 1 number=
[ assoc-hashcode ] [ nip assoc-size ] if ; [ assoc-hashcode ] [ nip assoc-size ] if
] recursive-hashcode ;
! Default method ! Default method
M: assoc new-assoc drop <hashtable> ; M: assoc new-assoc drop <hashtable> ;

View File

@ -91,8 +91,6 @@ M: real hashcode* nip >fixnum ;
M: real <=> - ; M: real <=> - ;
! real and sequence overlap. we disambiguate: ! real and sequence overlap. we disambiguate:
M: integer equal? number= ;
M: integer hashcode* nip >fixnum ; M: integer hashcode* nip >fixnum ;
M: integer <=> - ; M: integer <=> - ;

View File

@ -1,18 +1,15 @@
USING: tools.profiler.private tools.time help.markup help.syntax USING: tools.profiler.private tools.time help.markup help.syntax
quotations io strings words definitions generator ; quotations io strings words definitions ;
IN: tools.profiler IN: tools.profiler
ARTICLE: "profiling" "Profiling code" ARTICLE: "profiling" "Profiling code"
"A simple call counting profiler is included. Both compiled and interpreted code can be profiled. There are a number of limitations when profiling compiled code:" "The " { $vocab-link "tools.profiler" } " vocabulary implements a simple call counting profiler. The profiler has three main limitations:"
{ $list { $list
{ "Calls to " { $link POSTPONE: inline } " words are not counted" } "Calls to primitives are not counted."
"Calls to primitives are not counted" { "Calls to " { $link POSTPONE: inline } " words from words compiled with the optimizing compiler are not counted." }
"Certain types of tail-recursive words compiled with the optimizing compiler will only count the initial invocation of the word, not every tail call."
} }
"The profiler must be enabled before use:" "Quotations can be passed to a combinator which calls them with word call counting enabled:"
{ $subsection enable-profiler }
"Since enabling the profiler reduces performance, it should be disabled after use:"
{ $subsection disable-profiler }
"While enabled, a combinator which counts all calls made by a quotation can be used:"
{ $subsection profile } { $subsection profile }
"After a quotation has been profiled, call counts can be presented in various ways:" "After a quotation has been profiled, call counts can be presented in various ways:"
{ $subsection profile. } { $subsection profile. }
@ -22,10 +19,6 @@ ARTICLE: "profiling" "Profiling code"
ABOUT: "profiling" ABOUT: "profiling"
HELP: reset-counters
{ $description "Reset the call count of all words in the dictionary." }
{ $notes "This word is automatically called by the profiler when profiling begins." } ;
HELP: counters HELP: counters
{ $values { "words" "a sequence of words" } { "assoc" "an association list mapping words to integers" } } { $values { "words" "a sequence of words" } { "assoc" "an association list mapping words to integers" } }
{ $description "Outputs an association list of word call counts." } ; { $description "Outputs an association list of word call counts." } ;
@ -34,20 +27,9 @@ HELP: counters.
{ $values { "assoc" "an association list mapping words to integers" } } { $values { "assoc" "an association list mapping words to integers" } }
{ $description "Prints an association list of call counts to the " { $link stdio } " stream." } ; { $description "Prints an association list of call counts to the " { $link stdio } " stream." } ;
HELP: enable-profiler
{ $description "Recompiles all words in the dictionary to include a stub which increments the call count during profiling. Once this is done, the " { $link profile } " combinator may be used." }
{ $notes "Performance is affected when profiling is enabled, so profiling should only be enabled when necessary." } ;
HELP: disable-profiler
{ $description "Recompiles all words in the dictionary to exclude a stub which increments the call count during profiling. This should be done when you no longer wish to use the " { $link profile } " combinator." } ;
HELP: check-profiler
{ $description "Throws an error if the profiler has not yet been enabled by a call to " { $link enable-profiler } "." } ;
HELP: profile HELP: profile
{ $values { "quot" quotation } } { $values { "quot" quotation } }
{ $description "Calls the quotation while collecting word call counts, which can then be displayed using " { $link profile. } " or related words." } { $description "Calls the quotation while collecting word call counts, which can then be displayed using " { $link profile. } " or related words." } ;
{ $errors "Throws an error if the profiler has not been enabled by a prior call to " { $link enable-profiler } "." } ;
HELP: profile. HELP: profile.
{ $description "Prints a table of call counts from the most recent invocation of " { $link profile } "." } ; { $description "Prints a table of call counts from the most recent invocation of " { $link profile } "." } ;
@ -68,9 +50,6 @@ HELP: vocabs-profile.
HELP: profiling ( ? -- ) HELP: profiling ( ? -- )
{ $values { "?" "a boolean" } } { $values { "?" "a boolean" } }
{ $description "Internal primitive to switch on call counting. This word should not be used; instead see " { $link enable-profiler } ", " { $link profile } " and " { $link disable-profiler } "." } ; { $description "Internal primitive to switch on call counting. This word should not be used; instead use " { $link profile } "." } ;
{ time profile } related-words { time profile } related-words
HELP: profiler-prologues
{ $var-description "If set, each word will be compiled with an extra prologue which checks if profiling is enabled, and if so, increments the word's call count. This variable is off by default. It should never be set directly; " { $link enable-profiler } " and " { $link disable-profiler } " should be used instead." } ;

View File

@ -2,8 +2,6 @@ IN: temporary
USING: tools.profiler tools.test kernel memory math threads USING: tools.profiler tools.test kernel memory math threads
alien tools.profiler.private ; alien tools.profiler.private ;
enable-profiler
[ ] [ [ 10 [ data-gc ] times ] profile ] unit-test [ ] [ [ 10 [ data-gc ] times ] profile ] unit-test
[ ] [ [ 1000 sleep ] profile ] unit-test [ ] [ [ 1000 sleep ] profile ] unit-test
@ -28,5 +26,3 @@ enable-profiler
] profile ] profile
[ 1 ] [ \ foobar profile-counter ] unit-test [ 1 ] [ \ foobar profile-counter ] unit-test
disable-profiler

View File

@ -1,13 +1,13 @@
! Copyright (C) 2007 Slava Pestov. ! Copyright (C) 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: words sequences math prettyprint kernel arrays USING: words sequences math prettyprint kernel arrays io
io io.styles namespaces assocs kernel.private generator io.styles namespaces assocs kernel.private strings combinators
compiler strings combinators sorting math.parser sorting math.parser vocabs definitions tools.profiler.private
vocabs definitions tools.profiler.private ; continuations ;
IN: tools.profiler IN: tools.profiler
: reset-counters ( -- ) : profile ( quot -- )
all-words [ 0 swap set-profile-counter ] each ; [ t profiling call ] [ f profiling ] [ ] cleanup ;
: counters ( words -- assoc ) : counters ( words -- assoc )
[ dup profile-counter ] { } map>assoc ; [ dup profile-counter ] { } map>assoc ;
@ -40,26 +40,6 @@ M: string (profile.)
[ counter. ] assoc-each [ counter. ] assoc-each
] tabular-output ; ] tabular-output ;
: enable-profiler ( -- )
t profiler-prologues set-global recompile-all
"Profiler enabled; use disable-profiler to disable" print ;
: disable-profiler ( -- )
f profiler-prologues set-global recompile-all ;
: check-profiler ( -- )
profiler-prologues get-global [
"Enable the profiler by calling enable-profiler first"
throw
] unless ;
: profile ( quot -- )
check-profiler
reset-counters
t profiling
call
f profiling ;
: profile. ( -- ) : profile. ( -- )
"Call counts for all words:" print "Call counts for all words:" print
all-words counters counters. ; all-words counters counters. ;

View File

@ -24,23 +24,11 @@ TUPLE: profiler-gadget pane ;
: com-vocabs-profile ( gadget -- ) : com-vocabs-profile ( gadget -- )
[ vocabs-profile. ] with-profiler-pane ; [ vocabs-profile. ] with-profiler-pane ;
\ enable-profiler H{
{ +nullary+ t }
{ +listener+ t }
} define-command
\ disable-profiler H{
{ +nullary+ t }
{ +listener+ t }
} define-command
: profiler-help "ui-profiler" help-window ; : profiler-help "ui-profiler" help-window ;
\ profiler-help H{ { +nullary+ t } } define-command \ profiler-help H{ { +nullary+ t } } define-command
profiler-gadget "toolbar" f { profiler-gadget "toolbar" f {
{ f enable-profiler }
{ f disable-profiler }
{ f com-full-profile } { f com-full-profile }
{ f com-vocabs-profile } { f com-vocabs-profile }
{ T{ key-down f f "F1" } profiler-help } { T{ key-down f f "F1" } profiler-help }

View File

@ -65,7 +65,7 @@ $nl
ARTICLE: "ui-profiler" "UI profiler" ARTICLE: "ui-profiler" "UI profiler"
"The graphical profiler is based on the terminal profiler (see " { $link "profiling" } ") and adds more convenient browsing of profiler results." "The graphical profiler is based on the terminal profiler (see " { $link "profiling" } ") and adds more convenient browsing of profiler results."
$nl $nl
"The profiler must be enabled before use. Once the profiler has been enabled, enter a piece of code in the listener input area and press " { $operation com-profile } "." "To use the profiler, enter a piece of code in the listener input area and press " { $operation com-profile } "."
$nl $nl
"Vocabulary and word presentations in the profiler pane can be clicked on to show profiler results pertaining to the object in question. Clicking a vocabulary in the profiler yields the same output as the " { $link vocab-profile. } " word, and clicking a word yields the same output as the " { $link usage-profile. } " word. Consult " { $link "profiling" } " for details." "Vocabulary and word presentations in the profiler pane can be clicked on to show profiler results pertaining to the object in question. Clicking a vocabulary in the profiler yields the same output as the " { $link vocab-profile. } " word, and clicking a word yields the same output as the " { $link usage-profile. } " word. Consult " { $link "profiling" } " for details."
{ $command-map profiler-gadget "toolbar" } ; { $command-map profiler-gadget "toolbar" } ;

View File

@ -64,7 +64,7 @@ TUPLE: posting author title date link body ;
: print-posting ( posting -- ) : print-posting ( posting -- )
<h2 "posting-title" =class h2> <h2 "posting-title" =class h2>
<a dup posting-link =href a> <a dup posting-link =href a>
dup posting-title write dup posting-title write-html
" - " write " - " write
dup posting-author write dup posting-author write
</a> </a>
@ -104,6 +104,9 @@ SYMBOL: cached-postings
{ "Elie Chaftari" "http://fun-factor.blogspot.com/feeds/posts/default" "http://fun-factor.blogspot.com/" } { "Elie Chaftari" "http://fun-factor.blogspot.com/feeds/posts/default" "http://fun-factor.blogspot.com/" }
{ "Doug Coleman" "http://code-factor.blogspot.com/feeds/posts/default" "http://code-factor.blogspot.com/" } { "Doug Coleman" "http://code-factor.blogspot.com/feeds/posts/default" "http://code-factor.blogspot.com/" }
{ "Daniel Ehrenberg" "http://useless-factor.blogspot.com/feeds/posts/default" "http://useless-factor.blogspot.com/" } { "Daniel Ehrenberg" "http://useless-factor.blogspot.com/feeds/posts/default" "http://useless-factor.blogspot.com/" }
{ "Kio M. Smallwood"
"http://sekenre.wordpress.com/feed/atom/"
"http://sekenre.wordpress.com/" }
{ "Samuel Tardieu" "http://www.rfc1149.net/blog/tag/factor/feed/atom/" "http://www.rfc1149.net/blog/tag/factor/" } { "Samuel Tardieu" "http://www.rfc1149.net/blog/tag/factor/feed/atom/" "http://www.rfc1149.net/blog/tag/factor/" }
{ "Slava Pestov" "http://factor-language.blogspot.com/atom.xml" "http://factor-language.blogspot.com/" } { "Slava Pestov" "http://factor-language.blogspot.com/atom.xml" "http://factor-language.blogspot.com/" }
} default-blogroll set-global } default-blogroll set-global

View File

@ -95,14 +95,19 @@ DEFINE_PRIMITIVE(set_callstack)
critical_error("Bug in set_callstack()",0); critical_error("Bug in set_callstack()",0);
} }
F_COMPILED *frame_code(F_STACK_FRAME *frame)
{
return (F_COMPILED *)frame->xt - 1;
}
CELL frame_type(F_STACK_FRAME *frame) CELL frame_type(F_STACK_FRAME *frame)
{ {
return xt_to_compiled(frame->xt)->type; return frame_code(frame)->type;
} }
CELL frame_executing(F_STACK_FRAME *frame) CELL frame_executing(F_STACK_FRAME *frame)
{ {
F_COMPILED *compiled = xt_to_compiled(frame->xt); F_COMPILED *compiled = frame_code(frame);
CELL code_start = (CELL)(compiled + 1); CELL code_start = (CELL)(compiled + 1);
CELL literal_start = code_start CELL literal_start = code_start
+ compiled->code_length + compiled->code_length
@ -199,7 +204,7 @@ DEFINE_PRIMITIVE(set_innermost_stack_frame_quot)
REGISTER_UNTAGGED(callstack); REGISTER_UNTAGGED(callstack);
REGISTER_UNTAGGED(quot); REGISTER_UNTAGGED(quot);
if(quot->compiled == F) if(quot->compiledp == F)
jit_compile(quot); jit_compile(quot);
UNREGISTER_UNTAGGED(quot); UNREGISTER_UNTAGGED(quot);

View File

@ -9,6 +9,7 @@ F_STACK_FRAME *fix_callstack_top(F_STACK_FRAME *top, F_STACK_FRAME *bottom);
void iterate_callstack(CELL top, CELL bottom, CALLSTACK_ITER iterator); void iterate_callstack(CELL top, CELL bottom, CALLSTACK_ITER iterator);
void iterate_callstack_object(F_CALLSTACK *stack, CALLSTACK_ITER iterator); void iterate_callstack_object(F_CALLSTACK *stack, CALLSTACK_ITER iterator);
F_STACK_FRAME *frame_successor(F_STACK_FRAME *frame); F_STACK_FRAME *frame_successor(F_STACK_FRAME *frame);
F_COMPILED *frame_code(F_STACK_FRAME *frame);
CELL frame_executing(F_STACK_FRAME *frame); CELL frame_executing(F_STACK_FRAME *frame);
CELL frame_scan(F_STACK_FRAME *frame); CELL frame_scan(F_STACK_FRAME *frame);
CELL frame_type(F_STACK_FRAME *frame); CELL frame_type(F_STACK_FRAME *frame);

View File

@ -279,17 +279,17 @@ void collect_literals(void)
void mark_sweep_step(F_COMPILED *compiled, CELL code_start, void mark_sweep_step(F_COMPILED *compiled, CELL code_start,
CELL reloc_start, CELL literals_start, CELL words_start, CELL words_end) CELL reloc_start, CELL literals_start, CELL words_start, CELL words_end)
{ {
CELL scan; F_COMPILED **start = (F_COMPILED **)words_start;
F_COMPILED **end = (F_COMPILED **)words_end;
F_COMPILED **iter = start;
for(scan = words_start; scan < words_end; scan += CELLS) while(iter < end)
recursive_mark((XT)get(scan)); recursive_mark(compiled_to_block(*iter++));
} }
/* Mark all XTs and literals referenced from a word XT */ /* Mark all XTs and literals referenced from a word XT */
void recursive_mark(XT xt) void recursive_mark(F_BLOCK *block)
{ {
F_BLOCK *block = xt_to_block(xt);
/* If already marked, do nothing */ /* If already marked, do nothing */
switch(block->status) switch(block->status)
{ {
@ -303,7 +303,7 @@ void recursive_mark(XT xt)
break; break;
} }
F_COMPILED *compiled = xt_to_compiled(xt); F_COMPILED *compiled = block_to_compiled(block);
iterate_code_heap_step(compiled,collect_literals_step); iterate_code_heap_step(compiled,collect_literals_step);
switch(compiled->finalized) switch(compiled->finalized)
@ -386,10 +386,9 @@ CELL compute_heap_forwarding(F_HEAP *heap)
return address - heap->segment->start; return address - heap->segment->start;
} }
void forward_xt(XT *xt) F_COMPILED *forward_xt(F_COMPILED *compiled)
{ {
F_BLOCK *block = xt_to_block(*xt); return block_to_compiled(compiled_to_block(compiled)->forwarding);
*xt = block_to_xt(block->forwarding);
} }
void forward_object_xts(void) void forward_object_xts(void)
@ -404,15 +403,15 @@ void forward_object_xts(void)
{ {
F_WORD *word = untag_object(obj); F_WORD *word = untag_object(obj);
if(in_code_heap_p((CELL)word->xt)) if(word->compiledp != F)
forward_xt(&word->xt); set_word_xt(word,forward_xt(word->code));
} }
else if(type_of(obj) == QUOTATION_TYPE) else if(type_of(obj) == QUOTATION_TYPE)
{ {
F_QUOTATION *quot = untag_object(obj); F_QUOTATION *quot = untag_object(obj);
if(in_code_heap_p((CELL)quot->xt)) if(quot->compiledp != F)
forward_xt(&quot->xt); set_quot_xt(quot,forward_xt(quot->code));
} }
} }
@ -423,11 +422,14 @@ void forward_object_xts(void)
void compaction_code_block_fixup(F_COMPILED *compiled, CELL code_start, void compaction_code_block_fixup(F_COMPILED *compiled, CELL code_start,
CELL reloc_start, CELL literals_start, CELL words_start, CELL words_end) CELL reloc_start, CELL literals_start, CELL words_start, CELL words_end)
{ {
XT *iter = (XT *)words_start; F_COMPILED **iter = (F_COMPILED **)words_start;
XT *end = (XT *)words_end; F_COMPILED **end = (F_COMPILED **)words_end;
while(iter < end) while(iter < end)
forward_xt(iter++); {
*iter = forward_xt(*iter);
iter++;
}
} }
void forward_block_xts(void) void forward_block_xts(void)

View File

@ -47,18 +47,6 @@ INLINE F_BLOCK *next_block(F_HEAP *heap, F_BLOCK *block)
/* compiled code */ /* compiled code */
F_HEAP code_heap; F_HEAP code_heap;
/* The compiled code heap is structured into blocks. */
typedef struct
{
CELL type; /* this is WORD_TYPE or QUOTATION_TYPE */
CELL code_length; /* # bytes */
CELL reloc_length; /* # bytes */
CELL literals_length; /* # bytes */
CELL words_length; /* # bytes */
CELL finalized; /* has finalize_code_block() been called on this yet? */
CELL padding[2];
} F_COMPILED;
typedef void (*CODE_HEAP_ITERATOR)(F_COMPILED *compiled, CELL code_start, typedef void (*CODE_HEAP_ITERATOR)(F_COMPILED *compiled, CELL code_start,
CELL reloc_start, CELL literals_start, CELL words_start, CELL words_end); CELL reloc_start, CELL literals_start, CELL words_start, CELL words_end);
@ -73,14 +61,9 @@ INLINE void iterate_code_heap_step(F_COMPILED *compiled, CODE_HEAP_ITERATOR iter
iter(compiled,code_start,reloc_start,literals_start,words_start,words_end); iter(compiled,code_start,reloc_start,literals_start,words_start,words_end);
} }
INLINE F_BLOCK *xt_to_block(XT xt) INLINE F_BLOCK *compiled_to_block(F_COMPILED *compiled)
{ {
return (F_BLOCK *)((CELL)xt - sizeof(F_BLOCK) - sizeof(F_COMPILED)); return (F_BLOCK *)compiled - 1;
}
INLINE F_COMPILED *xt_to_compiled(XT xt)
{
return (F_COMPILED *)((CELL)xt - sizeof(F_COMPILED));
} }
INLINE F_COMPILED *block_to_compiled(F_BLOCK *block) INLINE F_COMPILED *block_to_compiled(F_BLOCK *block)
@ -88,11 +71,6 @@ INLINE F_COMPILED *block_to_compiled(F_BLOCK *block)
return (F_COMPILED *)(block + 1); return (F_COMPILED *)(block + 1);
} }
INLINE XT block_to_xt(F_BLOCK *block)
{
return (XT)((CELL)block + sizeof(F_BLOCK) + sizeof(F_COMPILED));
}
INLINE F_BLOCK *first_block(F_HEAP *heap) INLINE F_BLOCK *first_block(F_HEAP *heap)
{ {
return (F_BLOCK *)heap->segment->start; return (F_BLOCK *)heap->segment->start;
@ -107,7 +85,7 @@ void init_code_heap(CELL size);
bool in_code_heap_p(CELL ptr); bool in_code_heap_p(CELL ptr);
void iterate_code_heap(CODE_HEAP_ITERATOR iter); void iterate_code_heap(CODE_HEAP_ITERATOR iter);
void collect_literals(void); void collect_literals(void);
void recursive_mark(XT xt); void recursive_mark(F_BLOCK *block);
void dump_heap(F_HEAP *heap); void dump_heap(F_HEAP *heap);
void code_gc(void); void code_gc(void);
void compact_code_heap(void); void compact_code_heap(void);

View File

@ -36,6 +36,8 @@ void *get_rel_symbol(F_REL *rel, CELL literals_start)
return undefined_symbol; return undefined_symbol;
} }
static CELL xt_offset;
/* Compute an address to store at a relocation */ /* Compute an address to store at a relocation */
INLINE CELL compute_code_rel(F_REL *rel, INLINE CELL compute_code_rel(F_REL *rel,
CELL code_start, CELL literals_start, CELL words_start) CELL code_start, CELL literals_start, CELL words_start)
@ -51,7 +53,11 @@ INLINE CELL compute_code_rel(F_REL *rel,
case RT_DISPATCH: case RT_DISPATCH:
return CREF(words_start,REL_ARGUMENT(rel)); return CREF(words_start,REL_ARGUMENT(rel));
case RT_XT: case RT_XT:
return get(CREF(words_start,REL_ARGUMENT(rel))); return get(CREF(words_start,REL_ARGUMENT(rel)))
+ sizeof(F_COMPILED) + xt_offset;
case RT_XT_PROFILING:
return get(CREF(words_start,REL_ARGUMENT(rel)))
+ sizeof(F_COMPILED);
case RT_LABEL: case RT_LABEL:
return code_start + REL_ARGUMENT(rel); return code_start + REL_ARGUMENT(rel);
default: default:
@ -127,6 +133,8 @@ void apply_relocation(CELL class, CELL offset, F_FIXNUM absolute_value)
void relocate_code_block(F_COMPILED *relocating, CELL code_start, void relocate_code_block(F_COMPILED *relocating, CELL code_start,
CELL reloc_start, CELL literals_start, CELL words_start, CELL words_end) CELL reloc_start, CELL literals_start, CELL words_start, CELL words_end)
{ {
xt_offset = (profiling_p() ? 0 : profiler_prologue());
F_REL *rel = (F_REL *)reloc_start; F_REL *rel = (F_REL *)reloc_start;
F_REL *rel_end = (F_REL *)literals_start; F_REL *rel_end = (F_REL *)literals_start;
@ -172,12 +180,15 @@ void finalize_code_block(F_COMPILED *relocating, CELL code_start,
critical_error("Finalizing a finalized block",(CELL)relocating); critical_error("Finalizing a finalized block",(CELL)relocating);
for(scan = words_start; scan < words_end; scan += CELLS) for(scan = words_start; scan < words_end; scan += CELLS)
put(scan,(CELL)(untag_word(get(scan))->xt)); put(scan,(CELL)(untag_word(get(scan))->code));
relocating->finalized = true; relocating->finalized = true;
if(reloc_start != literals_start)
{
relocate_code_block(relocating,code_start,reloc_start, relocate_code_block(relocating,code_start,reloc_start,
literals_start,words_start,words_end); literals_start,words_start,words_end);
}
flush_icache(code_start,reloc_start - code_start); flush_icache(code_start,reloc_start - code_start);
} }
@ -231,7 +242,7 @@ CELL allot_code_block(CELL size)
return start; return start;
} }
XT add_compiled_block( F_COMPILED *add_compiled_block(
CELL type, CELL type,
F_ARRAY *code, F_ARRAY *code,
F_ARRAY *labels, F_ARRAY *labels,
@ -252,7 +263,7 @@ XT add_compiled_block(
REGISTER_UNTAGGED(words); REGISTER_UNTAGGED(words);
REGISTER_UNTAGGED(literals); REGISTER_UNTAGGED(literals);
CELL start = allot_code_block(sizeof(F_COMPILED) + code_length CELL here = allot_code_block(sizeof(F_COMPILED) + code_length
+ rel_length + literals_length + words_length); + rel_length + literals_length + words_length);
UNREGISTER_UNTAGGED(literals); UNREGISTER_UNTAGGED(literals);
@ -261,9 +272,6 @@ XT add_compiled_block(
UNREGISTER_UNTAGGED(labels); UNREGISTER_UNTAGGED(labels);
UNREGISTER_UNTAGGED(code); UNREGISTER_UNTAGGED(code);
/* begin depositing the code block's contents */
CELL here = start;
/* compiled header */ /* compiled header */
F_COMPILED *header = (void *)here; F_COMPILED *header = (void *)here;
header->type = type; header->type = type;
@ -275,6 +283,8 @@ XT add_compiled_block(
here += sizeof(F_COMPILED); here += sizeof(F_COMPILED);
CELL code_start = here;
/* code */ /* code */
deposit_integers(here,code,code_format); deposit_integers(here,code,code_format);
here += code_length; here += code_length;
@ -300,18 +310,26 @@ XT add_compiled_block(
here += words_length; here += words_length;
} }
/* compute the XT */
XT xt = (XT)(start + sizeof(F_COMPILED));
/* fixup labels */ /* fixup labels */
if(labels) if(labels)
fixup_labels(labels,code_format,(CELL)xt); fixup_labels(labels,code_format,code_start);
/* next time we do a minor GC, we have to scan the code heap for /* next time we do a minor GC, we have to scan the code heap for
literals */ literals */
last_code_heap_scan = NURSERY; last_code_heap_scan = NURSERY;
return xt; return header;
}
void set_word_xt(F_WORD *word, F_COMPILED *compiled)
{
word->code = compiled;
word->xt = (XT)(compiled + 1);
if(!profiling_p())
word->xt += profiler_prologue();
word->compiledp = T;
} }
DEFINE_PRIMITIVE(add_compiled_block) DEFINE_PRIMITIVE(add_compiled_block)
@ -322,12 +340,11 @@ DEFINE_PRIMITIVE(add_compiled_block)
F_ARRAY *words = untag_array(dpop()); F_ARRAY *words = untag_array(dpop());
F_ARRAY *literals = untag_array(dpop()); F_ARRAY *literals = untag_array(dpop());
XT xt = add_compiled_block(WORD_TYPE,code,labels,rel,words,literals); F_COMPILED *compiled = add_compiled_block(WORD_TYPE,code,labels,rel,words,literals);
/* push the XT of the new word on the stack */ /* push a new word whose XT points to this code block on the stack */
F_WORD *word = allot_word(F,F); F_WORD *word = allot_word(F,F);
word->xt = xt; set_word_xt(word,compiled);
word->compiledp = T;
dpush(tag_object(word)); dpush(tag_object(word));
} }
@ -344,13 +361,8 @@ DEFINE_PRIMITIVE(finalize_compile)
{ {
F_ARRAY *pair = untag_array(array_nth(array,i)); F_ARRAY *pair = untag_array(array_nth(array,i));
F_WORD *word = untag_word(array_nth(pair,0)); F_WORD *word = untag_word(array_nth(pair,0));
XT xt = untag_word(array_nth(pair,1))->xt; F_COMPILED *compiled = untag_word(array_nth(pair,1))->code;
F_BLOCK *block = xt_to_block(xt); set_word_xt(word,compiled);
if(block->status != B_ALLOCATED)
critical_error("bad XT",(CELL)xt);
word->xt = xt;
word->compiledp = T;
} }
/* perform relocation */ /* perform relocation */
@ -358,7 +370,6 @@ DEFINE_PRIMITIVE(finalize_compile)
{ {
F_ARRAY *pair = untag_array(array_nth(array,i)); F_ARRAY *pair = untag_array(array_nth(array,i));
F_WORD *word = untag_word(array_nth(pair,0)); F_WORD *word = untag_word(array_nth(pair,0));
XT xt = word->xt; iterate_code_heap_step(word->code,finalize_code_block);
iterate_code_heap_step(xt_to_compiled(xt),finalize_code_block);
} }
} }

View File

@ -9,6 +9,8 @@ typedef enum {
RT_DISPATCH, RT_DISPATCH,
/* a compiled word reference */ /* a compiled word reference */
RT_XT, RT_XT,
/* a compiled word reference, pointing at the profiling prologue */
RT_XT_PROFILING,
/* a local label */ /* a local label */
RT_LABEL RT_LABEL
} F_RELTYPE; } F_RELTYPE;
@ -57,7 +59,9 @@ void relocate_code_block(F_COMPILED *relocating, CELL code_start,
void finalize_code_block(F_COMPILED *relocating, CELL code_start, void finalize_code_block(F_COMPILED *relocating, CELL code_start,
CELL reloc_start, CELL literals_start, CELL words_start, CELL words_end); CELL reloc_start, CELL literals_start, CELL words_start, CELL words_end);
XT add_compiled_block( void set_word_xt(F_WORD *word, F_COMPILED *compiled);
F_COMPILED *add_compiled_block(
CELL type, CELL type,
F_ARRAY *code, F_ARRAY *code,
F_ARRAY *labels, F_ARRAY *labels,

View File

@ -386,7 +386,7 @@ void collect_stack_frame(F_STACK_FRAME *frame)
} }
if(collecting_code) if(collecting_code)
recursive_mark(frame->xt); recursive_mark(compiled_to_block(frame_code(frame)));
} }
/* The base parameter allows us to adjust for a heap-allocated /* The base parameter allows us to adjust for a heap-allocated
@ -402,9 +402,6 @@ void collect_callstack(F_CONTEXT *stacks)
the user environment and extra roots registered with REGISTER_ROOT */ the user environment and extra roots registered with REGISTER_ROOT */
void collect_roots(void) void collect_roots(void)
{ {
int i;
F_CONTEXT *stacks;
copy_handle(&T); copy_handle(&T);
copy_handle(&bignum_zero); copy_handle(&bignum_zero);
copy_handle(&bignum_pos_one); copy_handle(&bignum_pos_one);
@ -413,7 +410,7 @@ void collect_roots(void)
collect_stack(extra_roots_region,extra_roots); collect_stack(extra_roots_region,extra_roots);
save_stacks(); save_stacks();
stacks = stack_chain; F_CONTEXT *stacks = stack_chain;
while(stacks) while(stacks)
{ {
@ -428,6 +425,7 @@ void collect_roots(void)
stacks = stacks->next; stacks = stacks->next;
} }
int i;
for(i = 0; i < USER_ENV; i++) for(i = 0; i < USER_ENV; i++)
copy_handle(&userenv[i]); copy_handle(&userenv[i]);
} }
@ -517,13 +515,13 @@ CELL binary_payload_start(CELL pointer)
return 0; return 0;
/* these objects have some binary data at the end */ /* these objects have some binary data at the end */
case WORD_TYPE: case WORD_TYPE:
return sizeof(F_WORD) - CELLS; return sizeof(F_WORD) - CELLS * 2;
case ALIEN_TYPE: case ALIEN_TYPE:
return CELLS * 3; return CELLS * 3;
case DLL_TYPE: case DLL_TYPE:
return CELLS * 2; return CELLS * 2;
case QUOTATION_TYPE: case QUOTATION_TYPE:
return sizeof(F_QUOTATION) - CELLS; return sizeof(F_QUOTATION) - CELLS * 2;
/* everything else consists entirely of pointers */ /* everything else consists entirely of pointers */
default: default:
return unaligned_object_size(pointer); return unaligned_object_size(pointer);
@ -549,12 +547,12 @@ CELL collect_next(CELL scan)
case WORD_TYPE: case WORD_TYPE:
word = (F_WORD *)scan; word = (F_WORD *)scan;
if(collecting_code && word->compiledp != F) if(collecting_code && word->compiledp != F)
recursive_mark(word->xt); recursive_mark(compiled_to_block(word->code));
break; break;
case QUOTATION_TYPE: case QUOTATION_TYPE:
quot = (F_QUOTATION *)scan; quot = (F_QUOTATION *)scan;
if(collecting_code && quot->xt != lazy_jit_compile) if(collecting_code && quot->compiledp != F)
recursive_mark(quot->xt); recursive_mark(compiled_to_block(quot->code));
break; break;
case CALLSTACK_TYPE: case CALLSTACK_TYPE:
stack = (F_CALLSTACK *)scan; stack = (F_CALLSTACK *)scan;

View File

@ -192,6 +192,7 @@ void dump_generations(void)
void dump_objects(F_FIXNUM type) void dump_objects(F_FIXNUM type)
{ {
data_gc();
begin_scan(); begin_scan();
CELL obj; CELL obj;

View File

@ -14,6 +14,10 @@ void critical_error(char* msg, CELL tagged)
} }
void throw_error(CELL error, F_STACK_FRAME *callstack_top) void throw_error(CELL error, F_STACK_FRAME *callstack_top)
{
/* If the error handler is set, we rewind any C stack frames and
pass the error to user-space. */
if(userenv[BREAK_ENV] != F)
{ {
/* If error was thrown during heap scan, we re-enable the GC */ /* If error was thrown during heap scan, we re-enable the GC */
gc_off = false; gc_off = false;
@ -27,10 +31,6 @@ void throw_error(CELL error, F_STACK_FRAME *callstack_top)
dpush(error); dpush(error);
/* If the error handler is set, we rewind any C stack frames and
pass the error to user-space. */
if(userenv[BREAK_ENV] != F)
{
/* Errors thrown from C code pass NULL for this parameter. /* Errors thrown from C code pass NULL for this parameter.
Errors thrown from Factor code, or signal handlers, pass the Errors thrown from Factor code, or signal handlers, pass the
actual stack pointer at the time, since the saved pointer is actual stack pointer at the time, since the saved pointer is

View File

@ -43,8 +43,6 @@ void init_factor(F_PARAMETERS *p)
/* Disable GC during init as a sanity check */ /* Disable GC during init as a sanity check */
gc_off = true; gc_off = true;
profiling = false;
early_init(); early_init();
if(p->image == NULL) if(p->image == NULL)
@ -145,6 +143,7 @@ void init_factor_from_args(F_CHAR *image, int argc, F_CHAR **argv, bool embedded
for(i = 0; i < argc; i++) for(i = 0; i < argc; i++)
free(posix_argv[i]); free(posix_argv[i]);
free(posix_argv);
} }
char *factor_eval_string(char *string) char *factor_eval_string(char *string)

View File

@ -146,6 +146,7 @@ DEFINE_PRIMITIVE(save_image_and_exit)
/* do a full GC + code heap compaction */ /* do a full GC + code heap compaction */
compact_code_heap(); compact_code_heap();
/* Save the image */
save_image(unbox_native_string()); save_image(unbox_native_string());
/* now exit; we cannot continue executing like this */ /* now exit; we cannot continue executing like this */
@ -159,15 +160,21 @@ void fixup_word(F_WORD *word)
if(word->compiledp == F) if(word->compiledp == F)
word->xt = default_word_xt(word); word->xt = default_word_xt(word);
else else
code_fixup(&word->xt); {
code_fixup((CELL)&word->xt);
code_fixup((CELL)&word->code);
}
} }
void fixup_quotation(F_QUOTATION *quot) void fixup_quotation(F_QUOTATION *quot)
{ {
if(quot->compiled == F) if(quot->compiledp == F)
quot->xt = lazy_jit_compile; quot->xt = lazy_jit_compile;
else else
code_fixup(&quot->xt); {
code_fixup((CELL)&quot->xt);
code_fixup((CELL)&quot->code);
}
} }
void fixup_alien(F_ALIEN *d) void fixup_alien(F_ALIEN *d)
@ -177,7 +184,7 @@ void fixup_alien(F_ALIEN *d)
void fixup_stack_frame(F_STACK_FRAME *frame) void fixup_stack_frame(F_STACK_FRAME *frame)
{ {
code_fixup(&frame->xt); code_fixup((CELL)&frame->xt);
if(frame_type(frame) == QUOTATION_TYPE) if(frame_type(frame) == QUOTATION_TYPE)
{ {
@ -186,7 +193,7 @@ void fixup_stack_frame(F_STACK_FRAME *frame)
frame->scan = scan + frame->array; frame->scan = scan + frame->array;
} }
code_fixup(&FRAME_RETURN_ADDRESS(frame)); code_fixup((CELL)&FRAME_RETURN_ADDRESS(frame));
} }
void fixup_callstack_object(F_CALLSTACK *stack) void fixup_callstack_object(F_CALLSTACK *stack)
@ -258,14 +265,17 @@ void fixup_code_block(F_COMPILED *relocating, CELL code_start,
for(scan = words_start; scan < words_end; scan += CELLS) for(scan = words_start; scan < words_end; scan += CELLS)
{ {
if(relocating->finalized) if(relocating->finalized)
code_fixup((XT*)scan); code_fixup(scan);
else else
data_fixup((CELL*)scan); data_fixup((CELL*)scan);
} }
if(reloc_start != literals_start)
{
relocate_code_block(relocating,code_start,reloc_start, relocate_code_block(relocating,code_start,reloc_start,
literals_start,words_start,words_end); literals_start,words_start,words_end);
} }
}
void relocate_code() void relocate_code()
{ {

View File

@ -55,11 +55,10 @@ INLINE void data_fixup(CELL *cell)
CELL code_relocation_base; CELL code_relocation_base;
INLINE void code_fixup(XT *cell) INLINE void code_fixup(CELL cell)
{ {
CELL value = (CELL)*cell; CELL value = get(cell);
value += (code_heap.segment->start - code_relocation_base); put(cell,value + (code_heap.segment->start - code_relocation_base));
*cell = (XT)value;
} }
void relocate_data(); void relocate_data();

View File

@ -144,6 +144,18 @@ typedef struct {
CELL array; CELL array;
} F_HASHTABLE; } F_HASHTABLE;
/* The compiled code heap is structured into blocks. */
typedef struct
{
CELL type; /* this is WORD_TYPE or QUOTATION_TYPE */
CELL code_length; /* # bytes */
CELL reloc_length; /* # bytes */
CELL literals_length; /* # bytes */
CELL words_length; /* # bytes */
CELL finalized; /* has finalize_code_block() been called on this yet? */
CELL padding[2];
} F_COMPILED;
/* Assembly code makes assumptions about the layout of this struct */ /* Assembly code makes assumptions about the layout of this struct */
typedef struct { typedef struct {
/* TAGGED header */ /* TAGGED header */
@ -164,6 +176,8 @@ typedef struct {
CELL counter; CELL counter;
/* UNTAGGED execution token: jump here to execute word */ /* UNTAGGED execution token: jump here to execute word */
XT xt; XT xt;
/* UNTAGGED compiled code block */
F_COMPILED *code;
} F_WORD; } F_WORD;
/* Assembly code makes assumptions about the layout of this struct */ /* Assembly code makes assumptions about the layout of this struct */
@ -195,9 +209,11 @@ typedef struct {
/* tagged */ /* tagged */
CELL array; CELL array;
/* tagged */ /* tagged */
CELL compiled; CELL compiledp;
/* untagged */ /* UNTAGGED */
XT xt; XT xt;
/* UNTAGGED compiled code block */
F_COMPILED *code;
} F_QUOTATION; } F_QUOTATION;
/* Assembly code makes assumptions about the layout of this struct */ /* Assembly code makes assumptions about the layout of this struct */

View File

@ -7,7 +7,7 @@ Used under BSD license with permission from Paolo Bonzini and Bruno Haible,
http://sourceforge.net/mailarchive/message.php?msg_name=200503102200.32002.bruno%40clisp.org http://sourceforge.net/mailarchive/message.php?msg_name=200503102200.32002.bruno%40clisp.org
Extensively modified for Factor - portions copyright (C) 2004-2007 Slava Pestov */ Modified for Factor by Slava Pestov */
#include "master.h" #include "master.h"
@ -37,6 +37,8 @@ static void call_fault_handler(exception_type_t exception,
else else
signal_callstack_top = NULL; signal_callstack_top = NULL;
MACH_STACK_POINTER(thread_state) = fix_stack_pointer(MACH_STACK_POINTER(thread_state));
/* Now we point the program counter at the right handler function. */ /* Now we point the program counter at the right handler function. */
if(exception == EXC_BAD_ACCESS) if(exception == EXC_BAD_ACCESS)
{ {

View File

@ -1,3 +1,13 @@
/* Fault handler information. MacOSX version.
Copyright (C) 1993-1999, 2002-2003 Bruno Haible <clisp.org at bruno>
Copyright (C) 2003 Paolo Bonzini <gnu.org at bonzini>
Used under BSD license with permission from Paolo Bonzini and Bruno Haible,
2005-03-10:
http://sourceforge.net/mailarchive/message.php?msg_name=200503102200.32002.bruno%40clisp.org
Modified for Factor by Slava Pestov */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>

View File

@ -22,6 +22,7 @@
#include "primitives.h" #include "primitives.h"
#include "debug.h" #include "debug.h"
#include "run.h" #include "run.h"
#include "profiler.h"
#include "errors.h" #include "errors.h"
#include "bignumint.h" #include "bignumint.h"
#include "bignum.h" #include "bignum.h"

View File

@ -1,3 +1,13 @@
/* Fault handler information. MacOSX version.
Copyright (C) 1993-1999, 2002-2003 Bruno Haible <clisp.org at bruno>
Copyright (C) 2003 Paolo Bonzini <gnu.org at bonzini>
Used under BSD license with permission from Paolo Bonzini and Bruno Haible,
2005-03-10:
http://sourceforge.net/mailarchive/message.php?msg_name=200503102200.32002.bruno%40clisp.org
Modified for Factor by Slava Pestov */
#define FRAME_RETURN_ADDRESS(frame) *((XT *)(frame_successor(frame) + 1) + 2) #define FRAME_RETURN_ADDRESS(frame) *((XT *)(frame_successor(frame) + 1) + 2)
#define MACH_EXC_STATE_TYPE ppc_exception_state_t #define MACH_EXC_STATE_TYPE ppc_exception_state_t
@ -20,3 +30,8 @@
#define UAP_PROGRAM_COUNTER(ucontext) \ #define UAP_PROGRAM_COUNTER(ucontext) \
MACH_PROGRAM_COUNTER(&(((ucontext_t *)(ucontext))->uc_mcontext->ss)) MACH_PROGRAM_COUNTER(&(((ucontext_t *)(ucontext))->uc_mcontext->ss))
#endif #endif
INLINE CELL fix_stack_pointer(CELL sp)
{
return sp;
}

View File

@ -1,3 +1,13 @@
/* Fault handler information. MacOSX version.
Copyright (C) 1993-1999, 2002-2003 Bruno Haible <clisp.org at bruno>
Copyright (C) 2003 Paolo Bonzini <gnu.org at bonzini>
Used under BSD license with permission from Paolo Bonzini and Bruno Haible,
2005-03-10:
http://sourceforge.net/mailarchive/message.php?msg_name=200503102200.32002.bruno%40clisp.org
Modified for Factor by Slava Pestov */
#define MACH_EXC_STATE_TYPE i386_exception_state_t #define MACH_EXC_STATE_TYPE i386_exception_state_t
#define MACH_EXC_STATE_FLAVOR i386_EXCEPTION_STATE #define MACH_EXC_STATE_FLAVOR i386_EXCEPTION_STATE
#define MACH_EXC_STATE_COUNT i386_EXCEPTION_STATE_COUNT #define MACH_EXC_STATE_COUNT i386_EXCEPTION_STATE_COUNT
@ -18,3 +28,8 @@
#define UAP_PROGRAM_COUNTER(ucontext) \ #define UAP_PROGRAM_COUNTER(ucontext) \
MACH_PROGRAM_COUNTER(&(((ucontext_t *)(ucontext))->uc_mcontext->ss)) MACH_PROGRAM_COUNTER(&(((ucontext_t *)(ucontext))->uc_mcontext->ss))
#endif #endif
INLINE CELL fix_stack_pointer(CELL sp)
{
return ((sp + 4) & ~15) - 4;
}

View File

@ -1,19 +0,0 @@
.text
.globl c_to_factor_toplevel
.word exception_handler
.word 0
c_to_factor_toplevel:
ldr pc, _Pc_to_factor
_Pc_to_factor:
.word c_to_factor
.section .pdata
.word c_to_factor_toplevel
.word 0xc0000002 | (0xFFFFF << 8)

60
vm/profiler.c Normal file
View File

@ -0,0 +1,60 @@
#include "master.h"
bool profiling_p(void)
{
return to_boolean(userenv[PROFILING_ENV]);
}
F_FIXNUM profiler_prologue(void)
{
return to_fixnum(userenv[PROFILER_PROLOGUE_ENV]);
}
void profiling_word(F_WORD *word)
{
/* If we just enabled the profiler, reset call count */
if(profiling_p())
word->counter = tag_fixnum(0);
if(word->compiledp == F)
{
if(type_of(word->def) == QUOTATION_TYPE)
word->xt = default_word_xt(word);
}
else
set_word_xt(word,word->code);
}
void set_profiling(bool profiling)
{
if(profiling == profiling_p())
return;
userenv[PROFILING_ENV] = tag_boolean(profiling);
/* Push everything to tenured space so that we can heap scan */
data_gc();
/* Step 1 - Update word XTs and saved callstack objects */
begin_scan();
CELL obj;
while((obj = next_object()) != F)
{
if(type_of(obj) == WORD_TYPE)
profiling_word(untag_object(obj));
}
gc_off = false; /* end heap scan */
/* Step 2 - Update XTs in code heap */
iterate_code_heap(relocate_code_block);
/* Step 3 - flush instruction cache */
flush_icache(code_heap.segment->start,code_heap.segment->size);
}
DEFINE_PRIMITIVE(profiling)
{
set_profiling(to_boolean(dpop()));
}

3
vm/profiler.h Normal file
View File

@ -0,0 +1,3 @@
bool profiling_p(void);
F_FIXNUM profiler_prologue(void);
DECLARE_PRIMITIVE(profiling);

View File

@ -37,6 +37,13 @@ bool jit_stack_frame_p(F_ARRAY *array)
return false; return false;
} }
void set_quot_xt(F_QUOTATION *quot, F_COMPILED *code)
{
quot->code = code;
quot->xt = (XT)(code + 1);
quot->compiledp = T;
}
void jit_compile(F_QUOTATION *quot) void jit_compile(F_QUOTATION *quot)
{ {
F_ARRAY *array = untag_object(quot->array); F_ARRAY *array = untag_object(quot->array);
@ -148,12 +155,11 @@ void jit_compile(F_QUOTATION *quot)
F_ARRAY *literals = allot_array(ARRAY_TYPE,1,tag_object(quot)); F_ARRAY *literals = allot_array(ARRAY_TYPE,1,tag_object(quot));
UNREGISTER_UNTAGGED(result); UNREGISTER_UNTAGGED(result);
XT xt = add_compiled_block(QUOTATION_TYPE,result,NULL,NULL,NULL,literals); F_COMPILED *compiled = add_compiled_block(QUOTATION_TYPE,result,NULL,NULL,NULL,literals);
iterate_code_heap_step(xt_to_compiled(xt),finalize_code_block); iterate_code_heap_step(compiled,finalize_code_block);
UNREGISTER_UNTAGGED(quot); UNREGISTER_UNTAGGED(quot);
quot->xt = xt; set_quot_xt(quot,compiled);
quot->compiled = T;
} }
F_FASTCALL CELL primitive_jit_compile(CELL tagged, F_STACK_FRAME *stack) F_FASTCALL CELL primitive_jit_compile(CELL tagged, F_STACK_FRAME *stack)
@ -222,7 +228,7 @@ DEFINE_PRIMITIVE(array_to_quotation)
F_QUOTATION *quot = allot_object(QUOTATION_TYPE,sizeof(F_QUOTATION)); F_QUOTATION *quot = allot_object(QUOTATION_TYPE,sizeof(F_QUOTATION));
quot->array = dpeek(); quot->array = dpeek();
quot->xt = lazy_jit_compile; quot->xt = lazy_jit_compile;
quot->compiled = F; quot->compiledp = F;
drepl(tag_object(quot)); drepl(tag_object(quot));
} }
@ -234,6 +240,7 @@ DEFINE_PRIMITIVE(quotation_xt)
DEFINE_PRIMITIVE(strip_compiled_quotations) DEFINE_PRIMITIVE(strip_compiled_quotations)
{ {
data_gc();
begin_scan(); begin_scan();
CELL obj; CELL obj;
@ -242,7 +249,7 @@ DEFINE_PRIMITIVE(strip_compiled_quotations)
if(type_of(obj) == QUOTATION_TYPE) if(type_of(obj) == QUOTATION_TYPE)
{ {
F_QUOTATION *quot = untag_object(obj); F_QUOTATION *quot = untag_object(obj);
quot->compiled = F; quot->compiledp = F;
quot->xt = lazy_jit_compile; quot->xt = lazy_jit_compile;
} }
} }

View File

@ -1,3 +1,4 @@
void set_quot_xt(F_QUOTATION *quot, F_COMPILED *code);
void jit_compile(F_QUOTATION *quot); void jit_compile(F_QUOTATION *quot);
F_FASTCALL CELL primitive_jit_compile(CELL tagged, F_STACK_FRAME *stack); F_FASTCALL CELL primitive_jit_compile(CELL tagged, F_STACK_FRAME *stack);
XT quot_offset_to_pc(F_QUOTATION *quot, F_FIXNUM offset); XT quot_offset_to_pc(F_QUOTATION *quot, F_FIXNUM offset);

View File

@ -269,7 +269,7 @@ XT default_word_xt(F_WORD *word)
return dosym; return dosym;
else if(type_of(word->def) == QUOTATION_TYPE) else if(type_of(word->def) == QUOTATION_TYPE)
{ {
if(profiling) if(profiling_p())
return docol_profiling; return docol_profiling;
else else
return docol; return docol;
@ -364,36 +364,3 @@ DEFINE_PRIMITIVE(set_slot)
CELL value = dpop(); CELL value = dpop();
set_slot(obj,slot,value); set_slot(obj,slot,value);
} }
void enable_word_profiling(F_WORD *word)
{
if(word->xt == docol)
word->xt = docol_profiling;
}
void disable_word_profiling(F_WORD *word)
{
if(word->xt == docol_profiling)
word->xt = docol;
}
DEFINE_PRIMITIVE(profiling)
{
profiling = to_boolean(dpop());
begin_scan();
CELL obj;
while((obj = next_object()) != F)
{
if(type_of(obj) == WORD_TYPE)
{
if(profiling)
enable_word_profiling(untag_object(obj));
else
disable_word_profiling(untag_object(obj));
}
}
gc_off = false; /* end heap scan */
}

View File

@ -1,6 +1,3 @@
/* Is profiling on? */
DLLEXPORT bool profiling;
#define USER_ENV 40 #define USER_ENV 40
typedef enum { typedef enum {
@ -52,6 +49,10 @@ typedef enum {
JIT_DISPATCH, JIT_DISPATCH,
JIT_EPILOG, JIT_EPILOG,
JIT_RETURN, JIT_RETURN,
/* Profiler support */
PROFILING_ENV = 38, /* is the profiler on? */
PROFILER_PROLOGUE_ENV /* length of optimizing compiler's profiler prologue */
} F_ENVTYPE; } F_ENVTYPE;
#define FIRST_SAVE_ENV BOOT_ENV #define FIRST_SAVE_ENV BOOT_ENV
@ -242,4 +243,3 @@ DECLARE_PRIMITIVE(tag);
DECLARE_PRIMITIVE(class_hash); DECLARE_PRIMITIVE(class_hash);
DECLARE_PRIMITIVE(slot); DECLARE_PRIMITIVE(slot);
DECLARE_PRIMITIVE(set_slot); DECLARE_PRIMITIVE(set_slot);
DECLARE_PRIMITIVE(profiling);