From c31530caecbdb96384603fd11ad5a356897474f0 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Thu, 10 Nov 2011 16:00:47 -0800 Subject: [PATCH] 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. --- GNUmakefile | 2 - Nmakefile | 1 - basis/bootstrap/image/image.factor | 8 +-- basis/compiler/constants/constants.factor | 4 +- basis/cpu/x86/bootstrap.factor | 13 ----- core/bootstrap/primitives.factor | 1 - vm/code_block_visitor.hpp | 12 ++--- vm/code_blocks.hpp | 13 +++++ vm/code_heap.cpp | 4 +- vm/counting_profiler.cpp | 66 ----------------------- vm/counting_profiler.hpp | 4 -- vm/cpu-x86.cpp | 2 +- vm/entry_points.cpp | 12 ++--- vm/jit.cpp | 1 - vm/layouts.hpp | 26 +++++---- vm/master.hpp | 1 - vm/primitives.hpp | 1 - vm/quotations.cpp | 26 ++++----- vm/slot_visitor.hpp | 4 +- vm/vm.cpp | 1 - vm/vm.hpp | 13 +---- vm/words.cpp | 42 +++------------ 22 files changed, 64 insertions(+), 193 deletions(-) delete mode 100755 vm/counting_profiler.cpp delete mode 100755 vm/counting_profiler.hpp diff --git a/GNUmakefile b/GNUmakefile index 55906786cc..955a310e12 100755 --- a/GNUmakefile +++ b/GNUmakefile @@ -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 \ diff --git a/Nmakefile b/Nmakefile index d1feec5a10..05aa8cb562 100755 --- a/Nmakefile +++ b/Nmakefile @@ -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 \ diff --git a/basis/bootstrap/image/image.factor b/basis/bootstrap/image/image.factor index 9de2c443af..76ff136386 100755 --- a/basis/bootstrap/image/image.factor +++ b/basis/bootstrap/image/image.factor @@ -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 ; diff --git a/basis/compiler/constants/constants.factor b/basis/compiler/constants/constants.factor index e285952461..85aa5c4439 100644 --- a/basis/compiler/constants/constants.factor +++ b/basis/compiler/constants/constants.factor @@ -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 diff --git a/basis/cpu/x86/bootstrap.factor b/basis/cpu/x86/bootstrap.factor index 9691d289e1..c600fa5309 100644 --- a/basis/cpu/x86/bootstrap.factor +++ b/basis/cpu/x86/bootstrap.factor @@ -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 diff --git a/core/bootstrap/primitives.factor b/core/bootstrap/primitives.factor index 594120fdd6..2f9b079e45 100755 --- a/core/bootstrap/primitives.factor +++ b/core/bootstrap/primitives.factor @@ -241,7 +241,6 @@ bi "props" "pic-def" "pic-tail-def" - { "counter" { "fixnum" "math" } } { "sub-primitive" read-only } } define-builtin diff --git a/vm/code_block_visitor.hpp b/vm/code_block_visitor.hpp index d43daa3ad3..2421ace669 100644 --- a/vm/code_block_visitor.hpp +++ b/vm/code_block_visitor.hpp @@ -59,19 +59,15 @@ void code_block_visitor::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: diff --git a/vm/code_blocks.hpp b/vm/code_blocks.hpp index cd7d1ea5ae..c0f076836b 100644 --- a/vm/code_blocks.hpp +++ b/vm/code_blocks.hpp @@ -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; } + +} + + diff --git a/vm/code_heap.cpp b/vm/code_heap.cpp index c81cef10e1..f46891f7b8 100755 --- a/vm/code_heap.cpp +++ b/vm/code_heap.cpp @@ -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) diff --git a/vm/counting_profiler.cpp b/vm/counting_profiler.cpp deleted file mode 100755 index 9d3f390d85..0000000000 --- a/vm/counting_profiler.cpp +++ /dev/null @@ -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_,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 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(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())); -} - -} diff --git a/vm/counting_profiler.hpp b/vm/counting_profiler.hpp deleted file mode 100755 index 412ef35bb4..0000000000 --- a/vm/counting_profiler.hpp +++ /dev/null @@ -1,4 +0,0 @@ -namespace factor -{ - -} diff --git a/vm/cpu-x86.cpp b/vm/cpu-x86.cpp index d3a7bf0b15..003d8e1980 100644 --- a/vm/cpu-x86.cpp +++ b/vm/cpu-x86.cpp @@ -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; } } diff --git a/vm/entry_points.cpp b/vm/entry_points.cpp index fc144a37e2..f3a834eb17 100755 --- a/vm/entry_points.cpp +++ b/vm/entry_points.cpp @@ -22,18 +22,14 @@ void factor_vm::c_to_factor(cell quot) template 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 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 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 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 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); } diff --git a/vm/jit.cpp b/vm/jit.cpp index d31123a63c..a84856ec6f 100644 --- a/vm/jit.cpp +++ b/vm/jit.cpp @@ -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) */ diff --git a/vm/layouts.hpp b/vm/layouts.hpp index ebffa644b5..4431e73b96 100644 --- a/vm/layouts.hpp +++ b/vm/layouts.hpp @@ -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 */ diff --git a/vm/master.hpp b/vm/master.hpp index 3eaefc77b8..5b0604fe33 100755 --- a/vm/master.hpp +++ b/vm/master.hpp @@ -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" diff --git a/vm/primitives.hpp b/vm/primitives.hpp index fe3a89a991..7884cf2e30 100644 --- a/vm/primitives.hpp +++ b/vm/primitives.hpp @@ -46,7 +46,6 @@ namespace factor _(context_object) \ _(context_object_for) \ _(current_callback) \ - _(counting_profiler) \ _(data_room) \ _(datastack) \ _(datastack_for) \ diff --git a/vm/quotations.cpp b/vm/quotations.cpp index c49092f649..878169e787 100755 --- a/vm/quotations.cpp +++ b/vm/quotations.cpp @@ -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(special_objects[LAZY_JIT_COMPILE_WORD])->code; + return untag(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(quot)); } @@ -344,8 +338,8 @@ void factor_vm::primitive_quotation_code() { quotation *quot = untag_check(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 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(); } } diff --git a/vm/slot_visitor.hpp b/vm/slot_visitor.hpp index 4fda738140..bd2b848398 100755 --- a/vm/slot_visitor.hpp +++ b/vm/slot_visitor.hpp @@ -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 */ diff --git a/vm/vm.cpp b/vm/vm.cpp index d2298c289a..0029dd8c35 100755 --- a/vm/vm.cpp +++ b/vm/vm.cpp @@ -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), diff --git a/vm/vm.hpp b/vm/vm.hpp index a4c11e390f..6836bf11ab 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -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); diff --git a/vm/words.cpp b/vm/words.cpp index af27401935..735a92eacf 100644 --- a/vm/words.cpp +++ b/vm/words.cpp @@ -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(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 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(ctx->peek()); - ctx->replace(tag_boolean(w->code->optimized_p())); + ctx->replace(tag_boolean(w->code()->optimized_p())); } void factor_vm::primitive_wrapper() -- 2.34.1