Non-optimizing compiler now open-codes megamorphic dispatch fast path

db4
Slava Pestov 2009-04-30 03:37:07 -05:00
parent 964fbd0a24
commit 515c619202
18 changed files with 207 additions and 113 deletions

View File

@ -173,6 +173,11 @@ SYMBOL: pic-check
SYMBOL: pic-hit SYMBOL: pic-hit
SYMBOL: pic-miss-word SYMBOL: pic-miss-word
! Megamorphic dispatch
SYMBOL: mega-lookup
SYMBOL: mega-lookup-word
SYMBOL: mega-miss-word
! Default definition for undefined words ! Default definition for undefined words
SYMBOL: undefined-quot SYMBOL: undefined-quot
@ -215,6 +220,9 @@ SYMBOL: undefined-quot
{ pic-check 54 } { pic-check 54 }
{ pic-hit 55 } { pic-hit 55 }
{ pic-miss-word 56 } { pic-miss-word 56 }
{ mega-lookup 57 }
{ mega-lookup-word 58 }
{ mega-miss-word 59 }
{ undefined-quot 60 } { undefined-quot 60 }
} ; inline } ; inline
@ -526,6 +534,8 @@ M: quotation '
\ 3dip jit-3dip-word set \ 3dip jit-3dip-word set
\ (execute) jit-execute-word set \ (execute) jit-execute-word set
\ inline-cache-miss \ pic-miss-word set \ inline-cache-miss \ pic-miss-word set
\ mega-cache-lookup \ mega-lookup-word set
\ mega-cache-miss \ mega-miss-word set
[ undefined ] undefined-quot set [ undefined ] undefined-quot set
{ {
jit-code-format jit-code-format
@ -563,6 +573,9 @@ M: quotation '
pic-check pic-check
pic-hit pic-hit
pic-miss-word pic-miss-word
mega-lookup
mega-lookup-word
mega-miss-word
undefined-quot undefined-quot
} [ emit-userenv ] each ; } [ emit-userenv ] each ;

View File

@ -44,7 +44,7 @@ SYMBOL: calls
SYMBOL: compiling-word SYMBOL: compiling-word
: compiled-stack-traces? ( -- ? ) 59 getenv ; : compiled-stack-traces? ( -- ? ) 67 getenv ;
! Mapping _label IDs to label instances ! Mapping _label IDs to label instances
SYMBOL: labels SYMBOL: labels

View File

@ -1,6 +1,7 @@
! Copyright (C) 2008, 2009 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: math kernel layouts system strings words quotations byte-arrays alien ; USING: math kernel layouts system strings words quotations byte-arrays
alien arrays ;
IN: compiler.constants IN: compiler.constants
! These constants must match vm/memory.h ! These constants must match vm/memory.h
@ -20,8 +21,8 @@ CONSTANT: deck-bits 18
: tuple-class-offset ( -- n ) bootstrap-cell tuple 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 ) 9 bootstrap-cells \ word tag-number - ; inline
: quot-xt-offset ( -- n ) 5 bootstrap-cells quotation tag-number - ; inline : quot-xt-offset ( -- n ) 5 bootstrap-cells quotation tag-number - ; inline
: word-code-offset ( -- n ) 10 bootstrap-cells object tag-number - ; inline : word-code-offset ( -- n ) 10 bootstrap-cells \ word tag-number - ; inline
: array-start-offset ( -- n ) 2 bootstrap-cells object tag-number - ; inline : array-start-offset ( -- n ) 2 bootstrap-cells array tag-number - ; inline
: compiled-header-size ( -- n ) 5 bootstrap-cells ; inline : compiled-header-size ( -- n ) 5 bootstrap-cells ; inline
! Relocation classes ! Relocation classes

View File

