Replace compiled? primitive with compiled? word slot
parent
155cb7f3be
commit
fc0cea8e42
|
@ -11,10 +11,6 @@
|
||||||
- files can be reloaded and edited
|
- files can be reloaded and edited
|
||||||
- modules can be (re)loaded
|
- modules can be (re)loaded
|
||||||
- keyboard navigation
|
- keyboard navigation
|
||||||
- editor:
|
|
||||||
- more efficient multi-line inserts
|
|
||||||
- write "foo| " and put caret at | then select word element: selects
|
|
||||||
space
|
|
||||||
- ui browser: show currently selected vocab & words
|
- ui browser: show currently selected vocab & words
|
||||||
- keyboard-navigatable list gadget of some kind
|
- keyboard-navigatable list gadget of some kind
|
||||||
- tuple= in dataflow view
|
- tuple= in dataflow view
|
||||||
|
@ -22,7 +18,6 @@
|
||||||
- ui quick start doc
|
- ui quick start doc
|
||||||
- auto-update browser and help when sources reload
|
- auto-update browser and help when sources reload
|
||||||
- how do we refer to command shortcuts in the docs?
|
- how do we refer to command shortcuts in the docs?
|
||||||
- reliably clonable gadgets
|
|
||||||
- figure out if we need both set-model and set-model*
|
- figure out if we need both set-model and set-model*
|
||||||
- if i do 10000 [ . ] each and then clear, the listener window is slow
|
- if i do 10000 [ . ] each and then clear, the listener window is slow
|
||||||
- full-height nodes should really be full height
|
- full-height nodes should really be full height
|
||||||
|
@ -38,11 +33,11 @@
|
||||||
- editor should support stream output protocol
|
- editor should support stream output protocol
|
||||||
- double/triple click
|
- double/triple click
|
||||||
- autoscroll
|
- autoscroll
|
||||||
- undo and redo
|
|
||||||
- transpose char/word/line
|
- transpose char/word/line
|
||||||
- page up/down
|
|
||||||
- search and replace
|
|
||||||
- drag scroll
|
- drag scroll
|
||||||
|
- more efficient multi-line inserts
|
||||||
|
- write "foo| " and put caret at | then select word element: selects
|
||||||
|
space
|
||||||
- slider needs to be modelized
|
- slider needs to be modelized
|
||||||
- fonts/ should go inside the .app -- we need multi-tier resource-path
|
- fonts/ should go inside the .app -- we need multi-tier resource-path
|
||||||
- should be possible to drop an image file on the .app to run it
|
- should be possible to drop an image file on the .app to run it
|
||||||
|
@ -50,7 +45,6 @@
|
||||||
- own-selection violates ICCCM
|
- own-selection violates ICCCM
|
||||||
- cocoa: windows are not updated while resizing
|
- cocoa: windows are not updated while resizing
|
||||||
- grid slows down with 2000 lines
|
- grid slows down with 2000 lines
|
||||||
- ui uses too much cpu time idling
|
|
||||||
- see if its possible to only repaint dirty regions
|
- see if its possible to only repaint dirty regions
|
||||||
- x11 title bars are funny
|
- x11 title bars are funny
|
||||||
- rollover is not updated on window focus changes
|
- rollover is not updated on window focus changes
|
||||||
|
@ -102,6 +96,7 @@
|
||||||
|
|
||||||
+ misc:
|
+ misc:
|
||||||
|
|
||||||
|
- symbol redef is an xref false positive
|
||||||
- signal 4 on datastack underflow on mac intel??
|
- signal 4 on datastack underflow on mac intel??
|
||||||
- fix alien-callback/SEH bug on win32
|
- fix alien-callback/SEH bug on win32
|
||||||
- minor GC takes too long now, we should card mark code heap
|
- minor GC takes too long now, we should card mark code heap
|
||||||
|
|
|
@ -172,6 +172,7 @@ M: f '
|
||||||
dup word-primitive ' ,
|
dup word-primitive ' ,
|
||||||
dup word-def ' ,
|
dup word-def ' ,
|
||||||
dup word-props ' ,
|
dup word-props ' ,
|
||||||
|
f ' ,
|
||||||
0 ,
|
0 ,
|
||||||
] { } make
|
] { } make
|
||||||
word-tag word-tag [ emit-seq ] emit-object
|
word-tag word-tag [ emit-seq ] emit-object
|
||||||
|
|
|
@ -99,7 +99,6 @@ call
|
||||||
{ "float>=" "math-internals" }
|
{ "float>=" "math-internals" }
|
||||||
{ "(word)" "kernel-internals" }
|
{ "(word)" "kernel-internals" }
|
||||||
{ "update-xt" "words" }
|
{ "update-xt" "words" }
|
||||||
{ "compiled?" "words" }
|
|
||||||
{ "drop" "kernel" }
|
{ "drop" "kernel" }
|
||||||
{ "2drop" "kernel" }
|
{ "2drop" "kernel" }
|
||||||
{ "3drop" "kernel" }
|
{ "3drop" "kernel" }
|
||||||
|
@ -284,6 +283,12 @@ num-types f <array> builtins set
|
||||||
{ "word-props" "words" }
|
{ "word-props" "words" }
|
||||||
{ "set-word-props" "words" }
|
{ "set-word-props" "words" }
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
7
|
||||||
|
object
|
||||||
|
{ "compiled?" "words" }
|
||||||
|
f
|
||||||
|
}
|
||||||
} define-builtin
|
} define-builtin
|
||||||
|
|
||||||
"ratio?" "math" create t "inline" set-word-prop
|
"ratio?" "math" create t "inline" set-word-prop
|
||||||
|
|
14
vm/code_gc.c
14
vm/code_gc.c
|
@ -67,6 +67,8 @@ CELL heap_allot(HEAP *heap, CELL size)
|
||||||
F_BLOCK *prev = NULL;
|
F_BLOCK *prev = NULL;
|
||||||
F_BLOCK *scan = heap->free_list;
|
F_BLOCK *scan = heap->free_list;
|
||||||
|
|
||||||
|
size = align8(size);
|
||||||
|
|
||||||
while(scan)
|
while(scan)
|
||||||
{
|
{
|
||||||
CELL this_size = scan->size - sizeof(F_BLOCK);
|
CELL this_size = scan->size - sizeof(F_BLOCK);
|
||||||
|
@ -209,20 +211,20 @@ void mark_sweep_step(F_COMPILED *compiled, CELL code_start,
|
||||||
if(compiled->finalized)
|
if(compiled->finalized)
|
||||||
{
|
{
|
||||||
for(scan = words_start; scan < words_end; scan += CELLS)
|
for(scan = words_start; scan < words_end; scan += CELLS)
|
||||||
mark_and_sweep(get(scan));
|
recursive_mark(get(scan));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mark_and_sweep(CELL xt)
|
void recursive_mark(CELL xt)
|
||||||
{
|
{
|
||||||
F_BLOCK *block = xt_to_block(xt);
|
F_BLOCK *block = xt_to_block(xt);
|
||||||
|
|
||||||
if(block->status == B_MARKED)
|
if(block->status == B_MARKED)
|
||||||
return;
|
return;
|
||||||
else if(block->status == B_FREE)
|
else if(block->status == B_ALLOCATED)
|
||||||
critical_error("Marking a free block",(CELL)block);
|
block->status = B_MARKED;
|
||||||
|
else
|
||||||
block->status = B_MARKED;
|
critical_error("Marking the wrong block",(CELL)block);
|
||||||
|
|
||||||
F_COMPILED *compiled = xt_to_compiled(xt);
|
F_COMPILED *compiled = xt_to_compiled(xt);
|
||||||
iterate_code_heap_step(compiled,collect_literals_step);
|
iterate_code_heap_step(compiled,collect_literals_step);
|
||||||
|
|
|
@ -74,6 +74,6 @@ INLINE F_COMPILED *xt_to_compiled(CELL xt)
|
||||||
void init_code_heap(CELL size);
|
void init_code_heap(CELL size);
|
||||||
void iterate_code_heap(CODE_HEAP_ITERATOR iter);
|
void iterate_code_heap(CODE_HEAP_ITERATOR iter);
|
||||||
void collect_literals(void);
|
void collect_literals(void);
|
||||||
void mark_and_sweep(CELL xt);
|
void recursive_mark(CELL xt);
|
||||||
void primitive_code_room(void);
|
void primitive_code_room(void);
|
||||||
void primitive_code_gc(void);
|
void primitive_code_gc(void);
|
||||||
|
|
|
@ -232,6 +232,7 @@ void primitive_finalize_compile(void)
|
||||||
F_ARRAY *pair = untag_array(get(AREF(array,i)));
|
F_ARRAY *pair = untag_array(get(AREF(array,i)));
|
||||||
F_WORD *word = untag_word(get(AREF(pair,0)));
|
F_WORD *word = untag_word(get(AREF(pair,0)));
|
||||||
word->xt = to_cell(get(AREF(pair,1)));
|
word->xt = to_cell(get(AREF(pair,1)));
|
||||||
|
word->compiledp = T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* perform relocation */
|
/* perform relocation */
|
||||||
|
|
67
vm/data_gc.c
67
vm/data_gc.c
|
@ -79,31 +79,6 @@ void primitive_size(void)
|
||||||
drepl(tag_fixnum(object_size(dpeek())));
|
drepl(tag_fixnum(object_size(dpeek())));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The number of cells from the start of the object which should be scanned by
|
|
||||||
the GC. Some types have a binary payload at the end (string, word, DLL) which
|
|
||||||
we ignore. */
|
|
||||||
CELL binary_payload_start(CELL pointer)
|
|
||||||
{
|
|
||||||
switch(untag_header(get(pointer)))
|
|
||||||
{
|
|
||||||
/* these objects do not refer to other objects at all */
|
|
||||||
case STRING_TYPE:
|
|
||||||
case FLOAT_TYPE:
|
|
||||||
case BYTE_ARRAY_TYPE:
|
|
||||||
case BIGNUM_TYPE:
|
|
||||||
return 0;
|
|
||||||
/* these objects have some binary data at the end */
|
|
||||||
case WORD_TYPE:
|
|
||||||
return sizeof(F_WORD) - CELLS;
|
|
||||||
case ALIEN_TYPE:
|
|
||||||
case DLL_TYPE:
|
|
||||||
return CELLS * 2;
|
|
||||||
/* everything else consists entirely of pointers */
|
|
||||||
default:
|
|
||||||
return unaligned_object_size(pointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void primitive_data_room(void)
|
void primitive_data_room(void)
|
||||||
{
|
{
|
||||||
F_ARRAY *a = array(ARRAY_TYPE,gen_count,F);
|
F_ARRAY *a = array(ARRAY_TYPE,gen_count,F);
|
||||||
|
@ -417,8 +392,37 @@ CELL copy_object(CELL pointer)
|
||||||
return RETAG(copy_object_impl(pointer),tag);
|
return RETAG(copy_object_impl(pointer),tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void collect_object(CELL scan)
|
/* The number of cells from the start of the object which should be scanned by
|
||||||
|
the GC. Some types have a binary payload at the end (string, word, DLL) which
|
||||||
|
we ignore. */
|
||||||
|
CELL binary_payload_start(CELL pointer)
|
||||||
{
|
{
|
||||||
|
switch(untag_header(get(pointer)))
|
||||||
|
{
|
||||||
|
/* these objects do not refer to other objects at all */
|
||||||
|
case STRING_TYPE:
|
||||||
|
case FLOAT_TYPE:
|
||||||
|
case BYTE_ARRAY_TYPE:
|
||||||
|
case BIGNUM_TYPE:
|
||||||
|
return 0;
|
||||||
|
/* these objects have some binary data at the end */
|
||||||
|
case WORD_TYPE:
|
||||||
|
return sizeof(F_WORD) - CELLS;
|
||||||
|
case ALIEN_TYPE:
|
||||||
|
case DLL_TYPE:
|
||||||
|
return CELLS * 2;
|
||||||
|
/* everything else consists entirely of pointers */
|
||||||
|
default:
|
||||||
|
return unaligned_object_size(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Every object has a regular representation in the runtime, which makes GC
|
||||||
|
much simpler. Every slot of the object until binary_payload_start is a pointer
|
||||||
|
to some other object. */
|
||||||
|
INLINE void collect_object(CELL start)
|
||||||
|
{
|
||||||
|
CELL scan = start;
|
||||||
CELL payload_start = binary_payload_start(scan);
|
CELL payload_start = binary_payload_start(scan);
|
||||||
CELL end = scan + payload_start;
|
CELL end = scan + payload_start;
|
||||||
|
|
||||||
|
@ -429,6 +433,16 @@ INLINE void collect_object(CELL scan)
|
||||||
copy_handle((CELL*)scan);
|
copy_handle((CELL*)scan);
|
||||||
scan += CELLS;
|
scan += CELLS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* It is odd to put this hook here, but this is the only special case
|
||||||
|
made for any type of object by the GC. If code GC is being performed,
|
||||||
|
compiled code blocks referenced by this word must be marked. */
|
||||||
|
if(collecting_code && object_type(start) == WORD_TYPE)
|
||||||
|
{
|
||||||
|
F_WORD *word = (F_WORD *)start;
|
||||||
|
if(word->compiledp != F)
|
||||||
|
recursive_mark(word->xt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CELL collect_next(CELL scan)
|
CELL collect_next(CELL scan)
|
||||||
|
@ -487,6 +501,7 @@ void end_gc()
|
||||||
fprintf(stderr,"*** %s GC (%ld minor, %ld cards)\n",
|
fprintf(stderr,"*** %s GC (%ld minor, %ld cards)\n",
|
||||||
collecting_code ? "Code and data" : "Data",
|
collecting_code ? "Code and data" : "Data",
|
||||||
minor_collections,cards_scanned);
|
minor_collections,cards_scanned);
|
||||||
|
fflush(stderr);
|
||||||
minor_collections = 0;
|
minor_collections = 0;
|
||||||
cards_scanned = 0;
|
cards_scanned = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,11 @@ typedef struct {
|
||||||
CELL array;
|
CELL array;
|
||||||
} F_HASHTABLE;
|
} F_HASHTABLE;
|
||||||
|
|
||||||
|
/* When a word is executed we jump to the value of the XT field. However this
|
||||||
|
value is an unportable function pointer. Interpreted and primitive words will
|
||||||
|
have their XT set to a value in the 'primitives' global (see primitives.c).
|
||||||
|
Compiled words are marked as such and their XT, which point inside the code
|
||||||
|
heap, are instead relocated on startup, and also considered a code GC root. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* TAGGED header */
|
/* TAGGED header */
|
||||||
CELL header;
|
CELL header;
|
||||||
|
@ -120,6 +125,8 @@ typedef struct {
|
||||||
CELL def;
|
CELL def;
|
||||||
/* TAGGED property hash for library code */
|
/* TAGGED property hash for library code */
|
||||||
CELL props;
|
CELL props;
|
||||||
|
/* TAGGED t or f, depending on if the word is compiled or not */
|
||||||
|
CELL compiledp;
|
||||||
/* UNTAGGED execution token: jump here to execute word */
|
/* UNTAGGED execution token: jump here to execute word */
|
||||||
CELL xt;
|
CELL xt;
|
||||||
} F_WORD;
|
} F_WORD;
|
||||||
|
|
|
@ -68,7 +68,6 @@ void* primitives[] = {
|
||||||
primitive_float_greatereq,
|
primitive_float_greatereq,
|
||||||
primitive_word,
|
primitive_word,
|
||||||
primitive_update_xt,
|
primitive_update_xt,
|
||||||
primitive_word_compiledp,
|
|
||||||
primitive_drop,
|
primitive_drop,
|
||||||
primitive_2drop,
|
primitive_2drop,
|
||||||
primitive_3drop,
|
primitive_3drop,
|
||||||
|
|
19
vm/types.c
19
vm/types.c
|
@ -417,11 +417,9 @@ void primitive_hashtable(void)
|
||||||
dpush(tag_object(hash));
|
dpush(tag_object(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When a word is executed we jump to the value of the xt field. However this
|
|
||||||
value is an unportable function pointer, so in the image we store a primitive
|
|
||||||
number that indexes a list of xts. */
|
|
||||||
void update_xt(F_WORD* word)
|
void update_xt(F_WORD* word)
|
||||||
{
|
{
|
||||||
|
word->compiledp = F;
|
||||||
word->xt = primitive_to_xt(to_fixnum(word->primitive));
|
word->xt = primitive_to_xt(to_fixnum(word->primitive));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,6 +440,7 @@ void primitive_word(void)
|
||||||
word->primitive = tag_fixnum(0);
|
word->primitive = tag_fixnum(0);
|
||||||
word->def = F;
|
word->def = F;
|
||||||
word->props = F;
|
word->props = F;
|
||||||
|
word->compiledp = F;
|
||||||
word->xt = (CELL)undefined;
|
word->xt = (CELL)undefined;
|
||||||
dpush(tag_word(word));
|
dpush(tag_word(word));
|
||||||
}
|
}
|
||||||
|
@ -451,23 +450,11 @@ void primitive_update_xt(void)
|
||||||
update_xt(untag_word(dpop()));
|
update_xt(untag_word(dpop()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void primitive_word_compiledp(void)
|
|
||||||
{
|
|
||||||
F_WORD* word = untag_word(dpop());
|
|
||||||
if(to_fixnum(word->primitive) != 1)
|
|
||||||
box_boolean(false);
|
|
||||||
else
|
|
||||||
box_boolean(word->xt != (CELL)docol);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fixup_word(F_WORD* word)
|
void fixup_word(F_WORD* word)
|
||||||
{
|
{
|
||||||
/* If this is a compiled word, relocate the code pointer. Otherwise,
|
/* If this is a compiled word, relocate the code pointer. Otherwise,
|
||||||
reset it based on the primitive number of the word. */
|
reset it based on the primitive number of the word. */
|
||||||
if(code_relocation_base != 0
|
if(word->compiledp != F)
|
||||||
&& word->xt >= code_relocation_base
|
|
||||||
&& word->xt < code_relocation_base
|
|
||||||
- compiling.base + compiling.limit)
|
|
||||||
code_fixup(&word->xt);
|
code_fixup(&word->xt);
|
||||||
else
|
else
|
||||||
update_xt(word);
|
update_xt(word);
|
||||||
|
|
|
@ -161,7 +161,6 @@ INLINE CELL tag_word(F_WORD *word)
|
||||||
void update_xt(F_WORD* word);
|
void update_xt(F_WORD* word);
|
||||||
void primitive_word(void);
|
void primitive_word(void);
|
||||||
void primitive_update_xt(void);
|
void primitive_update_xt(void);
|
||||||
void primitive_word_compiledp(void);
|
|
||||||
void fixup_word(F_WORD* word);
|
void fixup_word(F_WORD* word);
|
||||||
|
|
||||||
INLINE F_WRAPPER *untag_wrapper_fast(CELL tagged)
|
INLINE F_WRAPPER *untag_wrapper_fast(CELL tagged)
|
||||||
|
|
Loading…
Reference in New Issue