Non-optimizing compiler now open-codes megamorphic dispatch fast path
parent
964fbd0a24
commit
515c619202
|
@ -173,6 +173,11 @@ SYMBOL: pic-check
|
|||
SYMBOL: pic-hit
|
||||
SYMBOL: pic-miss-word
|
||||
|
||||
! Megamorphic dispatch
|
||||
SYMBOL: mega-lookup
|
||||
SYMBOL: mega-lookup-word
|
||||
SYMBOL: mega-miss-word
|
||||
|
||||
! Default definition for undefined words
|
||||
SYMBOL: undefined-quot
|
||||
|
||||
|
@ -215,6 +220,9 @@ SYMBOL: undefined-quot
|
|||
{ pic-check 54 }
|
||||
{ pic-hit 55 }
|
||||
{ pic-miss-word 56 }
|
||||
{ mega-lookup 57 }
|
||||
{ mega-lookup-word 58 }
|
||||
{ mega-miss-word 59 }
|
||||
{ undefined-quot 60 }
|
||||
} ; inline
|
||||
|
||||
|
@ -526,6 +534,8 @@ M: quotation '
|
|||
\ 3dip jit-3dip-word set
|
||||
\ (execute) jit-execute-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
|
||||
{
|
||||
jit-code-format
|
||||
|
@ -563,6 +573,9 @@ M: quotation '
|
|||
pic-check
|
||||
pic-hit
|
||||
pic-miss-word
|
||||
mega-lookup
|
||||
mega-lookup-word
|
||||
mega-miss-word
|
||||
undefined-quot
|
||||
} [ emit-userenv ] each ;
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ SYMBOL: calls
|
|||
|
||||
SYMBOL: compiling-word
|
||||
|
||||
: compiled-stack-traces? ( -- ? ) 59 getenv ;
|
||||
: compiled-stack-traces? ( -- ? ) 67 getenv ;
|
||||
|
||||
! Mapping _label IDs to label instances
|
||||
SYMBOL: labels
|
||||
|
|
|
@ -1,6 +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 ;
|
||||
USING: math kernel layouts system strings words quotations byte-arrays
|
||||
alien arrays ;
|
||||
IN: compiler.constants
|
||||
|
||||
! 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
|
||||
: word-xt-offset ( -- n ) 9 bootstrap-cells \ word 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
|
||||
: array-start-offset ( -- n ) 2 bootstrap-cells object tag-number - ; inline
|
||||
: word-code-offset ( -- n ) 10 bootstrap-cells \ word tag-number - ; inline
|
||||
: array-start-offset ( -- n ) 2 bootstrap-cells array tag-number - ; inline
|
||||
: compiled-header-size ( -- n ) 5 bootstrap-cells ; inline
|
||||
|
||||
! Relocation classes
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
USING: bootstrap.image.private kernel kernel.private namespaces
|
||||
system cpu.x86.assembler layouts compiler.units math
|
||||
math.private compiler.constants vocabs slots.private words
|
||||
locals.backend make sequences combinators ;
|
||||
locals.backend make sequences combinators arrays ;
|
||||
IN: bootstrap.x86
|
||||
|
||||
big-endian off
|
||||
|
@ -181,9 +181,11 @@ big-endian off
|
|||
] pic-load jit-define
|
||||
|
||||
! Tag
|
||||
[
|
||||
: load-tag ( -- )
|
||||
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
|
||||
! conditional branches there
|
||||
|
@ -191,8 +193,8 @@ big-endian off
|
|||
! Hi-tag
|
||||
[
|
||||
temp0 temp1 MOV
|
||||
temp1 tag-mask get AND
|
||||
temp1 object tag-number CMP
|
||||
load-tag
|
||||
temp1 object tag-number tag-fixnum CMP
|
||||
[ temp1 temp0 object tag-number neg [+] MOV ] { } make
|
||||
[ length JNE ] [ % ] bi
|
||||
] pic-hi-tag jit-define
|
||||
|
@ -200,8 +202,8 @@ big-endian off
|
|||
! Tuple
|
||||
[
|
||||
temp0 temp1 MOV
|
||||
temp1 tag-mask get AND
|
||||
temp1 tuple tag-number CMP
|
||||
load-tag
|
||||
temp1 tuple tag-number tag-fixnum CMP
|
||||
[ temp1 temp0 tuple tag-number neg bootstrap-cell + [+] MOV ] { } make
|
||||
[ length JNE ] [ % ] bi
|
||||
] pic-tuple jit-define
|
||||
|
@ -209,21 +211,17 @@ big-endian off
|
|||
! Hi-tag and tuple
|
||||
[
|
||||
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)
|
||||
temp1 BIN: 110 tag-fixnum CMP
|
||||
[
|
||||
! Untag temp0 in temp2
|
||||
temp2 temp0 MOV
|
||||
temp2 tag-mask get bitnot AND
|
||||
! Set temp1 to 0 for objects, and 1 for tuples
|
||||
temp1 1 AND
|
||||
bootstrap-cell {
|
||||
{ 4 [ temp1 2 SHR ] }
|
||||
{ 8 [ temp1 3 SHR ] }
|
||||
} case
|
||||
! Untag temp0
|
||||
temp0 tag-mask get bitnot AND
|
||||
! Set temp1 to 0 for objects, and 8 for tuples
|
||||
temp1 1 tag-fixnum AND
|
||||
bootstrap-cell 4 = [ temp1 1 SHR ] when
|
||||
! Load header cell or tuple layout cell
|
||||
temp1 temp2 temp1 [+] MOV
|
||||
temp1 temp0 temp1 [+] MOV
|
||||
] [ ] make [ length JL ] [ % ] bi
|
||||
] 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
|
||||
|
||||
! ! ! 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
|
||||
|
||||
! Quotations and words
|
||||
|
|
|
@ -349,6 +349,7 @@ tuple
|
|||
{ "get-local" "locals.backend" (( n -- obj )) }
|
||||
{ "load-local" "locals.backend" (( obj -- )) }
|
||||
{ "drop-locals" "locals.backend" (( n -- )) }
|
||||
{ "mega-cache-lookup" "generic.single.private" (( methods index cache -- )) }
|
||||
} [ first3 make-sub-primitive ] each
|
||||
|
||||
! Primitive words
|
||||
|
@ -501,8 +502,9 @@ tuple
|
|||
{ "jit-compile" "quotations" (( quot -- )) }
|
||||
{ "load-locals" "locals.backend" (( ... n -- )) }
|
||||
{ "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 -- )) }
|
||||
{ "inline-cache-miss" "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" (( -- )) }
|
||||
{ "dispatch-stats" "generic.single" (( -- stats )) }
|
||||
{ "reset-inline-cache-stats" "generic.single" (( -- )) }
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
! Copyright (C) 2009 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: accessors definitions generic generic.single kernel
|
||||
namespaces words ;
|
||||
USING: accessors definitions generic generic.single
|
||||
generic.single.private kernel namespaces words kernel.private
|
||||
quotations sequences ;
|
||||
IN: generic.hook
|
||||
|
||||
TUPLE: hook-combination < single-combination var ;
|
||||
|
@ -16,6 +17,11 @@ 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 ;
|
||||
|
||||
M: hook-generic definer drop \ HOOK: f ;
|
||||
|
||||
M: hook-generic effective-method
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: accessors arrays assocs classes classes.algebra
|
||||
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 ;
|
||||
IN: generic.single
|
||||
|
||||
|
@ -29,7 +29,7 @@ SYMBOL: combination
|
|||
|
||||
HOOK: picker combination ( -- quot )
|
||||
|
||||
M: single-combination next-method-quot*
|
||||
M: single-combination next-method-quot* ( class generic combination -- quot )
|
||||
[
|
||||
2dup next-method dup [
|
||||
[
|
||||
|
@ -238,29 +238,19 @@ M: f compile-engine ;
|
|||
[ <engine> compile-engine ] bi
|
||||
] tri ;
|
||||
|
||||
: make-empty-cache ( -- array )
|
||||
generic-word get "methods" word-prop
|
||||
assoc-size 2 * next-power-of-2 f <array> ;
|
||||
HOOK: inline-cache-quot combination ( word methods -- quot/f )
|
||||
|
||||
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 ;
|
||||
|
||||
: define-direct-entry ( word methods -- )
|
||||
[ drop ] [ direct-entry-def ] 2bi >>direct-entry-def drop ;
|
||||
HOOK: mega-cache-quot combination ( methods -- quot/f )
|
||||
|
||||
M: single-combination perform-combination
|
||||
[
|
||||
dup generic-word set
|
||||
dup build-decision-tree
|
||||
[ "decision-tree" set-word-prop ]
|
||||
[
|
||||
[
|
||||
picker %
|
||||
,
|
||||
make-empty-cache ,
|
||||
[ lookup-method (execute) ] %
|
||||
] [ ] make define
|
||||
]
|
||||
[ define-direct-entry ] 2tri
|
||||
[ mega-cache-quot define ]
|
||||
[ define-inline-cache-quot ]
|
||||
2tri
|
||||
] with-combination ;
|
|
@ -2,7 +2,8 @@
|
|||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: accessors definitions generic generic.single kernel
|
||||
namespaces words math math.order combinators sequences
|
||||
generic.single.private ;
|
||||
generic.single.private quotations kernel.private
|
||||
assocs arrays ;
|
||||
IN: generic.standard
|
||||
|
||||
TUPLE: standard-combination < single-combination # ;
|
||||
|
@ -39,12 +40,19 @@ M: standard-generic effective-method
|
|||
[ datastack ] dip [ "combination" word-prop #>> swap <reversed> nth ] keep
|
||||
(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)
|
||||
#! will jump to the inline cache entry point instead of the megamorphic
|
||||
#! dispatch entry point.
|
||||
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: simple-generic definer drop \ GENERIC: f ;
|
||||
|
|
118
vm/dispatch.c
118
vm/dispatch.c
|
@ -81,30 +81,6 @@ static CELL lookup_hi_tag_method(CELL object, CELL methods)
|
|||
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)
|
||||
{
|
||||
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))
|
||||
{
|
||||
megamorphic_cache_hits++;
|
||||
return array_nth(untag_object(methods),TAG(object));
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
return lookup_hairy_method(object,methods);
|
||||
}
|
||||
|
||||
void primitive_lookup_method(void)
|
||||
{
|
||||
CELL method_cache = get(ds);
|
||||
CELL methods = get(ds - CELLS);
|
||||
CELL object = get(ds - CELLS * 2);
|
||||
ds -= CELLS * 2;
|
||||
drepl(lookup_method_with_cache(object,methods,method_cache));
|
||||
CELL methods = dpop();
|
||||
CELL object = dpop();
|
||||
dpush(lookup_method(object,methods));
|
||||
}
|
||||
|
||||
/* Next two functions are used for polymorphic inline caching */
|
||||
|
||||
CELL object_class(CELL object)
|
||||
{
|
||||
if(!HI_TAG_OR_TUPLE_P(object))
|
||||
|
@ -172,12 +126,35 @@ CELL object_class(CELL 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))
|
||||
return array_nth(untag_object(methods),TAG(object));
|
||||
else
|
||||
return lookup_hairy_method(object,methods);
|
||||
CELL capacity = (array_capacity(array) >> 1) - 1;
|
||||
return ((class >> TAG_BITS) & capacity) << 1;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -194,3 +171,32 @@ void primitive_dispatch_stats(void)
|
|||
GROWABLE_ARRAY_DONE(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]);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
CELL megamorphic_cache_hits;
|
||||
CELL megamorphic_cache_misses;
|
||||
|
||||
CELL lookup_method(CELL object, CELL methods);
|
||||
void primitive_lookup_method(void);
|
||||
|
||||
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_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);
|
||||
|
|
|
@ -183,7 +183,7 @@ void primitive_save_image_and_exit(void)
|
|||
for(i = 0; i < FIRST_SAVE_ENV; i++)
|
||||
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;
|
||||
|
||||
/* do a full GC + code heap compaction */
|
||||
|
|
|
@ -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);
|
||||
|
||||
/* Generate machine code to determine the object's class. */
|
||||
jit_emit_with(&jit,userenv[PIC_LOAD],tag_fixnum(-index * CELLS));
|
||||
jit_emit(&jit,userenv[inline_cache_type]);
|
||||
jit_emit_class_lookup(&jit,index,inline_cache_type);
|
||||
|
||||
/* Generate machine code to check, in turn, if the class is one of the cached entries. */
|
||||
CELL i;
|
||||
|
|
6
vm/jit.c
6
vm/jit.c
|
@ -1,5 +1,11 @@
|
|||
#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 */
|
||||
void jit_init(F_JIT *jit, CELL jit_type, CELL owner)
|
||||
{
|
||||
|
|
6
vm/jit.h
6
vm/jit.h
|
@ -45,6 +45,12 @@ INLINE void jit_word_jump(F_JIT *jit, CELL 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 */
|
||||
INLINE void jit_emit_subprimitive(F_JIT *jit, F_WORD *word)
|
||||
{
|
||||
|
|
|
@ -50,8 +50,8 @@
|
|||
#include "callstack.h"
|
||||
#include "alien.h"
|
||||
#include "quotations.h"
|
||||
#include "dispatch.h"
|
||||
#include "jit.h"
|
||||
#include "dispatch.h"
|
||||
#include "inline_cache.h"
|
||||
#include "factor.h"
|
||||
#include "utilities.h"
|
||||
|
|
|
@ -143,8 +143,9 @@ void *primitives[] = {
|
|||
primitive_jit_compile,
|
||||
primitive_load_locals,
|
||||
primitive_check_datastack,
|
||||
primitive_lookup_method,
|
||||
primitive_inline_cache_miss,
|
||||
primitive_mega_cache_miss,
|
||||
primitive_lookup_method,
|
||||
primitive_reset_dispatch_stats,
|
||||
primitive_dispatch_stats,
|
||||
primitive_reset_inline_cache_stats,
|
||||
|
|
|
@ -89,6 +89,15 @@ static bool jit_ignore_declare_p(F_ARRAY *array, CELL i)
|
|||
&& 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)
|
||||
{
|
||||
F_FIXNUM length = array_capacity(array);
|
||||
|
@ -189,7 +198,7 @@ void jit_compile(CELL quot, bool relocate)
|
|||
jit_word_jump(&jit,obj);
|
||||
}
|
||||
else
|
||||
jit_emit_with(&jit,userenv[JIT_WORD_CALL],obj);
|
||||
jit_word_call(&jit,obj);
|
||||
}
|
||||
break;
|
||||
case WRAPPER_TYPE:
|
||||
|
@ -257,6 +266,16 @@ void jit_compile(CELL quot, bool relocate)
|
|||
i++;
|
||||
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:
|
||||
jit_push(&jit,obj);
|
||||
break;
|
||||
|
|
11
vm/run.h
11
vm/run.h
|
@ -32,7 +32,7 @@ typedef enum {
|
|||
BOOT_ENV = 20, /* boot quotation */
|
||||
GLOBAL_ENV, /* global namespace */
|
||||
|
||||
/* Used by the JIT compiler */
|
||||
/* Quotation compilation in quotations.c */
|
||||
JIT_CODE_FORMAT = 22,
|
||||
JIT_PROLOG,
|
||||
JIT_PRIMITIVE_WORD,
|
||||
|
@ -60,7 +60,7 @@ typedef enum {
|
|||
JIT_EXECUTE_JUMP,
|
||||
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_TAG,
|
||||
PIC_HI_TAG,
|
||||
|
@ -71,7 +71,10 @@ typedef enum {
|
|||
PIC_HIT,
|
||||
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 */
|
||||
|
||||
|
@ -84,6 +87,8 @@ typedef enum {
|
|||
THREADS_ENV = 64,
|
||||
RUN_QUEUE_ENV = 65,
|
||||
SLEEP_QUEUE_ENV = 66,
|
||||
|
||||
STACK_TRACES_ENV = 67,
|
||||
} F_ENVTYPE;
|
||||
|
||||
#define FIRST_SAVE_ENV BOOT_ENV
|
||||
|
|
Loading…
Reference in New Issue