@ -3,7 +3,7 @@
USING: bootstrap.image.private kernel kernel.private namespaces USING: bootstrap.image.private kernel kernel.private namespaces
system cpu.x86.assembler layouts compiler.units math system cpu.x86.assembler layouts compiler.units math
math.private compiler.constants vocabs slots.private words math.private compiler.constants vocabs slots.private words
locals.backend make sequences combinators ; locals.backend make sequences combinators arrays ;
IN: bootstrap.x86 IN: bootstrap.x86
big-endian off big-endian off
@ -181,9 +181,11 @@ big-endian off
] pic-load jit-define ] pic-load jit-define
! Tag ! Tag
[ : load-tag ( -- )
temp1 tag-mask get AND temp1 tag-mask get AND
] pic-tag jit-define temp1 tag-bits get SHL ;
[ load-tag ] pic-tag jit-define
! The 'make' trick lets us compute the jump distance for the ! The 'make' trick lets us compute the jump distance for the
! conditional branches there ! conditional branches there
@ -191,8 +193,8 @@ big-endian off
! Hi-tag ! Hi-tag
[ [
temp0 temp1 MOV temp0 temp1 MOV
temp1 tag-mask get AND load-tag
temp1 object tag-number CMP temp1 object tag-number tag-fixnum CMP
[ temp1 temp0 object tag-number neg [+] MOV ] { } make [ temp1 temp0 object tag-number neg [+] MOV ] { } make
[ length JNE ] [ % ] bi [ length JNE ] [ % ] bi
] pic-hi-tag jit-define ] pic-hi-tag jit-define
@ -200,8 +202,8 @@ big-endian off
! Tuple ! Tuple
[ [
temp0 temp1 MOV temp0 temp1 MOV
temp1 tag-mask get AND load-tag
temp1 tuple tag-number CMP temp1 tuple tag-number tag-fixnum CMP
[ temp1 temp0 tuple tag-number neg bootstrap-cell + [+] MOV ] { } make [ temp1 temp0 tuple tag-number neg bootstrap-cell + [+] MOV ] { } make
[ length JNE ] [ % ] bi [ length JNE ] [ % ] bi
] pic-tuple jit-define ] pic-tuple jit-define
@ -209,21 +211,17 @@ big-endian off
! Hi-tag and tuple ! Hi-tag and tuple
[ [
temp0 temp1 MOV temp0 temp1 MOV
temp1 tag-mask get AND load-tag
! If bits 2 and 3 are set, the tag is either 6 (object) or 7 (tuple) ! If bits 2 and 3 are set, the tag is either 6 (object) or 7 (tuple)
temp1 BIN: 110 tag-fixnum CMP temp1 BIN: 110 tag-fixnum CMP
[ [
! Untag temp0 in temp2 ! Untag temp0
temp2 temp0 MOV temp0 tag-mask get bitnot AND
temp2 tag-mask get bitnot AND ! Set temp1 to 0 for objects, and 8 for tuples
! Set temp1 to 0 for objects, and 1 for tuples temp1 1 tag-fixnum AND
temp1 1 AND bootstrap-cell 4 = [ temp1 1 SHR ] when
bootstrap-cell {
{ 4 [ temp1 2 SHR ] }
{ 8 [ temp1 3 SHR ] }
} case
! Load header cell or tuple layout cell ! Load header cell or tuple layout cell
temp1 temp2 temp1 [+] MOV temp1 temp0 temp1 [+] MOV
] [ ] make [ length JL ] [ % ] bi ] [ ] make [ length JL ] [ % ] bi
] pic-hi-tag-tuple jit-define ] pic-hi-tag-tuple jit-define
@ -238,6 +236,34 @@ big-endian off
[ f JE rc-relative rt-xt jit-rel ] pic-hit jit-define [ f JE rc-relative rt-xt jit-rel ] pic-hit jit-define
! ! ! Megamorphic caches
[
! cache = ...
temp0 0 MOV rc-absolute-cell rt-immediate jit-rel
! key = class
temp2 temp1 MOV
! compute cache.length - 1
temp3 temp0 1 bootstrap-cells array tag-number - [+] MOV
temp3 1 SHR
temp3 4 SUB
! key &= cache.length - 1
temp2 temp3 AND
! cache += array-start-offset
temp0 array-start-offset ADD
! cache += key
temp0 temp2 ADD
! if(get(cache) == class)
temp0 [] temp1 CMP
! ... goto get(cache + bootstrap-cell)
[
temp0 temp0 bootstrap-cell [+] MOV
temp0 word-xt-offset [+] JMP
] [ ] make
[ length JNE ] [ % ] bi
! fall-through on miss
] mega-lookup jit-define
! ! ! Sub-primitives ! ! ! Sub-primitives
! Quotations and words ! Quotations and words

