Working on inline caching for tail call sites
parent
cb4d8c7ea4
commit
581d017b46
|
@ -168,6 +168,7 @@ SYMBOL: pic-check-tag
|
|||
SYMBOL: pic-check
|
||||
SYMBOL: pic-hit
|
||||
SYMBOL: pic-miss-word
|
||||
SYMBOL: pic-miss-tail-word
|
||||
|
||||
! Megamorphic dispatch
|
||||
SYMBOL: mega-lookup
|
||||
|
@ -193,25 +194,26 @@ SYMBOL: undefined-quot
|
|||
{ jit-return 34 }
|
||||
{ jit-profiling 35 }
|
||||
{ jit-push-immediate 36 }
|
||||
{ jit-save-stack 38 }
|
||||
{ jit-dip-word 39 }
|
||||
{ jit-dip 40 }
|
||||
{ jit-2dip-word 41 }
|
||||
{ jit-2dip 42 }
|
||||
{ jit-3dip-word 43 }
|
||||
{ jit-3dip 44 }
|
||||
{ jit-execute-word 45 }
|
||||
{ jit-execute-jump 46 }
|
||||
{ jit-execute-call 47 }
|
||||
{ pic-load 48 }
|
||||
{ pic-tag 49 }
|
||||
{ pic-hi-tag 50 }
|
||||
{ pic-tuple 51 }
|
||||
{ pic-hi-tag-tuple 52 }
|
||||
{ pic-check-tag 53 }
|
||||
{ pic-check 54 }
|
||||
{ pic-hit 55 }
|
||||
{ pic-miss-word 56 }
|
||||
{ jit-save-stack 37 }
|
||||
{ jit-dip-word 38 }
|
||||
{ jit-dip 39 }
|
||||
{ jit-2dip-word 40 }
|
||||
{ jit-2dip 41 }
|
||||
{ jit-3dip-word 42 }
|
||||
{ jit-3dip 43 }
|
||||
{ jit-execute-word 44 }
|
||||
{ jit-execute-jump 45 }
|
||||
{ jit-execute-call 46 }
|
||||
{ pic-load 47 }
|
||||
{ pic-tag 48 }
|
||||
{ pic-hi-tag 49 }
|
||||
{ pic-tuple 50 }
|
||||
{ pic-hi-tag-tuple 51 }
|
||||
{ pic-check-tag 52 }
|
||||
{ pic-check 53 }
|
||||
{ pic-hit 54 }
|
||||
{ pic-miss-word 55 }
|
||||
{ pic-miss-tail-word 56 }
|
||||
{ mega-lookup 57 }
|
||||
{ mega-lookup-word 58 }
|
||||
{ mega-miss-word 59 }
|
||||
|
@ -351,7 +353,8 @@ M: f '
|
|||
[ vocabulary>> , ]
|
||||
[ def>> , ]
|
||||
[ props>> , ]
|
||||
[ direct-entry-def>> , ] ! direct-entry-def
|
||||
[ pic-def>> , ]
|
||||
[ pic-tail-def>> , ]
|
||||
[ drop 0 , ] ! count
|
||||
[ word-sub-primitive , ]
|
||||
[ drop 0 , ] ! xt
|
||||
|
@ -524,6 +527,7 @@ M: quotation '
|
|||
\ 3dip jit-3dip-word set
|
||||
\ (execute) jit-execute-word set
|
||||
\ inline-cache-miss \ pic-miss-word set
|
||||
\ inline-cache-miss-tail \ pic-miss-tail-word set
|
||||
\ mega-cache-lookup \ mega-lookup-word set
|
||||
\ mega-cache-miss \ mega-miss-word set
|
||||
[ undefined ] undefined-quot set
|
||||
|
@ -559,6 +563,7 @@ M: quotation '
|
|||
pic-check
|
||||
pic-hit
|
||||
pic-miss-word
|
||||
pic-miss-tail-word
|
||||
mega-lookup
|
||||
mega-lookup-word
|
||||
mega-miss-word
|
||||
|
|
|
@ -59,6 +59,9 @@ SYMBOL: literal-table
|
|||
: rel-word-pic ( word class -- )
|
||||
[ add-literal ] dip rt-xt-pic rel-fixup ;
|
||||
|
||||
: rel-word-pic-tail ( word class -- )
|
||||
[ add-literal ] dip rt-xt-pic-tail rel-fixup ;
|
||||
|
||||
: rel-primitive ( word class -- )
|
||||
[ def>> first add-literal ] dip rt-primitive rel-fixup ;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! Copyright (C) 2008, 2009 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: math kernel layouts system strings words quotations byte-arrays
|
||||
alien arrays ;
|
||||
alien arrays literals sequences ;
|
||||
IN: compiler.constants
|
||||
|
||||
! These constants must match vm/memory.h
|
||||
|
@ -14,14 +14,14 @@ CONSTANT: deck-bits 18
|
|||
: float-offset ( -- n ) 8 float tag-number - ; inline
|
||||
: string-offset ( -- n ) 4 bootstrap-cells string tag-number - ; inline
|
||||
: string-aux-offset ( -- n ) 2 bootstrap-cells string tag-number - ; inline
|
||||
: profile-count-offset ( -- n ) 7 bootstrap-cells \ word tag-number - ; inline
|
||||
: profile-count-offset ( -- n ) 8 bootstrap-cells \ word tag-number - ; inline
|
||||
: byte-array-offset ( -- n ) 2 bootstrap-cells byte-array tag-number - ; inline
|
||||
: alien-offset ( -- n ) 3 bootstrap-cells alien tag-number - ; inline
|
||||
: underlying-alien-offset ( -- n ) bootstrap-cell alien tag-number - ; inline
|
||||
: tuple-class-offset ( -- n ) bootstrap-cell tuple tag-number - ; inline
|
||||
: word-xt-offset ( -- n ) 9 bootstrap-cells \ word tag-number - ; inline
|
||||
: word-xt-offset ( -- n ) 10 bootstrap-cells \ word tag-number - ; inline
|
||||
: quot-xt-offset ( -- n ) 5 bootstrap-cells quotation tag-number - ; inline
|
||||
: word-code-offset ( -- n ) 10 bootstrap-cells \ word tag-number - ; inline
|
||||
: word-code-offset ( -- n ) 11 bootstrap-cells \ word tag-number - ; inline
|
||||
: array-start-offset ( -- n ) 2 bootstrap-cells array tag-number - ; inline
|
||||
: compiled-header-size ( -- n ) 4 bootstrap-cells ; inline
|
||||
|
||||
|
@ -43,14 +43,12 @@ CONSTANT: rt-dlsym 1
|
|||
CONSTANT: rt-dispatch 2
|
||||
CONSTANT: rt-xt 3
|
||||
CONSTANT: rt-xt-pic 4
|
||||
CONSTANT: rt-here 5
|
||||
CONSTANT: rt-this 6
|
||||
CONSTANT: rt-immediate 7
|
||||
CONSTANT: rt-stack-chain 8
|
||||
CONSTANT: rt-untagged 9
|
||||
CONSTANT: rt-xt-pic-tail 5
|
||||
CONSTANT: rt-here 6
|
||||
CONSTANT: rt-this 7
|
||||
CONSTANT: rt-immediate 8
|
||||
CONSTANT: rt-stack-chain 9
|
||||
CONSTANT: rt-untagged 10
|
||||
|
||||
: rc-absolute? ( n -- ? )
|
||||
[ rc-absolute-ppc-2/2 = ]
|
||||
[ rc-absolute-cell = ]
|
||||
[ rc-absolute = ]
|
||||
tri or or ;
|
||||
${ rc-absolute-ppc-2/2 rc-absolute-cell rc-absolute } member? ;
|
||||
|
|
|
@ -114,7 +114,11 @@ M: ppc stack-frame-size ( stack-frame -- i )
|
|||
4 cells align ;
|
||||
|
||||
M: ppc %call ( word -- ) 0 BL rc-relative-ppc-3 rel-word-pic ;
|
||||
M: ppc %jump ( word -- ) 0 B rc-relative-ppc-3 rel-word ;
|
||||
|
||||
M: ppc %jump ( word -- )
|
||||
0 3 LOAD32 rc-absolute-ppc-2/2 rel-here
|
||||
0 B rc-relative-ppc-3 rel-word-pic-tail ;
|
||||
|
||||
M: ppc %jump-label ( label -- ) B ;
|
||||
M: ppc %return ( -- ) BLR ;
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ M:: x86.32 %dispatch ( src temp offset -- )
|
|||
M: x86.32 param-reg-1 EAX ;
|
||||
M: x86.32 param-reg-2 EDX ;
|
||||
|
||||
M: x86.32 pic-tail-reg EBX ;
|
||||
|
||||
M: x86.32 reserved-area-size 0 ;
|
||||
|
||||
M: x86.32 %alien-invoke 0 CALL rc-relative rel-dlsym ;
|
||||
|
|
|
@ -39,6 +39,8 @@ M: x86.64 param-reg-1 int-regs param-regs first ;
|
|||
M: x86.64 param-reg-2 int-regs param-regs second ;
|
||||
: param-reg-3 ( -- reg ) int-regs param-regs third ; inline
|
||||
|
||||
M: x86.64 pic-tail-reg RBX ;
|
||||
|
||||
M: int-regs return-reg drop RAX ;
|
||||
M: float-regs return-reg drop XMM0 ;
|
||||
|
||||
|
|
|
@ -152,6 +152,8 @@ big-endian off
|
|||
|
||||
! ! ! Polymorphic inline caches
|
||||
|
||||
! The PIC and megamorphic code stubs are not permitted to touch temp3.
|
||||
|
||||
! Load a value from a stack position
|
||||
[
|
||||
temp1 ds-reg HEX: ffffffff [+] MOV rc-absolute rt-untagged jit-rel
|
||||
|
|
|
@ -23,6 +23,8 @@ HOOK: temp-reg-2 cpu ( -- reg )
|
|||
HOOK: param-reg-1 cpu ( -- reg )
|
||||
HOOK: param-reg-2 cpu ( -- reg )
|
||||
|
||||
HOOK: pic-tail-reg cpu ( -- reg )
|
||||
|
||||
M: x86 %load-immediate MOV ;
|
||||
|
||||
M: x86 %load-reference swap 0 MOV rc-absolute-cell rel-immediate ;
|
||||
|
@ -58,8 +60,13 @@ M: x86 stack-frame-size ( stack-frame -- i )
|
|||
align-stack ;
|
||||
|
||||
M: x86 %call ( word -- ) 0 CALL rc-relative rel-word-pic ;
|
||||
M: x86 %jump ( word -- ) 0 JMP rc-relative rel-word ;
|
||||
|
||||
M: x86 %jump ( word -- )
|
||||
pic-tail-reg 0 MOV 2 cells 1 + rc-absolute-cell rel-here
|
||||
0 JMP rc-relative rel-word-pic-tail ;
|
||||
|
||||
M: x86 %jump-label ( label -- ) 0 JMP rc-relative label-fixup ;
|
||||
|
||||
M: x86 %return ( -- ) 0 RET ;
|
||||
|
||||
: code-alignment ( align -- n )
|
||||
|
|
|
@ -231,7 +231,8 @@ bi
|
|||
"vocabulary"
|
||||
{ "def" { "quotation" "quotations" } initial: [ ] }
|
||||
"props"
|
||||
{ "direct-entry-def" }
|
||||
"pic-def"
|
||||
"pic-tail-def"
|
||||
{ "counter" { "fixnum" "math" } }
|
||||
{ "sub-primitive" read-only }
|
||||
} define-builtin
|
||||
|
@ -505,6 +506,7 @@ tuple
|
|||
{ "load-locals" "locals.backend" (( ... n -- )) }
|
||||
{ "check-datastack" "kernel.private" (( array in# out# -- ? )) }
|
||||
{ "inline-cache-miss" "generic.single.private" (( generic methods index cache -- )) }
|
||||
{ "inline-cache-miss-tail" "generic.single.private" (( generic methods index cache -- )) }
|
||||
{ "mega-cache-miss" "generic.single.private" (( methods index cache -- method )) }
|
||||
{ "lookup-method" "generic.single.private" (( object methods -- method )) }
|
||||
{ "reset-dispatch-stats" "generic.single" (( -- )) }
|
||||
|
|
|
@ -17,8 +17,6 @@ M: hook-combination picker
|
|||
|
||||
M: hook-combination dispatch# drop 0 ;
|
||||
|
||||
M: hook-combination inline-cache-quot 2drop f ;
|
||||
|
||||
M: hook-combination mega-cache-quot
|
||||
1quotation picker [ lookup-method (execute) ] surround ;
|
||||
|
||||
|
|
|
@ -273,5 +273,5 @@ M: growable call-next-hooker call-next-method "growable " prepend ;
|
|||
[ ] [ "IN: generic.single.tests GENERIC: xyz ( a -- b )" eval( -- ) ] unit-test
|
||||
[ ] [ "IN: generic.single.tests MATH: xyz ( a b -- c )" eval( -- ) ] unit-test
|
||||
|
||||
[ f ] [ "xyz" "generic.single.tests" lookup direct-entry-def>> ] unit-test
|
||||
[ f ] [ "xyz" "generic.single.tests" lookup pic-def>> ] unit-test
|
||||
[ f ] [ "xyz" "generic.single.tests" lookup "decision-tree" word-prop ] unit-test
|
|
@ -238,10 +238,14 @@ M: f compile-engine ;
|
|||
[ <engine> compile-engine ] bi
|
||||
] tri ;
|
||||
|
||||
HOOK: inline-cache-quot combination ( word methods -- quot/f )
|
||||
HOOK: inline-cache-quots combination ( word methods -- pic-quot/f pic-tail-quot/f )
|
||||
|
||||
M: single-combination inline-cache-quots 2drop f f ;
|
||||
|
||||
: define-inline-cache-quot ( word methods -- )
|
||||
[ drop ] [ inline-cache-quot ] 2bi >>direct-entry-def drop ;
|
||||
[ drop ] [ inline-cache-quots ] 2bi
|
||||
[ >>pic-def ] [ >>pic-tail-def ] bi*
|
||||
drop ;
|
||||
|
||||
HOOK: mega-cache-quot combination ( methods -- quot/f )
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
USING: accessors definitions generic generic.single kernel
|
||||
namespaces words math math.order combinators sequences
|
||||
generic.single.private quotations kernel.private
|
||||
assocs arrays layouts ;
|
||||
assocs arrays layouts make ;
|
||||
IN: generic.standard
|
||||
|
||||
TUPLE: standard-combination < single-combination # ;
|
||||
|
@ -38,17 +38,22 @@ M: standard-generic effective-method
|
|||
[ datastack ] dip [ "combination" word-prop #>> swap <reversed> nth ] keep
|
||||
(effective-method) ;
|
||||
|
||||
M: standard-combination inline-cache-quot ( word methods -- )
|
||||
: inline-cache-quot ( word methods miss-word -- quot )
|
||||
[ [ literalize , ] [ , ] [ combination get #>> , { } , , ] tri* ] [ ] make ;
|
||||
|
||||
M: standard-combination inline-cache-quots
|
||||
#! Direct calls to the generic word (not tail calls or indirect calls)
|
||||
#! will jump to the inline cache entry point instead of the megamorphic
|
||||
#! dispatch entry point.
|
||||
combination get #>> [ { } inline-cache-miss ] 3curry [ ] like ;
|
||||
[ \ inline-cache-miss inline-cache-quot ]
|
||||
[ \ inline-cache-miss-tail inline-cache-quot ]
|
||||
2bi ;
|
||||
|
||||
: make-empty-cache ( -- array )
|
||||
mega-cache-size get f <array> ;
|
||||
|
||||
M: standard-combination mega-cache-quot
|
||||
combination get #>> make-empty-cache [ mega-cache-lookup ] 3curry [ ] like ;
|
||||
combination get #>> make-empty-cache \ mega-cache-lookup [ ] 4sequence ;
|
||||
|
||||
M: standard-generic definer drop \ GENERIC# f ;
|
||||
|
||||
|
|
|
@ -155,7 +155,8 @@ M: word reset-word
|
|||
[ subwords forget-all ]
|
||||
[ reset-word ]
|
||||
[
|
||||
f >>direct-entry-def
|
||||
f >>pic-def
|
||||
f >>pic-tail-def
|
||||
{
|
||||
"methods"
|
||||
"combination"
|
||||
|
|
|
@ -27,7 +27,8 @@ void iterate_relocations(code_block *compiled, relocation_iterator iter)
|
|||
{
|
||||
case RT_PRIMITIVE:
|
||||
case RT_XT:
|
||||
case RT_XT_DIRECT:
|
||||
case RT_XT_PIC:
|
||||
case RT_XT_PIC_TAIL:
|
||||
case RT_IMMEDIATE:
|
||||
case RT_HERE:
|
||||
case RT_UNTAGGED:
|
||||
|
@ -171,9 +172,8 @@ void *object_xt(cell obj)
|
|||
}
|
||||
}
|
||||
|
||||
void *word_direct_xt(word *w)
|
||||
static void *xt_pic(word *w, cell tagged_quot)
|
||||
{
|
||||
cell tagged_quot = w->direct_entry_def;
|
||||
if(tagged_quot == F || max_pic_size == 0)
|
||||
return w->xt;
|
||||
else
|
||||
|
@ -186,20 +186,42 @@ void *word_direct_xt(word *w)
|
|||
}
|
||||
}
|
||||
|
||||
void *word_xt_pic(word *w)
|
||||
{
|
||||
return xt_pic(w,w->pic_def);
|
||||
}
|
||||
|
||||
void *word_xt_pic_tail(word *w)
|
||||
{
|
||||
return xt_pic(w,w->pic_tail_def);
|
||||
}
|
||||
|
||||
void update_word_references_step(relocation_entry rel, cell index, code_block *compiled)
|
||||
{
|
||||
relocation_type type = REL_TYPE(rel);
|
||||
if(type == RT_XT || type == RT_XT_DIRECT)
|
||||
if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL)
|
||||
{
|
||||
cell offset = REL_OFFSET(rel) + (cell)(compiled + 1);
|
||||
array *literals = untag<array>(compiled->literals);
|
||||
cell obj = array_nth(literals,index);
|
||||
|
||||
void *xt;
|
||||
if(type == RT_XT)
|
||||
switch(type)
|
||||
{
|
||||
case RT_XT:
|
||||
xt = object_xt(obj);
|
||||
else
|
||||
xt = word_direct_xt(untag<word>(obj));
|
||||
break;
|
||||
case RT_XT_PIC:
|
||||
xt = word_xt_pic(untag<word>(obj));
|
||||
break;
|
||||
case RT_XT_PIC_TAIL:
|
||||
xt = word_xt_pic_tail(untag<word>(obj));
|
||||
break;
|
||||
default:
|
||||
critical_error("Oops",type);
|
||||
xt = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
store_address_in_code_block(REL_CLASS(rel),offset,(cell)xt);
|
||||
}
|
||||
|
@ -367,25 +389,30 @@ void relocate_code_block_step(relocation_entry rel, cell index, code_block *comp
|
|||
array *literals = untag<array>(compiled->literals);
|
||||
fixnum absolute_value;
|
||||
|
||||
#define ARG array_nth(literals,index)
|
||||
|
||||
switch(REL_TYPE(rel))
|
||||
{
|
||||
case RT_PRIMITIVE:
|
||||
absolute_value = (cell)primitives[untag_fixnum(array_nth(literals,index))];
|
||||
absolute_value = (cell)primitives[untag_fixnum(ARG)];
|
||||
break;
|
||||
case RT_DLSYM:
|
||||
absolute_value = (cell)get_rel_symbol(literals,index);
|
||||
break;
|
||||
case RT_IMMEDIATE:
|
||||
absolute_value = array_nth(literals,index);
|
||||
absolute_value = ARG;
|
||||
break;
|
||||
case RT_XT:
|
||||
absolute_value = (cell)object_xt(array_nth(literals,index));
|
||||
absolute_value = (cell)object_xt(ARG);
|
||||
break;
|
||||
case RT_XT_DIRECT:
|
||||
absolute_value = (cell)word_direct_xt(untag<word>(array_nth(literals,index)));
|
||||
case RT_XT_PIC:
|
||||
absolute_value = (cell)word_xt_pic(untag<word>(ARG));
|
||||
break;
|
||||
case RT_XT_PIC_TAIL:
|
||||
absolute_value = (cell)word_xt_pic_tail(untag<word>(ARG));
|
||||
break;
|
||||
case RT_HERE:
|
||||
absolute_value = offset + (short)untag_fixnum(array_nth(literals,index));
|
||||
absolute_value = offset + (short)untag_fixnum(ARG);
|
||||
break;
|
||||
case RT_THIS:
|
||||
absolute_value = (cell)(compiled + 1);
|
||||
|
@ -394,13 +421,15 @@ void relocate_code_block_step(relocation_entry rel, cell index, code_block *comp
|
|||
absolute_value = (cell)&stack_chain;
|
||||
break;
|
||||
case RT_UNTAGGED:
|
||||
absolute_value = untag_fixnum(array_nth(literals,index));
|
||||
absolute_value = untag_fixnum(ARG);
|
||||
break;
|
||||
default:
|
||||
critical_error("Bad rel type",rel);
|
||||
return; /* Can't happen */
|
||||
}
|
||||
|
||||
#undef ARG
|
||||
|
||||
store_address_in_code_block(REL_CLASS(rel),offset,absolute_value);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,10 +8,12 @@ enum relocation_type {
|
|||
RT_DLSYM,
|
||||
/* a pointer to a compiled word reference */
|
||||
RT_DISPATCH,
|
||||
/* a word's general entry point XT */
|
||||
/* a word or quotation's general entry point */
|
||||
RT_XT,
|
||||
/* a word's direct entry point XT */
|
||||
RT_XT_DIRECT,
|
||||
/* a word's PIC entry point */
|
||||
RT_XT_PIC,
|
||||
/* a word's tail-call PIC entry point */
|
||||
RT_XT_PIC_TAIL,
|
||||
/* current offset */
|
||||
RT_HERE,
|
||||
/* current code block */
|
||||
|
|
|
@ -26,8 +26,8 @@ void jit_compile_word(cell word_, cell def_, bool relocate)
|
|||
|
||||
word->code = def->code;
|
||||
|
||||
if(word->direct_entry_def != F)
|
||||
jit_compile(word->direct_entry_def,relocate);
|
||||
if(word->pic_def != F) jit_compile(word->pic_def,relocate);
|
||||
if(word->pic_tail_def != F) jit_compile(word->pic_tail_def,relocate);
|
||||
}
|
||||
|
||||
/* Apply a function to every code block */
|
||||
|
|
|
@ -60,9 +60,10 @@ DEF(bool,check_sse2,(void)):
|
|||
ret
|
||||
|
||||
DEF(F_FASTCALL void,primitive_inline_cache_miss,(void)):
|
||||
mov (%esp),%eax
|
||||
mov (%esp),%ebx
|
||||
DEF(F_FASTCALL void,primitive_inline_cache_miss_tail,(void)):
|
||||
sub $8,%esp
|
||||
push %eax
|
||||
push %ebx
|
||||
call MANGLE(inline_cache_miss)
|
||||
add $12,%esp
|
||||
jmp *%eax
|
||||
|
|
|
@ -73,8 +73,10 @@ DEF(void,set_callstack,(F_STACK_FRAME *to, F_STACK_FRAME *from, CELL length, voi
|
|||
ret /* return _with new stack_ */
|
||||
|
||||
DEF(F_FASTCALL void,primitive_inline_cache_miss,(void)):
|
||||
mov (%rsp),ARG0
|
||||
mov (%rsp),%rbx
|
||||
DEF(F_FASTCALL void,primitive_inline_cache_miss_tail,(void)):
|
||||
sub $STACK_PADDING,%rsp
|
||||
mov %rbx,ARG0
|
||||
call MANGLE(inline_cache_miss)
|
||||
add $STACK_PADDING,%rsp
|
||||
jmp *%rax
|
||||
|
|
|
@ -7,15 +7,19 @@ namespace factor
|
|||
|
||||
inline static void flush_icache(cell start, cell len) {}
|
||||
|
||||
static const unsigned char call_opcode = 0xe8;
|
||||
static const unsigned char jmp_opcode = 0xe9;
|
||||
|
||||
inline static unsigned char call_site_opcode(cell return_address)
|
||||
{
|
||||
return *(unsigned char *)(return_address - 5);
|
||||
}
|
||||
|
||||
inline static void check_call_site(cell return_address)
|
||||
{
|
||||
/* An x86 CALL instruction looks like so:
|
||||
|e8|..|..|..|..|
|
||||
where the ... are a PC-relative jump address.
|
||||
The return_address points to right after the
|
||||
instruction. */
|
||||
#ifdef FACTOR_DEBUG
|
||||
assert(*(unsigned char *)(return_address - 5) == 0xe8);
|
||||
unsigned char opcode = call_site_opcode(return_address);
|
||||
assert(opcode == call_opcode || opcode == jmp_opcode);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -31,6 +35,11 @@ inline static void set_call_target(cell return_address, void *target)
|
|||
*(int *)(return_address - 4) = ((cell)target - return_address);
|
||||
}
|
||||
|
||||
inline static bool tail_call_site_p(cell return_address)
|
||||
{
|
||||
return call_site_opcode(return_address) == jmp_opcode;
|
||||
}
|
||||
|
||||
/* Defined in assembly */
|
||||
VM_ASM_API void c_to_factor(cell quot);
|
||||
VM_ASM_API void throw_impl(cell quot, stack_frame *rewind_to);
|
||||
|
|
|
@ -86,7 +86,11 @@ struct inline_cache_jit : public jit {
|
|||
inline_cache_jit(cell generic_word_) : jit(PIC_TYPE,generic_word_) {};
|
||||
|
||||
void emit_check(cell klass);
|
||||
void compile_inline_cache(fixnum index, cell generic_word_, cell methods_, cell cache_entries_);
|
||||
void compile_inline_cache(fixnum index,
|
||||
cell generic_word_,
|
||||
cell methods_,
|
||||
cell cache_entries_,
|
||||
bool tail_call_p);
|
||||
};
|
||||
|
||||
void inline_cache_jit::emit_check(cell klass)
|
||||
|
@ -102,7 +106,11 @@ void inline_cache_jit::emit_check(cell klass)
|
|||
|
||||
/* index: 0 = top of stack, 1 = item underneath, etc
|
||||
cache_entries: array of class/method pairs */
|
||||
void inline_cache_jit::compile_inline_cache(fixnum index, cell generic_word_, cell methods_, cell cache_entries_)
|
||||
void inline_cache_jit::compile_inline_cache(fixnum index,
|
||||
cell generic_word_,
|
||||
cell methods_,
|
||||
cell cache_entries_,
|
||||
bool tail_call_p)
|
||||
{
|
||||
gc_root<word> generic_word(generic_word_);
|
||||
gc_root<array> methods(methods_);
|
||||
|
@ -136,20 +144,25 @@ void inline_cache_jit::compile_inline_cache(fixnum index, cell generic_word_, ce
|
|||
push(methods.value());
|
||||
push(tag_fixnum(index));
|
||||
push(cache_entries.value());
|
||||
word_jump(userenv[PIC_MISS_WORD]);
|
||||
word_jump(userenv[tail_call_p ? PIC_MISS_TAIL_WORD : PIC_MISS_WORD]);
|
||||
}
|
||||
|
||||
static code_block *compile_inline_cache(fixnum index,
|
||||
cell generic_word_,
|
||||
cell methods_,
|
||||
cell cache_entries_)
|
||||
cell cache_entries_,
|
||||
bool tail_call_p)
|
||||
{
|
||||
gc_root<word> generic_word(generic_word_);
|
||||
gc_root<array> methods(methods_);
|
||||
gc_root<array> cache_entries(cache_entries_);
|
||||
|
||||
inline_cache_jit jit(generic_word.value());
|
||||
jit.compile_inline_cache(index,generic_word.value(),methods.value(),cache_entries.value());
|
||||
jit.compile_inline_cache(index,
|
||||
generic_word.value(),
|
||||
methods.value(),
|
||||
cache_entries.value(),
|
||||
tail_call_p);
|
||||
code_block *code = jit.to_code_block();
|
||||
relocate_code_block(code);
|
||||
return code;
|
||||
|
@ -227,14 +240,18 @@ void *inline_cache_miss(cell return_address)
|
|||
xt = compile_inline_cache(index,
|
||||
generic_word.value(),
|
||||
methods.value(),
|
||||
new_cache_entries.value()) + 1;
|
||||
new_cache_entries.value(),
|
||||
tail_call_site_p(return_address))->xt();
|
||||
}
|
||||
|
||||
/* Install the new stub. */
|
||||
set_call_target(return_address,xt);
|
||||
|
||||
#ifdef PIC_DEBUG
|
||||
printf("Updated call site 0x%lx with 0x%lx\n",return_address,(cell)xt);
|
||||
printf("Updated %s call site 0x%lx with 0x%lx\n",
|
||||
tail_call_site_p(return_address) ? "tail" : "non-tail",
|
||||
return_address,
|
||||
(cell)xt);
|
||||
#endif
|
||||
|
||||
return xt;
|
||||
|
|
|
@ -8,7 +8,8 @@ void init_inline_caching(int max_size);
|
|||
PRIMITIVE(reset_inline_cache_stats);
|
||||
PRIMITIVE(inline_cache_stats);
|
||||
PRIMITIVE(inline_cache_miss);
|
||||
PRIMITIVE(inline_cache_miss_tail);
|
||||
|
||||
extern "C" void *inline_cache_miss(cell return_address);
|
||||
VM_C_API void *inline_cache_miss(cell return_address);
|
||||
|
||||
}
|
||||
|
|
|
@ -229,7 +229,9 @@ struct word : public object {
|
|||
/* TAGGED property assoc for library code */
|
||||
cell props;
|
||||
/* TAGGED alternative entry point for direct non-tail calls. Used for inline caching */
|
||||
cell direct_entry_def;
|
||||
cell pic_def;
|
||||
/* TAGGED alternative entry point for direct tail calls. Used for inline caching */
|
||||
cell pic_tail_def;
|
||||
/* TAGGED call count for profiling */
|
||||
cell counter;
|
||||
/* TAGGED machine code for sub-primitive */
|
||||
|
|
|
@ -147,6 +147,7 @@ const primitive_type primitives[] = {
|
|||
primitive_load_locals,
|
||||
primitive_check_datastack,
|
||||
primitive_inline_cache_miss,
|
||||
primitive_inline_cache_miss_tail,
|
||||
primitive_mega_cache_miss,
|
||||
primitive_lookup_method,
|
||||
primitive_reset_dispatch_stats,
|
||||
|
|
|
@ -48,7 +48,7 @@ enum special_object {
|
|||
JIT_RETURN,
|
||||
JIT_PROFILING,
|
||||
JIT_PUSH_IMMEDIATE,
|
||||
JIT_SAVE_STACK = 38,
|
||||
JIT_SAVE_STACK,
|
||||
JIT_DIP_WORD,
|
||||
JIT_DIP,
|
||||
JIT_2DIP_WORD,
|
||||
|
@ -60,7 +60,7 @@ enum special_object {
|
|||
JIT_EXECUTE_CALL,
|
||||
|
||||
/* Polymorphic inline cache generation in inline_cache.c */
|
||||
PIC_LOAD = 48,
|
||||
PIC_LOAD = 47,
|
||||
PIC_TAG,
|
||||
PIC_HI_TAG,
|
||||
PIC_TUPLE,
|
||||
|
@ -69,6 +69,7 @@ enum special_object {
|
|||
PIC_CHECK,
|
||||
PIC_HIT,
|
||||
PIC_MISS_WORD,
|
||||
PIC_MISS_TAIL_WORD,
|
||||
|
||||
/* Megamorphic cache generation in dispatch.c */
|
||||
MEGA_LOOKUP = 57,
|
||||
|
|
|
@ -16,7 +16,8 @@ word *allot_word(cell vocab_, cell name_)
|
|||
new_word->def = userenv[UNDEFINED_ENV];
|
||||
new_word->props = F;
|
||||
new_word->counter = tag_fixnum(0);
|
||||
new_word->direct_entry_def = F;
|
||||
new_word->pic_def = F;
|
||||
new_word->pic_tail_def = F;
|
||||
new_word->subprimitive = F;
|
||||
new_word->profiling = NULL;
|
||||
new_word->code = NULL;
|
||||
|
|
Loading…
Reference in New Issue