." :noname 3 3 + ;" EVALUATE
So I'm wondering if there's a reasonable way to compile the code into
heap memory instead. It's ok if it's gforth specific I guess.
Paul Rubin <no.email@nospam.invalid> writes:
So I'm wondering if there's a reasonable way to compile the code into
heap memory instead. It's ok if it's gforth specific I guess.
I wonder if it suffices to temporarily set DP (the gforth dictionary
pointer, not documented in the gforth manual) to point into the
allocated memory.
: compile-str { a u -- xt newloc }
HERE { old-here }
a u EVALUATE ( compile into dictionary )
DROP \ don't need the xt this time
ALIGN HERE old-here - { size }
size ALLOC { newloc }
newloc DP ! \ now HERE points to the heap
a u EVALUATE ( xt ) \ re-do the compilation
old-here DP ! \ restore dictionary
newloc ( xt newloc)
;
The xt and newloc both have to be kept around, so the xt can be executed
and so the GC can find the allocated block, but both can be copied into
some other ALLOC'd object which the GC will scan.
Alternatively, if the compiler works in a way that xt and newloc are
known to be the same address, there's no need to remember both.
You can configure my garbage collector to treat internal pointers as
keeping the allocation alive, then you only need to keep the xt around.
You can configure my garbage collector to treat internal pointers as
keeping the allocation alive, then you only need to keep the xt around.
Ah, this is nice. I may have missed that in the html doc somehow.
2) If Gforth was built well, by default it does not just generate the
threaded code at HERE (where DP points to), but also native code
elsewhere. That native code storage is not controlled by the
garbage collector or free, and it is designed for a LIFO
reclamation discipline (and actually that, i.e., MARKER, already
cost far more development time than the benefits gained from
MARKER). So if you want to avoid memory leaks, you will want to
avoid the dynamic native-code generation by starting gforth (or
gforth-fast) with the option "--no-dynamic", or you just call
gforth-itc.
All these options normally cost performance, but given that the
native-code generation costs time, in your case you might even come
out ahead by disabling native-code generation, depending on your
ratio of generation vs. execution.
Now if you have a sequence of primitives to generate in your
heap-allocated threaded code, such as "+ C@",
anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
Now if you have a sequence of primitives to generate in your
heap-allocated threaded code, such as "+ C@",
I'm not versed enough in Gforth's implementation to completely
understand this post, but is there currently a way to generate threaded
code in the heap?
I had thought threaded code in Gforth was mostly for debugging and to
make certain legacy hacks work, but that it is mostly ok to use the
native code compiler.
Paul Rubin <no.email@nospam.invalid> writes:
So I'm wondering if there's a reasonable way to compile the code into
heap memory instead. It's ok if it's gforth specific I guess.
I wonder if it suffices to temporarily set DP (the gforth dictionary
pointer, not documented in the gforth manual) to point into the
allocated memory. To allocate the correct sized block, maybe compile
twice. Something like (untested):
: compile-str { a u -- xt newloc }
HERE { old-here }
a u EVALUATE ( compile into dictionary )
DROP \ don't need the xt this time
ALIGN HERE old-here - { size }
size ALLOC { newloc }
newloc DP ! \ now HERE points to the heap
a u EVALUATE ( xt ) \ re-do the compilation
old-here DP ! \ restore dictionary
newloc ( xt newloc)
;
The xt and newloc both have to be kept around, so the xt can be executed
and so the GC can find the allocated block, but both can be copied into
some other ALLOC'd object which the GC will scan.
Alternatively, if the compiler works in a way that xt and newloc are
known to be the same address, there's no need to remember both.
Let's say I convert a string into an anonymous function:
." :noname 3 3 + ;" EVALUATE
This leaves an xt on the stack. The compiled code lives in the
dictionary, right? So if I dynamically create a lot of such xt's for temporary use, that's a memory leak? If each one is supposed to be used
and released immediately after creation, FORGET could rewind the
dictionary to the right place, but maybe the required lifetimes are more complex.
So I'm wondering if there's a reasonable way to compile the code into
heap memory instead. It's ok if it's gforth specific I guess.
This would be the garbage collected heap using Anton's GC, if it
matters.
Why to want this? Muhahaha.
For more info, see the User's Manual, 4.6 "Special Fearures", for kForth-64/-32/-Win32 at
https://ccreweb.org/software/kforth.html
Let's say I convert a string into an anonymous function:
." :noname 3 3 + ;" EVALUATE
This leaves an xt on the stack. The compiled code lives in the
dictionary, right? So if I dynamically create a lot of such xt's for temporary use, that's a memory leak? If each one is supposed to be used
and released immediately after creation, FORGET could rewind the
dictionary to the right place, but maybe the required lifetimes are more complex.
So I'm wondering if there's a reasonable way to compile the code into
heap memory instead. It's ok if it's gforth specific I guess.
understand this post, but is there currently a way to generate threaded
code in the heap?
| Sysop: | DaiTengu |
|---|---|
| Location: | Appleton, WI |
| Users: | 1,126 |
| Nodes: | 10 (0 / 10) |
| Uptime: | 51:58:12 |
| Calls: | 14,414 |
| Calls today: | 2 |
| Files: | 186,401 |
| D/L today: |
11,531 files (3,175M bytes) |
| Messages: | 2,548,956 |
| Posted today: | 1 |