Early binding JIT work in progress
parent
c09af2f2c6
commit
4bb2a43a10
|
@ -50,17 +50,15 @@ big-endian off
|
|||
] rc-relative rt-primitive 12 jit-word-primitive-call jit-define
|
||||
|
||||
[
|
||||
arg0 scan-reg bootstrap-cell [+] MOV ! load word
|
||||
arg0 word-xt@ [+] JMP ! jump to word XT
|
||||
] f f f jit-word-jump jit-define
|
||||
(JMP) drop
|
||||
] rc-relative rt-xt 1 jit-word-jump jit-define
|
||||
|
||||
[
|
||||
advance-scan
|
||||
scan-save scan-reg MOV ! save scan pointer
|
||||
arg0 scan-reg [] MOV ! load word
|
||||
arg0 word-xt@ [+] CALL ! call word XT
|
||||
(CALL) drop
|
||||
scan-reg scan-save MOV ! restore scan pointer
|
||||
] f f f jit-word-call jit-define
|
||||
] rc-relative rt-xt 8 jit-word-call jit-define
|
||||
|
||||
[
|
||||
arg1 0 MOV ! load addr of true quotation
|
||||
|
|
|
@ -378,7 +378,7 @@ void forward_object_xts(void)
|
|||
{
|
||||
F_WORD *word = untag_object(obj);
|
||||
|
||||
if(word->compiledp != F)
|
||||
if(word_references_code_heap_p(word))
|
||||
word->code = forward_xt(word->code);
|
||||
}
|
||||
else if(type_of(obj) == QUOTATION_TYPE)
|
||||
|
@ -414,6 +414,8 @@ void fixup_object_xts(void)
|
|||
|
||||
if(word->compiledp != F)
|
||||
set_word_xt(word,word->code);
|
||||
else
|
||||
word->xt = word->code + sizeof(F_COMPILED);
|
||||
}
|
||||
else if(type_of(obj) == QUOTATION_TYPE)
|
||||
{
|
||||
|
|
|
@ -38,11 +38,6 @@ void *get_rel_symbol(F_REL *rel, CELL literals_start)
|
|||
|
||||
static CELL xt_offset;
|
||||
|
||||
void incompatible_call_error(void)
|
||||
{
|
||||
critical_error("Calling non-optimized word from optimized word",0);
|
||||
}
|
||||
|
||||
/* Compute an address to store at a relocation */
|
||||
INLINE CELL compute_code_rel(F_REL *rel,
|
||||
CELL code_start, CELL literals_start, CELL words_start)
|
||||
|
@ -62,15 +57,12 @@ INLINE CELL compute_code_rel(F_REL *rel,
|
|||
case RT_XT:
|
||||
word = untag_word(get(CREF(words_start,REL_ARGUMENT(rel))));
|
||||
if(word->compiledp == F)
|
||||
return (CELL)incompatible_call_error;
|
||||
return (CELL)word->code + sizeof(F_COMPILED);
|
||||
else
|
||||
return (CELL)word->code + sizeof(F_COMPILED) + xt_offset;
|
||||
case RT_XT_PROFILING:
|
||||
word = untag_word(get(CREF(words_start,REL_ARGUMENT(rel))));
|
||||
if(word->compiledp == F)
|
||||
return (CELL)incompatible_call_error;
|
||||
else
|
||||
return (CELL)word->code + sizeof(F_COMPILED);
|
||||
return (CELL)word->code + sizeof(F_COMPILED);
|
||||
case RT_LABEL:
|
||||
return code_start + REL_ARGUMENT(rel);
|
||||
default:
|
||||
|
@ -347,7 +339,19 @@ DEFINE_PRIMITIVE(modify_code_heap)
|
|||
if(data == F)
|
||||
{
|
||||
word->compiledp = F;
|
||||
word->xt = default_word_xt(word);
|
||||
|
||||
if(type_of(word->def) == QUOTATION_TYPE)
|
||||
{
|
||||
REGISTER_UNTAGGED(alist);
|
||||
REGISTER_UNTAGGED(word);
|
||||
|
||||
jit_compile(word->def);
|
||||
|
||||
UNREGISTER_UNTAGGED(word);
|
||||
UNREGISTER_UNTAGGED(alist);
|
||||
}
|
||||
|
||||
default_word_xt(word);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -557,7 +557,7 @@ CELL collect_next(CELL scan)
|
|||
{
|
||||
case WORD_TYPE:
|
||||
word = (F_WORD *)scan;
|
||||
if(collecting_code && word->compiledp != F)
|
||||
if(collecting_code && word_references_code_heap_p(word))
|
||||
recursive_mark(compiled_to_block(word->code));
|
||||
break;
|
||||
case QUOTATION_TYPE:
|
||||
|
|
36
vm/factor.c
36
vm/factor.c
|
@ -29,6 +29,39 @@ void default_parameters(F_PARAMETERS *p)
|
|||
p->console = false;
|
||||
}
|
||||
|
||||
/* Do some initialization that we do once only */
|
||||
void do_stage1_init(void)
|
||||
{
|
||||
fprintf(stderr,"*** Starting stage 2 early init...\n");
|
||||
fflush(stderr);
|
||||
|
||||
begin_scan();
|
||||
|
||||
CELL obj;
|
||||
while((obj = next_object()) != F)
|
||||
{
|
||||
if(type_of(obj) == WORD_TYPE)
|
||||
{
|
||||
F_WORD *word = untag_object(obj);
|
||||
if(type_of(word->def) == QUOTATION_TYPE)
|
||||
{
|
||||
jit_compile(word->def);
|
||||
default_word_xt(word);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* End heap scan */
|
||||
gc_off = false;
|
||||
|
||||
iterate_code_heap(finalize_code_block);
|
||||
|
||||
userenv[STAGE2_ENV] = T;
|
||||
|
||||
fprintf(stderr,"*** Finished stage 2 early init\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
/* Get things started */
|
||||
void init_factor(F_PARAMETERS *p)
|
||||
{
|
||||
|
@ -69,6 +102,9 @@ void init_factor(F_PARAMETERS *p)
|
|||
|
||||
/* We can GC now */
|
||||
gc_off = false;
|
||||
|
||||
if(!stage2)
|
||||
do_stage1_init();
|
||||
}
|
||||
|
||||
INLINE bool factor_arg(const F_CHAR* str, const F_CHAR* arg, CELL* value)
|
||||
|
|
23
vm/image.c
23
vm/image.c
|
@ -9,6 +9,8 @@ void init_objects(F_HEADER *h)
|
|||
bignum_zero = h->bignum_zero;
|
||||
bignum_pos_one = h->bignum_pos_one;
|
||||
bignum_neg_one = h->bignum_neg_one;
|
||||
|
||||
stage2 = (userenv[STAGE2_ENV] != F);
|
||||
}
|
||||
|
||||
INLINE void load_data_heap(FILE *file, F_HEADER *h, F_PARAMETERS *p)
|
||||
|
@ -176,12 +178,25 @@ void fixup_word(F_WORD *word)
|
|||
/* If this is a compiled word, relocate the code pointer. Otherwise,
|
||||
reset it based on the primitive number of the word. */
|
||||
if(word->compiledp == F)
|
||||
word->xt = default_word_xt(word);
|
||||
else
|
||||
{
|
||||
code_fixup((CELL)&word->xt);
|
||||
code_fixup((CELL)&word->code);
|
||||
if(type_of(word->def) == QUOTATION_TYPE)
|
||||
{
|
||||
if(!stage2)
|
||||
{
|
||||
/* Word XTs are fixed up in do_stage1_init() */
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primitive or undefined */
|
||||
default_word_xt(word);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
code_fixup((CELL)&word->xt);
|
||||
code_fixup((CELL)&word->code);
|
||||
}
|
||||
|
||||
void fixup_quotation(F_QUOTATION *quot)
|
||||
|
|
|
@ -8,16 +8,13 @@ bool profiling_p(void)
|
|||
void profiling_word(F_WORD *word)
|
||||
{
|
||||
/* If we just enabled the profiler, reset call count */
|
||||
if(profiling_p())
|
||||
word->counter = tag_fixnum(0);
|
||||
|
||||
if(word->compiledp == F)
|
||||
{
|
||||
if(type_of(word->def) == QUOTATION_TYPE)
|
||||
word->xt = default_word_xt(word);
|
||||
}
|
||||
else
|
||||
set_word_xt(word,word->code);
|
||||
// if(profiling_p())
|
||||
// word->counter = tag_fixnum(0);
|
||||
//
|
||||
// if(word->compiledp == F)
|
||||
// default_word_xt(word);
|
||||
// else
|
||||
// set_word_xt(word,word->code);
|
||||
}
|
||||
|
||||
void set_profiling(bool profiling)
|
||||
|
|
|
@ -90,6 +90,9 @@ void set_quot_xt(F_QUOTATION *quot, F_COMPILED *code)
|
|||
/* Might GC */
|
||||
void jit_compile(CELL quot)
|
||||
{
|
||||
if(untag_quotation(quot)->compiledp != F)
|
||||
return;
|
||||
|
||||
CELL code_format = compiled_code_format();
|
||||
|
||||
REGISTER_ROOT(quot);
|
||||
|
@ -149,7 +152,11 @@ void jit_compile(CELL quot)
|
|||
to_fixnum(word->def));
|
||||
}
|
||||
else
|
||||
EMIT(JIT_WORD_JUMP,0);
|
||||
{
|
||||
GROWABLE_ADD(words,array_nth(untag_object(array),i));
|
||||
EMIT(JIT_WORD_JUMP,words_count - 1);
|
||||
}
|
||||
|
||||
tail_call = true;
|
||||
}
|
||||
else
|
||||
|
@ -160,7 +167,10 @@ void jit_compile(CELL quot)
|
|||
to_fixnum(word->def));
|
||||
}
|
||||
else
|
||||
EMIT(JIT_WORD_CALL,0);
|
||||
{
|
||||
GROWABLE_ADD(words,array_nth(untag_object(array),i));
|
||||
EMIT(JIT_WORD_CALL,words_count - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WRAPPER_TYPE:
|
||||
|
|
22
vm/run.c
22
vm/run.c
|
@ -259,19 +259,27 @@ DEFINE_PRIMITIVE(set_retainstack)
|
|||
rs = array_to_stack(untag_array(dpop()),rs_bot);
|
||||
}
|
||||
|
||||
XT default_word_xt(F_WORD *word)
|
||||
void default_word_xt(F_WORD *word)
|
||||
{
|
||||
if(type_of(word->def) == QUOTATION_TYPE)
|
||||
{
|
||||
if(profiling_p())
|
||||
return docol_profiling;
|
||||
else
|
||||
return docol;
|
||||
F_QUOTATION *quot = untag_quotation(word->def);
|
||||
if(quot->compiledp == F)
|
||||
critical_error("default_word_xt invariant lost",0);
|
||||
word->xt = quot->xt;
|
||||
word->code = quot->code;
|
||||
|
||||
//if(profiling_p())
|
||||
// word->xt = docol_profiling;
|
||||
//else
|
||||
// word->xt = docol;
|
||||
}
|
||||
else if(type_of(word->def) == FIXNUM_TYPE)
|
||||
return primitives[to_fixnum(word->def)];
|
||||
word->xt = primitives[to_fixnum(word->def)];
|
||||
else if(word->def == F)
|
||||
word->xt = undefined;
|
||||
else
|
||||
return undefined;
|
||||
critical_error("bad word-def",tag_object(word));
|
||||
}
|
||||
|
||||
DEFINE_PRIMITIVE(getenv)
|
||||
|
|
22
vm/run.h
22
vm/run.h
|
@ -7,21 +7,21 @@ typedef enum {
|
|||
CURRENT_CALLBACK_ENV = 2, /* used by library only, per-callback */
|
||||
WALKER_HOOK_ENV, /* non-local exit hook, used by library only */
|
||||
CALLCC_1_ENV, /* used to pass the value in callcc1 */
|
||||
|
||||
|
||||
BREAK_ENV = 5, /* quotation called by throw primitive */
|
||||
ERROR_ENV, /* a marker consed onto kernel errors */
|
||||
|
||||
|
||||
CELL_SIZE_ENV = 7, /* sizeof(CELL) */
|
||||
CPU_ENV, /* CPU architecture */
|
||||
OS_ENV, /* operating system name */
|
||||
|
||||
|
||||
ARGS_ENV = 10, /* command line arguments */
|
||||
IN_ENV, /* stdin FILE* handle */
|
||||
OUT_ENV, /* stdout FILE* handle */
|
||||
|
||||
|
||||
IMAGE_ENV = 13, /* image path name */
|
||||
EXECUTABLE_ENV, /* runtime executable path name */
|
||||
|
||||
|
||||
EMBEDDED_ENV = 15, /* are we embedded in another app? */
|
||||
EVAL_CALLBACK_ENV, /* used when Factor is embedded in a C app */
|
||||
YIELD_CALLBACK_ENV, /* used when Factor is embedded in a C app */
|
||||
|
@ -40,18 +40,20 @@ typedef enum {
|
|||
JIT_WORD_PRIMITIVE_CALL,
|
||||
JIT_WORD_JUMP,
|
||||
JIT_WORD_CALL,
|
||||
JIT_PUSH_WRAPPER,
|
||||
UNUSED_1,
|
||||
JIT_PUSH_LITERAL,
|
||||
JIT_IF_WORD,
|
||||
JIT_IF_JUMP,
|
||||
JIT_IF_CALL,
|
||||
UNUSED_2,
|
||||
JIT_DISPATCH_WORD,
|
||||
JIT_DISPATCH,
|
||||
JIT_EPILOG,
|
||||
JIT_RETURN,
|
||||
|
||||
/* Profiler support */
|
||||
/* Profiler support */
|
||||
PROFILING_ENV = 38, /* is the profiler on? */
|
||||
|
||||
STAGE2_ENV = 39 /* Have we bootstrapped? */
|
||||
} F_ENVTYPE;
|
||||
|
||||
#define FIRST_SAVE_ENV BOOT_ENV
|
||||
|
@ -223,7 +225,7 @@ DECLARE_PRIMITIVE(from_r);
|
|||
DECLARE_PRIMITIVE(datastack);
|
||||
DECLARE_PRIMITIVE(retainstack);
|
||||
|
||||
XT default_word_xt(F_WORD *word);
|
||||
void default_word_xt(F_WORD *word);
|
||||
|
||||
DECLARE_PRIMITIVE(execute);
|
||||
DECLARE_PRIMITIVE(call);
|
||||
|
@ -240,3 +242,5 @@ DECLARE_PRIMITIVE(tag);
|
|||
DECLARE_PRIMITIVE(class_hash);
|
||||
DECLARE_PRIMITIVE(slot);
|
||||
DECLARE_PRIMITIVE(set_slot);
|
||||
|
||||
bool stage2;
|
||||
|
|
|
@ -463,7 +463,7 @@ F_WORD *allot_word(CELL vocab, CELL name)
|
|||
word->props = F;
|
||||
word->counter = tag_fixnum(0);
|
||||
word->compiledp = F;
|
||||
word->xt = default_word_xt(word);
|
||||
word->xt = undefined;
|
||||
return word;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,6 +109,11 @@ INLINE F_QUOTATION *untag_quotation(CELL tagged)
|
|||
return untag_object(tagged);
|
||||
}
|
||||
|
||||
INLINE bool word_references_code_heap_p(F_WORD *word)
|
||||
{
|
||||
return (word->compiledp != F || type_of(word->def) == QUOTATION_TYPE);
|
||||
}
|
||||
|
||||
INLINE F_WORD *untag_word(CELL tagged)
|
||||
{
|
||||
type_check(WORD_TYPE,tagged);
|
||||
|
|
Loading…
Reference in New Issue