View File

@ -349,6 +349,7 @@ tuple
{ "get-local" "locals.backend" (( n -- obj )) } { "get-local" "locals.backend" (( n -- obj )) }
{ "load-local" "locals.backend" (( obj -- )) } { "load-local" "locals.backend" (( obj -- )) }
{ "drop-locals" "locals.backend" (( n -- )) } { "drop-locals" "locals.backend" (( n -- )) }
{ "mega-cache-lookup" "generic.single.private" (( methods index cache -- )) }
} [ first3 make-sub-primitive ] each } [ first3 make-sub-primitive ] each
! Primitive words ! Primitive words
@ -501,8 +502,9 @@ tuple
{ "jit-compile" "quotations" (( quot -- )) } { "jit-compile" "quotations" (( quot -- )) }
{ "load-locals" "locals.backend" (( ... n -- )) } { "load-locals" "locals.backend" (( ... n -- )) }
{ "check-datastack" "kernel.private" (( array in# out# -- ? )) } { "check-datastack" "kernel.private" (( array in# out# -- ? )) }
{ "lookup-method" "generic.single.private" (( object methods method-cache -- method )) } { "inline-cache-miss" "generic.single.private" (( generic methods index cache -- )) }
{ "inline-cache-miss" "generic.single.private" (( generic methods -- )) } { "mega-cache-miss" "generic.single.private" (( methods index cache -- method )) }
{ "lookup-method" "generic.single.private" (( object methods -- method )) }
{ "reset-dispatch-stats" "generic.single" (( -- )) } { "reset-dispatch-stats" "generic.single" (( -- )) }
{ "dispatch-stats" "generic.single" (( -- stats )) } { "dispatch-stats" "generic.single" (( -- stats )) }
{ "reset-inline-cache-stats" "generic.single" (( -- )) } { "reset-inline-cache-stats" "generic.single" (( -- )) }

View File

@ -1,7 +1,8 @@
! Copyright (C) 2009 Slava Pestov. ! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors definitions generic generic.single kernel USING: accessors definitions generic generic.single
namespaces words ; generic.single.private kernel namespaces words kernel.private
quotations sequences ;
IN: generic.hook IN: generic.hook
TUPLE: hook-combination < single-combination var ; TUPLE: hook-combination < single-combination var ;
@ -16,6 +17,11 @@ M: hook-combination picker
M: hook-combination dispatch# drop 0 ; 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 ;
M: hook-generic definer drop \ HOOK: f ; M: hook-generic definer drop \ HOOK: f ;
M: hook-generic effective-method M: hook-generic effective-method

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays assocs classes classes.algebra USING: accessors arrays assocs classes classes.algebra
combinators definitions generic hashtables kernel combinators definitions generic hashtables kernel
kernel.private layouts make math namespaces quotations kernel.private layouts math namespaces quotations
sequences words generic.single.private effects make ; sequences words generic.single.private effects make ;
IN: generic.single IN: generic.single
@ -29,7 +29,7 @@ SYMBOL: combination
HOOK: picker combination ( -- quot ) HOOK: picker combination ( -- quot )
M: single-combination next-method-quot* M: single-combination next-method-quot* ( class generic combination -- quot )
[ [
2dup next-method dup [ 2dup next-method dup [
[ [
@ -238,29 +238,19 @@ M: f compile-engine ;
[ <engine> compile-engine ] bi [ <engine> compile-engine ] bi
] tri ; ] tri ;
: make-empty-cache ( -- array ) HOOK: inline-cache-quot combination ( word methods -- quot/f )
generic-word get "methods" word-prop
assoc-size 2 * next-power-of-2 f <array> ;
HOOK: direct-entry-def combination ( word methods -- quot/f ) : define-inline-cache-quot ( word methods -- )
[ drop ] [ inline-cache-quot ] 2bi >>direct-entry-def drop ;
M: single-combination direct-entry-def 2drop f ; HOOK: mega-cache-quot combination ( methods -- quot/f )
: define-direct-entry ( word methods -- )
[ drop ] [ direct-entry-def ] 2bi >>direct-entry-def drop ;
M: single-combination perform-combination M: single-combination perform-combination
[ [
dup generic-word set dup generic-word set
dup build-decision-tree dup build-decision-tree
[ "decision-tree" set-word-prop ] [ "decision-tree" set-word-prop ]
[ [ mega-cache-quot define ]
[ [ define-inline-cache-quot ]
picker % 2tri
,
make-empty-cache ,
[ lookup-method (execute) ] %
] [ ] make define
]
[ define-direct-entry ] 2tri
] with-combination ; ] with-combination ;

View File

@ -2,7 +2,8 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors definitions generic generic.single kernel USING: accessors definitions generic generic.single kernel
namespaces words math math.order combinators sequences namespaces words math math.order combinators sequences
generic.single.private ; generic.single.private quotations kernel.private
assocs arrays ;
IN: generic.standard IN: generic.standard
TUPLE: standard-combination < single-combination # ; TUPLE: standard-combination < single-combination # ;
@ -39,12 +40,19 @@ M: standard-generic effective-method
[ datastack ] dip [ "combination" word-prop #>> swap <reversed> nth ] keep [ datastack ] dip [ "combination" word-prop #>> swap <reversed> nth ] keep
(effective-method) ; (effective-method) ;
M: standard-combination direct-entry-def ( word methods -- ) M: standard-combination inline-cache-quot ( word methods -- )
#! Direct calls to the generic word (not tail calls or indirect calls) #! Direct calls to the generic word (not tail calls or indirect calls)
#! will jump to the inline cache entry point instead of the megamorphic #! will jump to the inline cache entry point instead of the megamorphic
#! dispatch entry point. #! dispatch entry point.
combination get #>> [ f inline-cache-miss ] 3curry [ ] like ; combination get #>> [ f inline-cache-miss ] 3curry [ ] like ;
: make-empty-cache ( -- array )
generic-word get "methods" word-prop
assoc-size 2 * next-power-of-2 f <array> ;
M: standard-combination mega-cache-quot
combination get #>> make-empty-cache [ mega-cache-lookup ] 3curry [ ] like ;
M: standard-generic definer drop \ GENERIC# f ; M: standard-generic definer drop \ GENERIC# f ;
M: simple-generic definer drop \ GENERIC: f ; M: simple-generic definer drop \ GENERIC: f ;

View File

@ -81,30 +81,6 @@ static CELL lookup_hi_tag_method(CELL object, CELL methods)
return array_nth(hi_tag_methods,tag); return array_nth(hi_tag_methods,tag);
} }
static CELL method_cache_hashcode(CELL key, F_ARRAY *array)
{
CELL capacity = (array_capacity(array) >> 1) - 1;
return ((key >> TAG_BITS) & capacity) << 1;
}
static CELL lookup_cached_method(CELL key, CELL method_cache)
{
F_ARRAY *array = untag_object(method_cache);
CELL hashcode = method_cache_hashcode(key,array);
if(array_nth(array,hashcode) == key)
return array_nth(array,hashcode + 1);
else
return F;
}
static void update_method_cache(CELL key, CELL method_cache, CELL method)
{
F_ARRAY *array = untag_object(method_cache);
CELL hashcode = method_cache_hashcode(key,array);
set_array_nth(array,hashcode,key);
set_array_nth(array,hashcode + 1,method);
}
static CELL lookup_hairy_method(CELL object, CELL methods) static CELL lookup_hairy_method(CELL object, CELL methods)
{ {
CELL method = array_nth(untag_object(methods),TAG(object)); CELL method = array_nth(untag_object(methods),TAG(object));
@ -127,43 +103,21 @@ static CELL lookup_hairy_method(CELL object, CELL methods)
} }
} }
static CELL lookup_method_with_cache(CELL object, CELL methods, CELL method_cache) CELL lookup_method(CELL object, CELL methods)
{ {
if(!HI_TAG_OR_TUPLE_P(object)) if(!HI_TAG_OR_TUPLE_P(object))
{
megamorphic_cache_hits++;
return array_nth(untag_object(methods),TAG(object)); return array_nth(untag_object(methods),TAG(object));
}
else else
{ return lookup_hairy_method(object,methods);
CELL key = get(HI_TAG_HEADER(object));
CELL method = lookup_cached_method(key,method_cache);
if(method != F)
{
megamorphic_cache_hits++;
return method;
}
else
{
megamorphic_cache_misses++;
method = lookup_hairy_method(object,methods);
update_method_cache(key,method_cache,method);
return method;
}
}
} }
void primitive_lookup_method(void) void primitive_lookup_method(void)
{ {
CELL method_cache = get(ds); CELL methods = dpop();
CELL methods = get(ds - CELLS); CELL object = dpop();
CELL object = get(ds - CELLS * 2); dpush(lookup_method(object,methods));
ds -= CELLS * 2;
drepl(lookup_method_with_cache(object,methods,method_cache));
} }
/* Next two functions are used for polymorphic inline caching */
CELL object_class(CELL object) CELL object_class(CELL object)
{ {
if(!HI_TAG_OR_TUPLE_P(object)) if(!HI_TAG_OR_TUPLE_P(object))
@ -172,12 +126,35 @@ CELL object_class(CELL object)
return get(HI_TAG_HEADER(object)); return get(HI_TAG_HEADER(object));
} }
CELL lookup_method(CELL object, CELL methods) static CELL method_cache_hashcode(CELL class, F_ARRAY *array)
{ {
if(!HI_TAG_OR_TUPLE_P(object)) CELL capacity = (array_capacity(array) >> 1) - 1;
return array_nth(untag_object(methods),TAG(object)); return ((class >> TAG_BITS) & capacity) << 1;
else }
return lookup_hairy_method(object,methods);
static void update_method_cache(CELL cache, CELL class, CELL method)
{
F_ARRAY *array = untag_object(cache);
CELL hashcode = method_cache_hashcode(class,array);
set_array_nth(array,hashcode,class);
set_array_nth(array,hashcode + 1,method);
}
void primitive_mega_cache_miss(void)
{
megamorphic_cache_misses++;
CELL cache = dpop();
F_FIXNUM index = untag_fixnum_fast(dpop());
CELL methods = dpop();
CELL object = get(ds - index * CELLS);
CELL class = object_class(object);
CELL method = lookup_method(object,methods);
update_method_cache(cache,class,method);
dpush(method);
} }
void primitive_reset_dispatch_stats(void) void primitive_reset_dispatch_stats(void)
@ -194,3 +171,32 @@ void primitive_dispatch_stats(void)
GROWABLE_ARRAY_DONE(stats); GROWABLE_ARRAY_DONE(stats);
dpush(stats); dpush(stats);
} }
void jit_emit_class_lookup(F_JIT *jit, F_FIXNUM index, CELL type)
{
jit_emit_with(jit,userenv[PIC_LOAD],tag_fixnum(-index * CELLS));
jit_emit(jit,userenv[type]);
}
void jit_emit_mega_cache_lookup(F_JIT *jit, CELL methods, F_FIXNUM index, CELL cache)
{
/* Generate machine code to determine the object's class. */
jit_emit_class_lookup(jit,index,PIC_HI_TAG_TUPLE);
/* Do a cache lookup. */
jit_emit_with(jit,userenv[MEGA_LOOKUP],cache);
/* If we end up here, the cache missed. */
jit_emit(jit,userenv[JIT_PROLOG]);
/* Push index, method table and cache on the stack. */
jit_push(jit,methods);
jit_push(jit,tag_fixnum(index));
jit_push(jit,cache);
jit_word_call(jit,userenv[MEGA_MISS_WORD]);
/* Now the new method has been stored into the cache, and its on
the stack. */
jit_emit(jit,userenv[JIT_EPILOG]);
jit_emit(jit,userenv[JIT_EXECUTE_JUMP]);
}

View File

@ -1,10 +1,16 @@
CELL megamorphic_cache_hits; CELL megamorphic_cache_hits;
CELL megamorphic_cache_misses; CELL megamorphic_cache_misses;
CELL lookup_method(CELL object, CELL methods);
void primitive_lookup_method(void); void primitive_lookup_method(void);
CELL object_class(CELL object); CELL object_class(CELL object);
CELL lookup_method(CELL object, CELL methods);
void primitive_mega_cache_miss(void);
void primitive_reset_dispatch_stats(void); void primitive_reset_dispatch_stats(void);
void primitive_dispatch_stats(void); void primitive_dispatch_stats(void);
void jit_emit_class_lookup(F_JIT *jit, F_FIXNUM index, CELL type);
void jit_emit_mega_cache_lookup(F_JIT *jit, CELL methods, F_FIXNUM index, CELL cache);

View File

@ -183,7 +183,7 @@ void primitive_save_image_and_exit(void)
for(i = 0; i < FIRST_SAVE_ENV; i++) for(i = 0; i < FIRST_SAVE_ENV; i++)
userenv[i] = F; userenv[i] = F;
for(i = LAST_SAVE_ENV + 1; i < USER_ENV; i++) for(i = LAST_SAVE_ENV + 1; i < STACK_TRACES_ENV; i++)
userenv[i] = F; userenv[i] = F;
/* do a full GC + code heap compaction */ /* do a full GC + code heap compaction */

View File

@ -82,8 +82,7 @@ static F_CODE_BLOCK *compile_inline_cache(F_FIXNUM index, CELL generic_word, CEL
jit_init(&jit,WORD_TYPE,generic_word); jit_init(&jit,WORD_TYPE,generic_word);
/* Generate machine code to determine the object's class. */ /* Generate machine code to determine the object's class. */
jit_emit_with(&jit,userenv[PIC_LOAD],tag_fixnum(-index * CELLS)); jit_emit_class_lookup(&jit,index,inline_cache_type);
jit_emit(&jit,userenv[inline_cache_type]);
/* Generate machine code to check, in turn, if the class is one of the cached entries. */ /* Generate machine code to check, in turn, if the class is one of the cached entries. */
CELL i; CELL i;

View File

@ -1,5 +1,11 @@
#include "master.h" #include "master.h"
/* Simple code generator used by:
- profiler (profiler.c),
- quotation compiler (quotations.c),
- megamorphic caches (dispatch.c),
- polymorphic inline caches (inline_cache.c) */
/* Allocates memory */ /* Allocates memory */
void jit_init(F_JIT *jit, CELL jit_type, CELL owner) void jit_init(F_JIT *jit, CELL jit_type, CELL owner)
{ {

View File

@ -45,6 +45,12 @@ INLINE void jit_word_jump(F_JIT *jit, CELL word)
jit_emit_with(jit,userenv[JIT_WORD_JUMP],word); jit_emit_with(jit,userenv[JIT_WORD_JUMP],word);
} }
/* Allocates memory */
INLINE void jit_word_call(F_JIT *jit, CELL word)
{
jit_emit_with(jit,userenv[JIT_WORD_CALL],word);
}
/* Allocates memory */ /* Allocates memory */
INLINE void jit_emit_subprimitive(F_JIT *jit, F_WORD *word) INLINE void jit_emit_subprimitive(F_JIT *jit, F_WORD *word)
{ {

View File

@ -50,8 +50,8 @@
#include "callstack.h" #include "callstack.h"
#include "alien.h" #include "alien.h"
#include "quotations.h" #include "quotations.h"
#include "dispatch.h"
#include "jit.h" #include "jit.h"
#include "dispatch.h"
#include "inline_cache.h" #include "inline_cache.h"
#include "factor.h" #include "factor.h"
#include "utilities.h" #include "utilities.h"

View File

@ -143,8 +143,9 @@ void *primitives[] = {
primitive_jit_compile, primitive_jit_compile,
primitive_load_locals, primitive_load_locals,
primitive_check_datastack, primitive_check_datastack,
primitive_lookup_method,
primitive_inline_cache_miss, primitive_inline_cache_miss,
primitive_mega_cache_miss,
primitive_lookup_method,
primitive_reset_dispatch_stats, primitive_reset_dispatch_stats,
primitive_dispatch_stats, primitive_dispatch_stats,
primitive_reset_inline_cache_stats, primitive_reset_inline_cache_stats,

View File

@ -89,6 +89,15 @@ static bool jit_ignore_declare_p(F_ARRAY *array, CELL i)
&& array_nth(array,i + 1) == userenv[JIT_DECLARE_WORD]; && array_nth(array,i + 1) == userenv[JIT_DECLARE_WORD];
} }
static bool jit_mega_lookup_p(F_ARRAY *array, CELL i)
{
return (i + 3) < array_capacity(array)
&& type_of(array_nth(array,i)) == ARRAY_TYPE
&& type_of(array_nth(array,i + 1)) == FIXNUM_TYPE
&& type_of(array_nth(array,i + 2)) == ARRAY_TYPE
&& array_nth(array,i + 3) == userenv[MEGA_LOOKUP_WORD];
}
static bool jit_stack_frame_p(F_ARRAY *array) static bool jit_stack_frame_p(F_ARRAY *array)
{ {
F_FIXNUM length = array_capacity(array); F_FIXNUM length = array_capacity(array);
@ -189,7 +198,7 @@ void jit_compile(CELL quot, bool relocate)
jit_word_jump(&jit,obj); jit_word_jump(&jit,obj);
} }
else else
jit_emit_with(&jit,userenv[JIT_WORD_CALL],obj); jit_word_call(&jit,obj);
} }
break; break;
case WRAPPER_TYPE: case WRAPPER_TYPE:
@ -257,6 +266,16 @@ void jit_compile(CELL quot, bool relocate)
i++; i++;
break; break;
} }
else if(jit_mega_lookup_p(untag_object(array),i))
{
jit_emit_mega_cache_lookup(&jit,
array_nth(untag_object(array),i),
untag_fixnum_fast(array_nth(untag_object(array),i + 1)),
array_nth(untag_object(array),i + 2));
i += 3;
tail_call = true;
break;
}
default: default:
jit_push(&jit,obj); jit_push(&jit,obj);
break; break;

