]> gitweb.factorcode.org Git - factor.git/commitdiff
Working on inline caching for tail call sites
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Thu, 7 May 2009 00:22:22 +0000 (19:22 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Thu, 7 May 2009 00:22:22 +0000 (19:22 -0500)
26 files changed:
basis/bootstrap/image/image.factor
basis/compiler/codegen/fixup/fixup.factor
basis/compiler/constants/constants.factor
basis/cpu/ppc/ppc.factor
basis/cpu/x86/32/32.factor
basis/cpu/x86/64/64.factor
basis/cpu/x86/bootstrap.factor
basis/cpu/x86/x86.factor
core/bootstrap/primitives.factor
core/generic/hook/hook.factor
core/generic/single/single-tests.factor
core/generic/single/single.factor
core/generic/standard/standard.factor
core/words/words.factor
vm/code_block.cpp
vm/code_block.hpp
vm/code_heap.cpp
vm/cpu-x86.32.S
vm/cpu-x86.64.S
vm/cpu-x86.hpp
vm/inline_cache.cpp
vm/inline_cache.hpp
vm/layouts.hpp
vm/primitives.cpp
vm/run.hpp
vm/words.cpp

index cad40b63848fda7dd99be8c01a1fbc3f0765c477..675c50732d05e7ec7c08d156642d1b3199f6a745 100644 (file)
@@ -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
index b52bb51b264ce2069b5f1e232498ff38b27f1ff8..d0c874feb0cd7116b46c7230b2422eafcfcf8d11 100755 (executable)
@@ -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 ;
 
index 886933b5cd5fa85d6a7dda741737be82d06ab350..5e0ee9860656c612060a15a7a6d308ff7354f4ff 100644 (file)
@@ -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? ;
index c239bacbc0ae9a6ff8ff4725759c0e6c0ab09cb2..a11b0daa8626c049d5059a6f9a35b7c3c6ac12d3 100644 (file)
@@ -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 ;
 
index 376edeb202fe4068a769b112c053161c84bfaea4..0a0ac4a53e727e570093db26083375cb7b217ca6 100755 (executable)
@@ -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 ;
index 8cc69958a4ec4761168b7a1acb5d966b7ba126e1..ad1b487e448100ae628f01a9901ae25416e46005 100644 (file)
@@ -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 ;
 
index 4b409102c9027002fccfe61c3dc97a0be2fe2f2b..8d35d4ed8afa56ff6046f0377bf830e4379a9de4 100644 (file)
@@ -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
index d508d7740b15cb3e795c87052b382a1bb436611f..5ae9e1c4893d9af2b2687512b2301a2d79fcd449 100644 (file)
@@ -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 )
index 83276cd3f252eeb9b45d16dae7ea9627c0450fd9..57bc61a0058c4ce1988c308625b0fe9d16fdde14 100644 (file)
@@ -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" (( -- )) }
index fe5b62f6c0386e9653495f6999866fd0ae33b6a7..5edbc54bd8b7dd96751c9520a1d6083d26ed705b 100644 (file)
@@ -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 ;
 
index c8cab970fd61b3b09803e240878611e5361a96c1..e48d404b92a60dd5d43b8cc5ad1804d21571eeb9 100644 (file)
@@ -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
\ No newline at end of file
index d8fa04edd64e3e8a1cb3e636f6341bb74cfb6946..36a76153f98035de524766eda06955264ee4f58a 100644 (file)
@@ -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 )
 
index bf801c4e47880d0a3de2505c25493b3e4641aef0..b76bcaa5829add4e5cf5ff271f515709844c9d28 100644 (file)
@@ -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 ;
 
index 1976c1e4cd295e5674bf3bf9fd39ffd9201c8baa..c01cf13bcd1d270c978718b65029107fffe62f9b 100755 (executable)
@@ -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"
index cd87da3801ca14fdfcf461d7cb1b2736e8fced31..1da16ad0a1c63b6bb517400bea7350b399fbcca4 100755 (executable)
@@ -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);
 }
 
index 85ae37384580f81789f4b3491acedb69e311eeab..b30de9d1481161181e98c591732b73ccd0a793e4 100644 (file)
@@ -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 */
index 77c78ad53393c8eb5c8d64bb2661a20a7798bbb0..c8c7639930a57a0cd9ae200ae4b0108fc9be68e2 100755 (executable)
@@ -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 */
index 0c08ea7b463352334f1825a5ebc97720ce5c3003..a1ce83932ee27cf50b904728c7baa563b8e1a489 100755 (executable)
@@ -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
index 5a70280ddfbdd107e37d3f8a909a28e2ddfcf7fa..0ace3543084dd4aaeed9c940c65e35498518bb08 100644 (file)
@@ -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
index c0b4651811178f924827312cdebe7ffef9a4d7bf..9b6f2ed57740df2a53470c497c045d9298db786f 100755 (executable)
@@ -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);
index 59632c418537439e396ba3e1e1b4a68326512de4..34d03e24f04b8d8ce376450a3a531ca74120317f 100755 (executable)
@@ -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 generic_word_,
+                                       cell methods_,
+                                       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;
index 84334efc78ccfc8ab5db637f40e6ae32dea08c6a..e2a6ae8cf931edb1e8b0fd5f98bf01a8550d5765 100644 (file)
@@ -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);
 
 }
index 8c96cf3187dc5587780163b161ae225bfd107df0..f8d114210a2acdd1dce502a980bde7214981e654 100755 (executable)
@@ -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 */
index f1c546894922c98a31df0f45fc188c6670104dca..bd761625d894586376a0dd2bfde9c4c4a0cca804 100755 (executable)
@@ -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,
index 829e25d2f725817fb1dfe37af1f2fd9d4fa4c9ce..48ebb8cf41373174be81c38cb8d475a7a5370148 100755 (executable)
@@ -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,
index 6e7c633c8464f03c97bfbe72ce767ea9fd9afedf..fa090c9ceaa6db19e881c4049edbb596f11cd94b 100644 (file)
@@ -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;