vm: strip out call-counting profiler

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.
db4
Joe Groff 2011-11-10 16:00:47 -08:00
parent 139c9ca38c
commit c31530caec
22 changed files with 64 additions and 193 deletions

View File

@ -34,7 +34,6 @@ ifdef CONFIG
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 \
@ -77,7 +76,6 @@ ifdef CONFIG
vm/contexts.hpp \
vm/run.hpp \
vm/objects.hpp \
vm/counting_profiler.hpp \
vm/sampling_profiler.hpp \
vm/errors.hpp \
vm/bignumint.hpp \

View File

@ -37,7 +37,6 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
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 \

View File

@ -350,11 +350,8 @@ M: f ' drop \ f type-number ;
[ 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
@ -493,8 +490,7 @@ M: quotation '
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 ;

View File

@ -20,9 +20,9 @@ CONSTANT: deck-bits 18
: 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

View File

@ -76,19 +76,6 @@ big-endian off
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

View File

@ -241,7 +241,6 @@ bi
"props"
"pic-def"
"pic-tail-def"
{ "counter" { "fixnum" "math" } }
{ "sub-primitive" read-only }
} define-builtin

View File

@ -59,19 +59,15 @@ void code_block_visitor<Fixup>::visit_object_code_block(object *obj)
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:

View File

@ -84,4 +84,17 @@ struct code_block
};
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;
}
}

View File

@ -178,15 +178,13 @@ void factor_vm::primitive_modify_code_heap()
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)

View File

@ -1,66 +0,0 @@
#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()));
}
}

View File

@ -1,4 +0,0 @@
namespace factor
{
}

View File

@ -63,7 +63,7 @@ void factor_vm::dispatch_signal_handler(cell *sp, cell *pc, cell handler)
else
assert(false);
*pc = (cell)handler_word->code->entry_point();
*pc = (cell)handler_word->entry_point;
}
}

View File

@ -22,18 +22,14 @@ void factor_vm::c_to_factor(cell quot)
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);
}
@ -41,7 +37,7 @@ void factor_vm::unwind_native_frames(cell quot, stack_frame *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)();
}
@ -49,7 +45,7 @@ cell factor_vm::get_fpu_state()
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);
}

View File

@ -4,7 +4,6 @@ namespace factor
{
/* Simple code generator used by:
- counting_profiler (counting_profiler.cpp),
- quotation compiler (quotations.cpp),
- megamorphic caches (dispatch.cpp),
- polymorphic inline caches (inline_cache.cpp) */

View File

@ -98,7 +98,6 @@ enum code_block_type
{
code_block_unoptimized,
code_block_optimized,
code_block_counting_profiler,
code_block_pic
};
@ -253,7 +252,11 @@ struct string : public object {
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 */
@ -270,16 +273,14 @@ struct word : public object {
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 */
@ -299,7 +300,11 @@ struct boxed_float : object {
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 */
@ -310,8 +315,9 @@ struct quotation : public object {
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 */

View File

@ -96,7 +96,6 @@ namespace factor
#include "contexts.hpp"
#include "run.hpp"
#include "objects.hpp"
#include "counting_profiler.hpp"
#include "sampling_profiler.hpp"
#include "errors.hpp"
#include "bignumint.hpp"

View File

@ -46,7 +46,6 @@ namespace factor
_(context_object) \
_(context_object_for) \
_(current_callback) \
_(counting_profiler) \
_(data_room) \
_(datastack) \
_(datastack_for) \

View File

@ -284,12 +284,6 @@ void quotation_jit::iterate_quotation()
}
}
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)
{
@ -313,7 +307,7 @@ void factor_vm::jit_compile_quot(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();
}
}
@ -322,9 +316,9 @@ void factor_vm::primitive_jit_compile()
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 */
@ -335,7 +329,7 @@ void factor_vm::primitive_array_to_quotation()
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));
}
@ -344,8 +338,8 @@ void factor_vm::primitive_quotation_code()
{
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 */
@ -369,7 +363,7 @@ cell factor_vm::lazy_jit_compile(cell quot_)
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();
}
@ -381,7 +375,7 @@ VM_C_API cell lazy_jit_compile(cell quot, factor_vm *parent)
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()
@ -404,8 +398,8 @@ void factor_vm::initialize_all_quotations()
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();
}
}

View File

@ -65,13 +65,13 @@ cell object::binary_payload_start(Fixup fixup) const
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 */

View File

@ -8,7 +8,6 @@ factor_vm::factor_vm(THREADHANDLE thread) :
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),

View File

@ -64,7 +64,6 @@ struct factor_vm
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;
@ -199,13 +198,7 @@ struct factor_vm
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);
@ -458,7 +451,6 @@ struct factor_vm
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);
@ -658,10 +650,9 @@ struct factor_vm
// 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);

View File

@ -11,11 +11,11 @@ void factor_vm::jit_compile_word(cell word_, cell def_, bool relocating)
/* 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);
@ -35,10 +35,8 @@ void factor_vm::compile_all_words()
{
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());
}
}
@ -54,22 +52,12 @@ word *factor_vm::allot_word(cell name_, cell vocab_, cell hashcode_)
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();
}
@ -89,30 +77,14 @@ void factor_vm::primitive_word_code()
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()