VM: Refactor quotations.cpp/hpp to Factor style

db4
Erik Charlebois 2013-05-11 22:27:06 -04:00
parent 4dffb25fe6
commit 435ac636c6
2 changed files with 297 additions and 338 deletions

View File

@ -1,12 +1,12 @@
#include "master.hpp" #include "master.hpp"
namespace factor namespace factor {
{
/* Simple non-optimizing compiler. /* Simple non-optimizing compiler.
This is one of the two compilers implementing Factor; the second one is written This is one of the two compilers implementing Factor; the second one is written
in Factor and performs advanced optimizations. See basis/compiler/compiler.factor. in Factor and performs advanced optimizations. See
basis/compiler/compiler.factor.
The non-optimizing compiler compiles a quotation at a time by concatenating The non-optimizing compiler compiles a quotation at a time by concatenating
machine code chunks; prolog, epilog, call word, jump to word, etc. These machine machine code chunks; prolog, epilog, call word, jump to word, etc. These machine
@ -36,420 +36,378 @@ includes stack shufflers, some fixnum arithmetic words, and words such as tag,
slot and eq?. A primitive call is relatively expensive (two subroutine calls) slot and eq?. A primitive call is relatively expensive (two subroutine calls)
so this results in a big speedup for relatively little effort. */ so this results in a big speedup for relatively little effort. */
void quotation_jit::init_quotation(cell quot) void quotation_jit::init_quotation(cell quot) {
{ elements = untag<quotation>(quot)->array;
elements = untag<quotation>(quot)->array;
} }
bool quotation_jit::primitive_call_p(cell i, cell length) bool quotation_jit::primitive_call_p(cell i, cell length) {
{ return (i + 2) <= length && array_nth(elements.untagged(), i + 1) ==
return (i + 2) <= length && array_nth(elements.untagged(),i + 1) == parent->special_objects[JIT_PRIMITIVE_WORD]; parent->special_objects[JIT_PRIMITIVE_WORD];
} }
bool quotation_jit::fast_if_p(cell i, cell length) bool quotation_jit::fast_if_p(cell i, cell length) {
{ return (i + 3) == length &&
return (i + 3) == length tagged<object>(array_nth(elements.untagged(), i + 1))
&& tagged<object>(array_nth(elements.untagged(),i + 1)).type_p(QUOTATION_TYPE) .type_p(QUOTATION_TYPE) &&
&& array_nth(elements.untagged(),i + 2) == parent->special_objects[JIT_IF_WORD]; array_nth(elements.untagged(), i + 2) ==
parent->special_objects[JIT_IF_WORD];
} }
bool quotation_jit::fast_dip_p(cell i, cell length) bool quotation_jit::fast_dip_p(cell i, cell length) {
{ return (i + 2) <= length && array_nth(elements.untagged(), i + 1) ==
return (i + 2) <= length && array_nth(elements.untagged(),i + 1) == parent->special_objects[JIT_DIP_WORD]; parent->special_objects[JIT_DIP_WORD];
} }
bool quotation_jit::fast_2dip_p(cell i, cell length) bool quotation_jit::fast_2dip_p(cell i, cell length) {
{ return (i + 2) <= length && array_nth(elements.untagged(), i + 1) ==
return (i + 2) <= length && array_nth(elements.untagged(),i + 1) == parent->special_objects[JIT_2DIP_WORD]; parent->special_objects[JIT_2DIP_WORD];
} }
bool quotation_jit::fast_3dip_p(cell i, cell length) bool quotation_jit::fast_3dip_p(cell i, cell length) {
{ return (i + 2) <= length && array_nth(elements.untagged(), i + 1) ==
return (i + 2) <= length && array_nth(elements.untagged(),i + 1) == parent->special_objects[JIT_3DIP_WORD]; parent->special_objects[JIT_3DIP_WORD];
} }
bool quotation_jit::mega_lookup_p(cell i, cell length) bool quotation_jit::mega_lookup_p(cell i, cell length) {
{ return (i + 4) <= length &&
return (i + 4) <= length tagged<object>(array_nth(elements.untagged(), i + 1))
&& tagged<object>(array_nth(elements.untagged(),i + 1)).type_p(FIXNUM_TYPE) .type_p(FIXNUM_TYPE) &&
&& tagged<object>(array_nth(elements.untagged(),i + 2)).type_p(ARRAY_TYPE) tagged<object>(array_nth(elements.untagged(), i + 2))
&& array_nth(elements.untagged(),i + 3) == parent->special_objects[MEGA_LOOKUP_WORD]; .type_p(ARRAY_TYPE) &&
array_nth(elements.untagged(), i + 3) ==
parent->special_objects[MEGA_LOOKUP_WORD];
} }
bool quotation_jit::declare_p(cell i, cell length) bool quotation_jit::declare_p(cell i, cell length) {
{ return (i + 2) <= length && array_nth(elements.untagged(), i + 1) ==
return (i + 2) <= length parent->special_objects[JIT_DECLARE_WORD];
&& array_nth(elements.untagged(),i + 1) == parent->special_objects[JIT_DECLARE_WORD];
} }
bool quotation_jit::special_subprimitive_p(cell obj) bool quotation_jit::special_subprimitive_p(cell obj) {
{ // Subprimitives should be flagged with whether they require a stack frame.
// Subprimitives should be flagged with whether they require a stack frame. // See #295.
// See #295. return obj == parent->special_objects[SIGNAL_HANDLER_WORD] ||
return obj == parent->special_objects[SIGNAL_HANDLER_WORD] obj == parent->special_objects[LEAF_SIGNAL_HANDLER_WORD] ||
|| obj == parent->special_objects[LEAF_SIGNAL_HANDLER_WORD] obj == parent->special_objects[FFI_SIGNAL_HANDLER_WORD] ||
|| obj == parent->special_objects[FFI_SIGNAL_HANDLER_WORD] obj == parent->special_objects[FFI_LEAF_SIGNAL_HANDLER_WORD] ||
|| obj == parent->special_objects[FFI_LEAF_SIGNAL_HANDLER_WORD] obj == parent->special_objects[UNWIND_NATIVE_FRAMES_WORD];
|| obj == parent->special_objects[UNWIND_NATIVE_FRAMES_WORD];
} }
bool quotation_jit::word_stack_frame_p(cell obj) bool quotation_jit::word_stack_frame_p(cell obj) {
{ return (to_boolean(untag<word>(obj)->subprimitive) &&
return (to_boolean(untag<word>(obj)->subprimitive) && !special_subprimitive_p(obj)) !special_subprimitive_p(obj)) ||
|| obj == parent->special_objects[JIT_PRIMITIVE_WORD]; obj == parent->special_objects[JIT_PRIMITIVE_WORD];
} }
bool quotation_jit::word_safepoint_p(cell obj) bool quotation_jit::word_safepoint_p(cell obj) {
{ return !special_subprimitive_p(obj);
return !special_subprimitive_p(obj);
} }
bool quotation_jit::safepoint_p() bool quotation_jit::safepoint_p() {
{ fixnum length = array_capacity(elements.untagged());
fixnum length = array_capacity(elements.untagged());
for(fixnum i = 0; i < length; i++) for (fixnum i = 0; i < length; i++) {
{ cell obj = array_nth(elements.untagged(), i);
cell obj = array_nth(elements.untagged(),i); switch (tagged<object>(obj).type()) {
switch(tagged<object>(obj).type()) case WORD_TYPE:
{ if (!word_safepoint_p(obj))
case WORD_TYPE: return false;
if(!word_safepoint_p(obj)) break;
return false; default:
break; break;
default: }
break; }
}
}
return true; return true;
} }
bool quotation_jit::stack_frame_p() bool quotation_jit::stack_frame_p() {
{ fixnum length = array_capacity(elements.untagged());
fixnum length = array_capacity(elements.untagged());
for(fixnum i = 0; i < length; i++) for (fixnum i = 0; i < length; i++) {
{ cell obj = array_nth(elements.untagged(), i);
cell obj = array_nth(elements.untagged(),i); if (tagged<object>(obj).type() == WORD_TYPE && !word_safepoint_p(obj))
if (tagged<object>(obj).type() == WORD_TYPE && !word_safepoint_p(obj)) return false;
return false; }
}
return true; return true;
} }
bool quotation_jit::trivial_quotation_p(array *elements) bool quotation_jit::trivial_quotation_p(array* elements) {
{ return array_capacity(elements) == 1 &&
return array_capacity(elements) == 1 && tagged<object>(array_nth(elements,0)).type_p(WORD_TYPE); tagged<object>(array_nth(elements, 0)).type_p(WORD_TYPE);
} }
void quotation_jit::emit_prolog(bool safepoint, bool stack_frame) void quotation_jit::emit_prolog(bool safepoint, bool stack_frame) {
{ if (safepoint)
if(safepoint) emit(parent->special_objects[JIT_SAFEPOINT]); emit(parent->special_objects[JIT_SAFEPOINT]);
if(stack_frame) emit(parent->special_objects[JIT_PROLOG]); if (stack_frame)
emit(parent->special_objects[JIT_PROLOG]);
} }
void quotation_jit::emit_epilog(bool safepoint, bool stack_frame) void quotation_jit::emit_epilog(bool safepoint, bool stack_frame) {
{ if (safepoint)
if(safepoint) emit(parent->special_objects[JIT_SAFEPOINT]); emit(parent->special_objects[JIT_SAFEPOINT]);
if(stack_frame) emit(parent->special_objects[JIT_EPILOG]); if (stack_frame)
emit(parent->special_objects[JIT_EPILOG]);
} }
/* Allocates memory conditionally */ /* Allocates memory conditionally */
void quotation_jit::emit_quot(cell quot_) void quotation_jit::emit_quot(cell quot_) {
{ data_root<quotation> quot(quot_, parent);
data_root<quotation> quot(quot_,parent);
array *elements = untag<array>(quot->array); array* elements = untag<array>(quot->array);
/* If the quotation consists of a single word, compile a direct call /* If the quotation consists of a single word, compile a direct call
to the word. */ to the word. */
if(trivial_quotation_p(elements)) if (trivial_quotation_p(elements))
literal(array_nth(elements,0)); literal(array_nth(elements, 0));
else else {
{ if (compiling)
if(compiling) parent->jit_compile_quot(quot.value(),relocate); parent->jit_compile_quot(quot.value(), relocate);
literal(quot.value()); literal(quot.value());
} }
} }
/* Allocates memory */ /* Allocates memory */
void quotation_jit::iterate_quotation() void quotation_jit::iterate_quotation() {
{ bool safepoint = safepoint_p();
bool safepoint = safepoint_p(); bool stack_frame = stack_frame_p();
bool stack_frame = stack_frame_p();
set_position(0); set_position(0);
emit_prolog(safepoint, stack_frame); emit_prolog(safepoint, stack_frame);
cell i; cell i;
cell length = array_capacity(elements.untagged()); cell length = array_capacity(elements.untagged());
bool tail_call = false; bool tail_call = false;
for(i = 0; i < length; i++) for (i = 0; i < length; i++) {
{ set_position(i);
set_position(i);
data_root<object> obj(array_nth(elements.untagged(),i),parent); data_root<object> obj(array_nth(elements.untagged(), i), parent);
switch(obj.type()) switch (obj.type()) {
{ case WORD_TYPE:
case WORD_TYPE: /* Sub-primitives */
/* Sub-primitives */ if (to_boolean(obj.as<word>()->subprimitive)) {
if(to_boolean(obj.as<word>()->subprimitive)) tail_call = emit_subprimitive(obj.value(), /* word */
{ i == length - 1, /* tail_call_p */
tail_call = emit_subprimitive(obj.value(), /* word */ stack_frame); /* stack_frame_p */
i == length - 1, /* tail_call_p */ } /* Everything else */
stack_frame); /* stack_frame_p */ else if (i == length - 1) {
} emit_epilog(safepoint, stack_frame);
/* Everything else */ tail_call = true;
else if(i == length - 1) word_jump(obj.value());
{ } else
emit_epilog(safepoint, stack_frame); word_call(obj.value());
tail_call = true; break;
word_jump(obj.value()); case WRAPPER_TYPE:
} push(obj.as<wrapper>()->object);
else break;
word_call(obj.value()); case BYTE_ARRAY_TYPE:
break; /* Primitive calls */
case WRAPPER_TYPE: if (primitive_call_p(i, length)) {
push(obj.as<wrapper>()->object); /* On x86-64 and PowerPC, the VM pointer is stored in
break; a register; on other platforms, the RT_VM relocation
case BYTE_ARRAY_TYPE: is used and it needs an offset parameter */
/* Primitive calls */
if(primitive_call_p(i,length))
{
/* On x86-64 and PowerPC, the VM pointer is stored in
a register; on other platforms, the RT_VM relocation
is used and it needs an offset parameter */
#ifdef FACTOR_X86 #ifdef FACTOR_X86
parameter(tag_fixnum(0)); parameter(tag_fixnum(0));
#endif #endif
parameter(obj.value()); parameter(obj.value());
parameter(false_object); parameter(false_object);
#ifdef FACTOR_PPC_TOC #ifdef FACTOR_PPC_TOC
parameter(obj.value()); parameter(obj.value());
parameter(false_object); parameter(false_object);
#endif #endif
emit(parent->special_objects[JIT_PRIMITIVE]); emit(parent->special_objects[JIT_PRIMITIVE]);
i++; i++;
} } else
else push(obj.value());
push(obj.value()); break;
break; case QUOTATION_TYPE:
case QUOTATION_TYPE: /* 'if' preceded by two literal quotations (this is why if and ? are
/* 'if' preceded by two literal quotations (this is why if and ? are mutually recursive in the library, but both still work) */
mutually recursive in the library, but both still work) */ if (fast_if_p(i, length)) {
if(fast_if_p(i,length)) emit_epilog(safepoint, stack_frame);
{ tail_call = true;
emit_epilog(safepoint, stack_frame);
tail_call = true;
emit_quot(array_nth(elements.untagged(),i)); emit_quot(array_nth(elements.untagged(), i));
emit_quot(array_nth(elements.untagged(),i + 1)); emit_quot(array_nth(elements.untagged(), i + 1));
emit(parent->special_objects[JIT_IF]); emit(parent->special_objects[JIT_IF]);
i += 2; i += 2;
} } /* dip */
/* dip */ else if (fast_dip_p(i, length)) {
else if(fast_dip_p(i,length)) emit_quot(obj.value());
{ emit(parent->special_objects[JIT_DIP]);
emit_quot(obj.value()); i++;
emit(parent->special_objects[JIT_DIP]); } /* 2dip */
i++; else if (fast_2dip_p(i, length)) {
} emit_quot(obj.value());
/* 2dip */ emit(parent->special_objects[JIT_2DIP]);
else if(fast_2dip_p(i,length)) i++;
{ } /* 3dip */
emit_quot(obj.value()); else if (fast_3dip_p(i, length)) {
emit(parent->special_objects[JIT_2DIP]); emit_quot(obj.value());
i++; emit(parent->special_objects[JIT_3DIP]);
} i++;
/* 3dip */ } else
else if(fast_3dip_p(i,length)) push(obj.value());
{ break;
emit_quot(obj.value()); case ARRAY_TYPE:
emit(parent->special_objects[JIT_3DIP]); /* Method dispatch */
i++; if (mega_lookup_p(i, length)) {
} fixnum index = untag_fixnum(array_nth(elements.untagged(), i + 1));
else /* Load the object from the datastack, then remove our stack frame. */
push(obj.value()); emit_with_literal(parent->special_objects[PIC_LOAD],
break; tag_fixnum(-index * sizeof(cell)));
case ARRAY_TYPE: emit_epilog(safepoint, stack_frame);
/* Method dispatch */ tail_call = true;
if(mega_lookup_p(i,length))
{
fixnum index = untag_fixnum(array_nth(elements.untagged(),i + 1));
/* Load the object from the datastack, then remove our stack frame. */
emit_with_literal(parent->special_objects[PIC_LOAD],tag_fixnum(-index * sizeof(cell)));
emit_epilog(safepoint, stack_frame);
tail_call = true;
emit_mega_cache_lookup( emit_mega_cache_lookup(array_nth(elements.untagged(), i), index,
array_nth(elements.untagged(),i), array_nth(elements.untagged(), i + 2));
index, i += 3;
array_nth(elements.untagged(),i + 2)); } /* Non-optimizing compiler ignores declarations */
i += 3; else if (declare_p(i, length))
} i++;
/* Non-optimizing compiler ignores declarations */ else
else if(declare_p(i,length)) push(obj.value());
i++; break;
else default:
push(obj.value()); push(obj.value());
break; break;
default: }
push(obj.value()); }
break;
}
}
if(!tail_call) if (!tail_call) {
{ set_position(length);
set_position(length);
emit_epilog(safepoint, stack_frame); emit_epilog(safepoint, stack_frame);
emit(parent->special_objects[JIT_RETURN]); emit(parent->special_objects[JIT_RETURN]);
} }
} }
cell quotation_jit::word_stack_frame_size(cell obj) cell quotation_jit::word_stack_frame_size(cell obj) {
{ if (special_subprimitive_p(obj))
if (special_subprimitive_p(obj)) return SIGNAL_HANDLER_STACK_FRAME_SIZE;
return SIGNAL_HANDLER_STACK_FRAME_SIZE; else
else return JIT_FRAME_SIZE;
return JIT_FRAME_SIZE;
} }
/* Allocates memory */ /* Allocates memory */
code_block *factor_vm::jit_compile_quot(cell owner_, cell quot_, bool relocating) code_block* factor_vm::jit_compile_quot(cell owner_, cell quot_,
{ bool relocating) {
data_root<object> owner(owner_,this); data_root<object> owner(owner_, this);
data_root<quotation> quot(quot_,this); data_root<quotation> quot(quot_, this);
quotation_jit compiler(owner.value(),true,relocating,this); quotation_jit compiler(owner.value(), true, relocating, this);
compiler.init_quotation(quot.value()); compiler.init_quotation(quot.value());
compiler.iterate_quotation(); compiler.iterate_quotation();
cell frame_size = compiler.word_stack_frame_size(owner_); cell frame_size = compiler.word_stack_frame_size(owner_);
code_block *compiled = compiler.to_code_block(frame_size); code_block* compiled = compiler.to_code_block(frame_size);
if(relocating) initialize_code_block(compiled); if (relocating)
initialize_code_block(compiled);
return compiled; return compiled;
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::jit_compile_quot(cell quot_, bool relocating) void factor_vm::jit_compile_quot(cell quot_, bool relocating) {
{ data_root<quotation> quot(quot_, this);
data_root<quotation> quot(quot_,this); if (!quot_compiled_p(quot.untagged())) {
if(!quot_compiled_p(quot.untagged())) code_block* compiled =
{ jit_compile_quot(quot.value(), quot.value(), relocating);
code_block *compiled = jit_compile_quot(quot.value(),quot.value(),relocating); quot.untagged()->entry_point = compiled->entry_point();
quot.untagged()->entry_point = compiled->entry_point(); }
}
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::primitive_jit_compile() void factor_vm::primitive_jit_compile() { jit_compile_quot(ctx->pop(), true); }
{
jit_compile_quot(ctx->pop(),true);
}
void *factor_vm::lazy_jit_compile_entry_point() void* factor_vm::lazy_jit_compile_entry_point() {
{ return untag<word>(special_objects[LAZY_JIT_COMPILE_WORD])->entry_point;
return untag<word>(special_objects[LAZY_JIT_COMPILE_WORD])->entry_point;
} }
/* push a new quotation on the stack */ /* push a new quotation on the stack */
/* Allocates memory */ /* Allocates memory */
void factor_vm::primitive_array_to_quotation() void factor_vm::primitive_array_to_quotation() {
{ quotation* quot = allot<quotation>(sizeof(quotation));
quotation *quot = allot<quotation>(sizeof(quotation));
quot->array = ctx->peek(); quot->array = ctx->peek();
quot->cached_effect = false_object; quot->cached_effect = false_object;
quot->cache_counter = false_object; quot->cache_counter = false_object;
quot->entry_point = lazy_jit_compile_entry_point(); quot->entry_point = lazy_jit_compile_entry_point();
ctx->replace(tag<quotation>(quot)); ctx->replace(tag<quotation>(quot));
} }
/* Allocates memory (from_unsigned_cell) */ /* Allocates memory (from_unsigned_cell) */
void factor_vm::primitive_quotation_code() void factor_vm::primitive_quotation_code() {
{ data_root<quotation> quot(ctx->pop(), this);
data_root<quotation> quot(ctx->pop(),this);
ctx->push(from_unsigned_cell((cell)quot->entry_point)); ctx->push(from_unsigned_cell((cell) quot->entry_point));
ctx->push(from_unsigned_cell((cell)quot->code() + quot->code()->size())); ctx->push(from_unsigned_cell((cell) quot->code() + quot->code()->size()));
} }
/* Allocates memory */ /* Allocates memory */
fixnum factor_vm::quot_code_offset_to_scan(cell quot_, cell offset) fixnum factor_vm::quot_code_offset_to_scan(cell quot_, cell offset) {
{ data_root<quotation> quot(quot_, this);
data_root<quotation> quot(quot_,this); data_root<array> array(quot->array, this);
data_root<array> array(quot->array,this);
quotation_jit compiler(quot.value(),false,false,this); quotation_jit compiler(quot.value(), false, false, this);
compiler.init_quotation(quot.value()); compiler.init_quotation(quot.value());
compiler.compute_position(offset); compiler.compute_position(offset);
compiler.iterate_quotation(); compiler.iterate_quotation();
return compiler.get_position(); return compiler.get_position();
} }
/* Allocates memory */ /* Allocates memory */
cell factor_vm::lazy_jit_compile(cell quot_) cell factor_vm::lazy_jit_compile(cell quot_) {
{ data_root<quotation> quot(quot_, this);
data_root<quotation> quot(quot_,this);
FACTOR_ASSERT(!quot_compiled_p(quot.untagged())); FACTOR_ASSERT(!quot_compiled_p(quot.untagged()));
code_block *compiled = jit_compile_quot(quot.value(),quot.value(),true); code_block* compiled = jit_compile_quot(quot.value(), quot.value(), true);
quot.untagged()->entry_point = compiled->entry_point(); quot.untagged()->entry_point = compiled->entry_point();
return quot.value(); return quot.value();
} }
/* Allocates memory */ /* Allocates memory */
VM_C_API cell lazy_jit_compile(cell quot, factor_vm *parent) VM_C_API cell lazy_jit_compile(cell quot, factor_vm* parent) {
{ return parent->lazy_jit_compile(quot);
return parent->lazy_jit_compile(quot);
} }
bool factor_vm::quot_compiled_p(quotation *quot) bool factor_vm::quot_compiled_p(quotation* quot) {
{ return quot->entry_point != NULL &&
return quot->entry_point != NULL && quot->entry_point != lazy_jit_compile_entry_point(); quot->entry_point != lazy_jit_compile_entry_point();
} }
void factor_vm::primitive_quot_compiled_p() void factor_vm::primitive_quot_compiled_p() {
{ tagged<quotation> quot(ctx->pop());
tagged<quotation> quot(ctx->pop()); quot.untag_check(this);
quot.untag_check(this); ctx->push(tag_boolean(quot_compiled_p(quot.untagged())));
ctx->push(tag_boolean(quot_compiled_p(quot.untagged())));
} }
/* Allocates memory */ /* Allocates memory */
cell factor_vm::find_all_quotations() cell factor_vm::find_all_quotations() { return instances(QUOTATION_TYPE); }
{
return instances(QUOTATION_TYPE);
}
/* Allocates memory */ /* Allocates memory */
void factor_vm::initialize_all_quotations() void factor_vm::initialize_all_quotations() {
{ data_root<array> quotations(find_all_quotations(), this);
data_root<array> quotations(find_all_quotations(),this);
cell length = array_capacity(quotations.untagged()); cell length = array_capacity(quotations.untagged());
for(cell i = 0; i < length; i++) for (cell i = 0; i < length; i++) {
{ data_root<quotation> quot(array_nth(quotations.untagged(), i), this);
data_root<quotation> quot(array_nth(quotations.untagged(),i),this); if (!quot->entry_point)
if(!quot->entry_point) quot.untagged()->entry_point = lazy_jit_compile_entry_point();
quot.untagged()->entry_point = lazy_jit_compile_entry_point(); }
}
} }
} }

View File

@ -1,38 +1,39 @@
namespace factor namespace factor {
{
struct quotation_jit : public jit { struct quotation_jit : public jit {
data_root<array> elements; data_root<array> elements;
bool compiling, relocate; bool compiling, relocate;
explicit quotation_jit(cell owner, bool compiling_, bool relocate_, factor_vm *vm) explicit quotation_jit(cell owner, bool compiling_, bool relocate_,
: jit(code_block_unoptimized,owner,vm), factor_vm* vm)
elements(false_object,vm), : jit(code_block_unoptimized, owner, vm),
compiling(compiling_), elements(false_object, vm),
relocate(relocate_){}; compiling(compiling_),
relocate(relocate_) {}
;
void init_quotation(cell quot); void init_quotation(cell quot);
void emit_mega_cache_lookup(cell methods, fixnum index, cell cache); void emit_mega_cache_lookup(cell methods, fixnum index, cell cache);
bool primitive_call_p(cell i, cell length); bool primitive_call_p(cell i, cell length);
bool trivial_quotation_p(array *elements); bool trivial_quotation_p(array* elements);
void emit_quot(cell quot); void emit_quot(cell quot);
void emit_prolog(bool safepoint, bool stack_frame); void emit_prolog(bool safepoint, bool stack_frame);
void emit_epilog(bool safepoint, bool stack_frame); void emit_epilog(bool safepoint, bool stack_frame);
bool fast_if_p(cell i, cell length); bool fast_if_p(cell i, cell length);
bool fast_dip_p(cell i, cell length); bool fast_dip_p(cell i, cell length);
bool fast_2dip_p(cell i, cell length); bool fast_2dip_p(cell i, cell length);
bool fast_3dip_p(cell i, cell length); bool fast_3dip_p(cell i, cell length);
bool mega_lookup_p(cell i, cell length); bool mega_lookup_p(cell i, cell length);
bool declare_p(cell i, cell length); bool declare_p(cell i, cell length);
bool special_subprimitive_p(cell obj); bool special_subprimitive_p(cell obj);
bool word_stack_frame_p(cell obj); bool word_stack_frame_p(cell obj);
cell word_stack_frame_size(cell obj); cell word_stack_frame_size(cell obj);
bool word_safepoint_p(cell obj); bool word_safepoint_p(cell obj);
bool stack_frame_p(); bool stack_frame_p();
bool safepoint_p(); bool safepoint_p();
void iterate_quotation(); void iterate_quotation();
}; };
VM_C_API cell lazy_jit_compile(cell quot, factor_vm *parent); VM_C_API cell lazy_jit_compile(cell quot, factor_vm* parent);
} }