View File

@ -32,7 +32,7 @@ typedef enum {
BOOT_ENV = 20, /* boot quotation */ BOOT_ENV = 20, /* boot quotation */
GLOBAL_ENV, /* global namespace */ GLOBAL_ENV, /* global namespace */
/* Used by the JIT compiler */ /* Quotation compilation in quotations.c */
JIT_CODE_FORMAT = 22, JIT_CODE_FORMAT = 22,
JIT_PROLOG, JIT_PROLOG,
JIT_PRIMITIVE_WORD, JIT_PRIMITIVE_WORD,
@ -60,7 +60,7 @@ typedef enum {
JIT_EXECUTE_JUMP, JIT_EXECUTE_JUMP,
JIT_EXECUTE_CALL, JIT_EXECUTE_CALL,
/* Used by polymorphic inline cache generation in inline_cache.c */ /* Polymorphic inline cache generation in inline_cache.c */
PIC_LOAD = 48, PIC_LOAD = 48,
PIC_TAG, PIC_TAG,
PIC_HI_TAG, PIC_HI_TAG,
@ -71,7 +71,10 @@ typedef enum {
PIC_HIT, PIC_HIT,
PIC_MISS_WORD, PIC_MISS_WORD,
STACK_TRACES_ENV = 59, /* Megamorphic cache generation in dispatch.c */
MEGA_LOOKUP = 57,
MEGA_LOOKUP_WORD,
MEGA_MISS_WORD,
UNDEFINED_ENV = 60, /* default quotation for undefined words */ UNDEFINED_ENV = 60, /* default quotation for undefined words */
@ -84,6 +87,8 @@ typedef enum {
THREADS_ENV = 64, THREADS_ENV = 64,
RUN_QUEUE_ENV = 65, RUN_QUEUE_ENV = 65,
SLEEP_QUEUE_ENV = 66, SLEEP_QUEUE_ENV = 66,
STACK_TRACES_ENV = 67,
} F_ENVTYPE; } F_ENVTYPE;
#define FIRST_SAVE_ENV BOOT_ENV #define FIRST_SAVE_ENV BOOT_ENV