This makes the separate "code" and "entry_point" fields in word and quotation redundant, so also remove them to reclaim an additional cell per word and quotation object, which should help with #318.
vm/code_heap.o \
vm/compaction.o \
vm/contexts.o \
- vm/counting_profiler.o \
vm/data_heap.o \
vm/data_heap_checker.o \
vm/debug.o \
vm/contexts.hpp \
vm/run.hpp \
vm/objects.hpp \
- vm/counting_profiler.hpp \
vm/sampling_profiler.hpp \
vm/errors.hpp \
vm/bignumint.hpp \
vm\code_heap.obj \
vm\compaction.obj \
vm\contexts.obj \
- vm\counting_profiler.obj \
vm\data_heap.obj \
vm\data_heap_checker.obj \
vm\debug.obj \
[ props>> , ]
[ pic-def>> , ]
[ pic-tail-def>> , ]
- [ drop 0 , ] ! count
[ word-sub-primitive , ]
- [ drop 0 , ] ! xt
- [ drop 0 , ] ! code
- [ drop 0 , ] ! profiling
+ [ drop 0 , ] ! entry point
} cleave
] { } make [ ' ] map
] bi
emit ! array
f ' emit ! cached-effect
f ' emit ! cache-counter
- 0 emit ! xt
- 0 emit ! code
+ 0 emit ! entry point
] emit-object
] cache-eql-object ;
: alien-offset ( -- n ) 4 alien type-number slot-offset ; inline
: underlying-alien-offset ( -- n ) 1 alien type-number slot-offset ; inline
: tuple-class-offset ( -- n ) 1 tuple type-number slot-offset ; inline
-: word-entry-point-offset ( -- n ) 10 \ word type-number slot-offset ; inline
+: word-entry-point-offset ( -- n ) 9 \ word type-number slot-offset ; inline
: quot-entry-point-offset ( -- n ) 4 quotation type-number slot-offset ; inline
-: word-code-offset ( -- n ) 11 \ word type-number slot-offset ; inline
+: code-block-entry-point-offset ( -- n ) 4 bootstrap-cells ; inline
: array-start-offset ( -- n ) 2 array type-number slot-offset ; inline
: compiled-header-size ( -- n ) 4 bootstrap-cells ; inline
: callstack-length-offset ( -- n ) 1 \ callstack type-number slot-offset ; inline
HEX: ffff RET f rc-absolute-2 rel-untagged
] callback-stub jit-define
-[
- ! Load word
- temp0 0 MOV f rc-absolute-cell rel-literal
- ! Bump profiling counter
- temp0 profile-count-offset [+] 1 tag-fixnum ADD
- ! Load word->code
- temp0 temp0 word-code-offset [+] MOV
- ! Compute word entry point
- temp0 compiled-header-size ADD
- ! Jump to entry point
- temp0 JMP
-] jit-profiling jit-define
-
[
! load literal
temp0 0 MOV f rc-absolute-cell rel-literal
"props"
"pic-def"
"pic-tail-def"
- { "counter" { "fixnum" "math" } }
{ "sub-primitive" read-only }
} define-builtin
case WORD_TYPE:
{
word *w = (word *)obj;
- if(w->code)
- w->code = visit_code_block(w->code);
- if(w->counting_profiler)
- w->counting_profiler = visit_code_block(w->counting_profiler);
-
- parent->update_word_entry_point(w);
+ if(w->entry_point)
+ w->entry_point = visit_code_block(w->code())->entry_point();
break;
}
case QUOTATION_TYPE:
{
quotation *q = (quotation *)obj;
- if(q->code)
- parent->set_quot_entry_point(q,visit_code_block(q->code));
+ if(q->entry_point)
+ q->entry_point = visit_code_block(q->code())->entry_point();
break;
}
case CALLSTACK_TYPE:
};
VM_C_API void undefined_symbol(void);
+
+inline code_block *word::code() const {
+ assert(entry_point != NULL);
+ return (code_block*)entry_point - 1;
+}
+
+inline code_block *quotation::code() const {
+ assert(entry_point != NULL);
+ return (code_block*)entry_point - 1;
}
+
+}
+
+
parameters,
literals);
- word->code = compiled;
+ word->entry_point = compiled->entry_point();
}
break;
default:
critical_error("Expected a quotation or an array",data.value());
break;
}
-
- update_word_entry_point(word.untagged());
}
if(update_existing_words)
+++ /dev/null
-#include "master.hpp"
-
-namespace factor
-{
-
-void factor_vm::init_counting_profiler()
-{
- counting_profiler_p = false;
-}
-
-/* Allocates memory */
-code_block *factor_vm::compile_counting_profiler_stub(cell word_)
-{
- data_root<word> word(word_,this);
-
- jit jit(code_block_counting_profiler,word.value(),this);
- jit.emit_with_literal(special_objects[JIT_PROFILING],word.value());
-
- return jit.to_code_block();
-}
-
-/* Allocates memory */
-void factor_vm::set_counting_profiler(bool counting_profiler)
-{
- if(counting_profiler == counting_profiler_p)
- return;
-
- /* Push everything to tenured space so that we can heap scan
- and allocate counting_profiler blocks if necessary */
- primitive_full_gc();
-
- data_root<array> words(find_all_words(),this);
-
- counting_profiler_p = counting_profiler;
-
- cell length = array_capacity(words.untagged());
- for(cell i = 0; i < length; i++)
- {
- tagged<word> word(array_nth(words.untagged(),i));
-
- /* Note: can't do w->counting_profiler = ... since LHS evaluates
- before RHS, and if RHS does a GC, we will have an
- invalid pointer on the LHS */
- if(counting_profiler)
- {
- if(!word->counting_profiler)
- {
- code_block *counting_profiler_block = compile_counting_profiler_stub(word.value());
- word->counting_profiler = counting_profiler_block;
- }
-
- word->counter = tag_fixnum(0);
- }
-
- update_word_entry_point(word.untagged());
- }
-
- update_code_heap_words(false);
-}
-
-void factor_vm::primitive_counting_profiler()
-{
- set_counting_profiler(to_boolean(ctx->pop()));
-}
-
-}
+++ /dev/null
-namespace factor
-{
-
-}
else
assert(false);
- *pc = (cell)handler_word->code->entry_point();
+ *pc = (cell)handler_word->entry_point;
}
}
template<typename Func> Func factor_vm::get_entry_point(cell n)
{
- /* We return word->code->entry_point() and not word->entry_point,
- because if the counting profiler is enabled, we don't want to go through the
- entry point's counting profiler stub. This clobbers registers, since entry
- points use the C ABI and not the Factor ABI. */
tagged<word> entry_point_word(special_objects[n]);
- return (Func)entry_point_word->code->entry_point();
+ return (Func)entry_point_word->entry_point;
}
void factor_vm::unwind_native_frames(cell quot, stack_frame *to)
{
tagged<word> entry_point_word(special_objects[UNWIND_NATIVE_FRAMES_WORD]);
- void *func = entry_point_word->code->entry_point();
+ void *func = entry_point_word->entry_point;
CODE_TO_FUNCTION_POINTER(func);
((unwind_native_frames_func_type)func)(quot,to);
}
cell factor_vm::get_fpu_state()
{
tagged<word> entry_point_word(special_objects[GET_FPU_STATE_WORD]);
- void *func = entry_point_word->code->entry_point();
+ void *func = entry_point_word->entry_point;
CODE_TO_FUNCTION_POINTER(func);
return ((get_fpu_state_func_type)func)();
}
void factor_vm::set_fpu_state(cell state)
{
tagged<word> entry_point_word(special_objects[SET_FPU_STATE_WORD]);
- void *func = entry_point_word->code->entry_point();
+ void *func = entry_point_word->entry_point;
CODE_TO_FUNCTION_POINTER(func);
((set_fpu_state_func_type)func)(state);
}
{
/* Simple code generator used by:
-- counting_profiler (counting_profiler.cpp),
- quotation compiler (quotations.cpp),
- megamorphic caches (dispatch.cpp),
- polymorphic inline caches (inline_cache.cpp) */
{
code_block_unoptimized,
code_block_optimized,
- code_block_counting_profiler,
code_block_pic
};
struct code_block;
-/* Assembly code makes assumptions about the layout of this struct */
+/* Assembly code makes assumptions about the layout of this struct:
+ basis/bootstrap/images/images.factor
+ basis/compiler/constants/constants.factor
+ core/bootstrap/primitives.factor
+*/
struct word : public object {
static const cell type_number = WORD_TYPE;
/* TAGGED hashcode */
cell pic_def;
/* TAGGED alternative entry point for direct tail calls. Used for inline caching */
cell pic_tail_def;
- /* TAGGED call count for counting_profiler */
- cell counter;
/* TAGGED machine code for sub-primitive */
cell subprimitive;
/* UNTAGGED entry point: jump here to execute word */
void *entry_point;
/* UNTAGGED compiled code block */
- code_block *code;
- /* UNTAGGED counting_profiler stub */
- code_block *counting_profiler;
+
+ /* defined in code_blocks.hpp */
+ code_block *code() const;
};
/* Assembly code makes assumptions about the layout of this struct */
double n;
};
-/* Assembly code makes assumptions about the layout of this struct */
+/* Assembly code makes assumptions about the layout of this struct:
+ basis/bootstrap/images/images.factor
+ basis/compiler/constants/constants.factor
+ core/bootstrap/primitives.factor
+*/
struct quotation : public object {
static const cell type_number = QUOTATION_TYPE;
/* tagged */
cell cache_counter;
/* UNTAGGED entry point; jump here to call quotation */
void *entry_point;
- /* UNTAGGED compiled code block */
- code_block *code;
+
+ /* defined in code_blocks.hpp */
+ code_block *code() const;
};
/* Assembly code makes assumptions about the layout of this struct */
#include "contexts.hpp"
#include "run.hpp"
#include "objects.hpp"
-#include "counting_profiler.hpp"
#include "sampling_profiler.hpp"
#include "errors.hpp"
#include "bignumint.hpp"
_(context_object) \
_(context_object_for) \
_(current_callback) \
- _(counting_profiler) \
_(data_room) \
_(datastack) \
_(datastack_for) \
}
}
-void factor_vm::set_quot_entry_point(quotation *quot, code_block *code)
-{
- quot->code = code;
- quot->entry_point = code->entry_point();
-}
-
/* Allocates memory */
code_block *factor_vm::jit_compile_quot(cell owner_, cell quot_, bool relocating)
{
if(!quot_compiled_p(quot.untagged()))
{
code_block *compiled = jit_compile_quot(quot.value(),quot.value(),relocating);
- set_quot_entry_point(quot.untagged(),compiled);
+ quot.untagged()->entry_point = compiled->entry_point();
}
}
jit_compile_quot(ctx->pop(),true);
}
-code_block *factor_vm::lazy_jit_compile_block()
+void *factor_vm::lazy_jit_compile_entry_point()
{
- return untag<word>(special_objects[LAZY_JIT_COMPILE_WORD])->code;
+ return untag<word>(special_objects[LAZY_JIT_COMPILE_WORD])->entry_point;
}
/* push a new quotation on the stack */
quot->array = ctx->peek();
quot->cached_effect = false_object;
quot->cache_counter = false_object;
- set_quot_entry_point(quot,lazy_jit_compile_block());
+ quot->entry_point = lazy_jit_compile_entry_point();
ctx->replace(tag<quotation>(quot));
}
{
quotation *quot = untag_check<quotation>(ctx->pop());
- ctx->push(from_unsigned_cell((cell)quot->code->entry_point()));
- ctx->push(from_unsigned_cell((cell)quot->code + quot->code->size()));
+ ctx->push(from_unsigned_cell((cell)quot->entry_point));
+ ctx->push(from_unsigned_cell((cell)quot->code() + quot->code()->size()));
}
/* Allocates memory */
assert(!quot_compiled_p(quot.untagged()));
code_block *compiled = jit_compile_quot(quot.value(),quot.value(),true);
- set_quot_entry_point(quot.untagged(),compiled);
+ quot.untagged()->entry_point = compiled->entry_point();
return quot.value();
}
bool factor_vm::quot_compiled_p(quotation *quot)
{
- return quot->code != NULL && quot->code != lazy_jit_compile_block();
+ return quot->entry_point != NULL && quot->entry_point != lazy_jit_compile_entry_point();
}
void factor_vm::primitive_quot_compiled_p()
for(cell i = 0; i < length; i++)
{
data_root<quotation> quot(array_nth(quotations.untagged(),i),this);
- if(!quot->code)
- set_quot_entry_point(quot.untagged(),lazy_jit_compile_block());
+ if(!quot->entry_point)
+ quot.untagged()->entry_point = lazy_jit_compile_entry_point();
}
}
return 0;
/* these objects have some binary data at the end */
case WORD_TYPE:
- return sizeof(word) - sizeof(cell) * 3;
+ return sizeof(word) - sizeof(cell);
case ALIEN_TYPE:
return sizeof(cell) * 3;
case DLL_TYPE:
return sizeof(cell) * 2;
case QUOTATION_TYPE:
- return sizeof(quotation) - sizeof(cell) * 2;
+ return sizeof(quotation) - sizeof(cell);
case STRING_TYPE:
return sizeof(string);
/* everything else consists entirely of pointers */
thread(thread),
callback_id(0),
c_to_factor_func(NULL),
- counting_profiler_p(false),
sampling_profiler_p(false),
signal_pipe_input(0),
signal_pipe_output(0),
c_to_factor_func_type c_to_factor_func;
/* Is profiling enabled? */
- bool counting_profiler_p;
volatile cell sampling_profiler_p;
fixnum samples_per_second;
void primitive_clone();
void primitive_become();
- // counting_profiler
- void init_counting_profiler();
- code_block *compile_counting_profiler_stub(cell word_);
- void set_counting_profiler(bool counting_profiler);
- void primitive_counting_profiler();
-
- /* Sampling profiler */
+ // sampling_profiler
void clear_samples();
void record_sample();
void record_callstack_sample(cell *begin, cell *end);
word *allot_word(cell name_, cell vocab_, cell hashcode_);
void primitive_word();
void primitive_word_code();
- void update_word_entry_point(word *w_);
void primitive_optimized_p();
void primitive_wrapper();
void jit_compile_word(cell word_, cell def_, bool relocating);
// quotations
void primitive_jit_compile();
- code_block *lazy_jit_compile_block();
+ void *lazy_jit_compile_entry_point();
void primitive_array_to_quotation();
void primitive_quotation_code();
- void set_quot_entry_point(quotation *quot, code_block *code);
code_block *jit_compile_quot(cell owner_, cell quot_, bool relocating);
void jit_compile_quot(cell quot_, bool relocating);
fixnum quot_code_offset_to_scan(cell quot_, cell offset);
/* Refuse to compile this word more than once, because quot_compiled_p()
depends on the identity of its code block */
- if(word->code && word.value() == special_objects[LAZY_JIT_COMPILE_WORD])
+ if(word->entry_point && word.value() == special_objects[LAZY_JIT_COMPILE_WORD])
return;
code_block *compiled = jit_compile_quot(word.value(),def.value(),relocating);
- word->code = compiled;
+ word->entry_point = compiled->entry_point();
if(to_boolean(word->pic_def)) jit_compile_quot(word->pic_def,relocating);
if(to_boolean(word->pic_tail_def)) jit_compile_quot(word->pic_tail_def,relocating);
{
data_root<word> word(array_nth(words.untagged(),i),this);
- if(!word->code || !word->code->optimized_p())
+ if(!word->entry_point || !word->code()->optimized_p())
jit_compile_word(word.value(),word->def,false);
-
- update_word_entry_point(word.untagged());
}
}
new_word->name = name.value();
new_word->def = special_objects[OBJ_UNDEFINED];
new_word->props = false_object;
- new_word->counter = tag_fixnum(0);
new_word->pic_def = false_object;
new_word->pic_tail_def = false_object;
new_word->subprimitive = false_object;
- new_word->counting_profiler = NULL;
- new_word->code = NULL;
+ new_word->entry_point = NULL;
jit_compile_word(new_word.value(),new_word->def,true);
- if(counting_profiler_p)
- {
- code_block *counting_profiler_block = compile_counting_profiler_stub(new_word.value());
- new_word->counting_profiler = counting_profiler_block;
- initialize_code_block(new_word->counting_profiler);
- }
-
- update_word_entry_point(new_word.untagged());
return new_word.untagged();
}
data_root<word> w(ctx->pop(),this);
w.untag_check(this);
- if(counting_profiler_p)
- {
- ctx->push(from_unsigned_cell((cell)w->counting_profiler->entry_point()));
- ctx->push(from_unsigned_cell((cell)w->counting_profiler + w->counting_profiler->size()));
- }
- else
- {
- ctx->push(from_unsigned_cell((cell)w->code->entry_point()));
- ctx->push(from_unsigned_cell((cell)w->code + w->code->size()));
- }
-}
-
-void factor_vm::update_word_entry_point(word *w)
-{
- if(counting_profiler_p && w->counting_profiler)
- w->entry_point = w->counting_profiler->entry_point();
- else
- w->entry_point = w->code->entry_point();
+ ctx->push(from_unsigned_cell((cell)w->entry_point));
+ ctx->push(from_unsigned_cell((cell)w->code() + w->code()->size()));
}
void factor_vm::primitive_optimized_p()
{
word *w = untag_check<word>(ctx->peek());
- ctx->replace(tag_boolean(w->code->optimized_p()));
+ ctx->replace(tag_boolean(w->code()->optimized_p()));
}
void factor_vm::primitive_wrapper()