简体   繁体   中英

Copy-on-write for stacks

How to implement copy-on-write technique for stack management in postfix calculations of big numbers?

I want to optimize my system regarding operations like:

duplicate top of stack
swap the two top elements
copy the second element on stack to the top
rotate the stack making the third element on top
apply n-ary operations on the stack 

A typical operation take a number of parameters from top of stack and leave a number of results instead.

My stack is implemented as an array where data grows from low-mem to hi-mem and pointers from hi-mem to low-mem.

As I can see, the problem is not in the copy-on-write technique per se, but in memory management and garbage collecting.

In Forth we cannot have operator overloading and should have an explicitly separate set of operations for each class of numbers. Then we have two options:

    1. A set of operations over bigint objects (their handlers), with manual memory management, similar to operations over files, dynamic memory buffers, or other objects.
    1. A full set of operations including the separate stack, like operations over floating-point numbers, with automatic memory management.

Note that option (2) contains (1) under the hood.

Reference counting

One approach to implement automatic memory management in option (2) is to use a dedicated stack (or maybe two stacks) and reference counting. The stack contains references to objects (buffers). The operations that alter data (like b::1+ ) should make copy of the buffer and replace the reference by a new one if the counter is greater than 1 (otherwise data can be altered in the place).

Placing an item (a reference) to the stack should increase its counter, removing from the stack should decrease its counter. When the counter become 0, the buffer should be freed.

Such operations like b::dup , b::over increase the counter. b::swap doesn't change any counter. b::drop decreases the counter (and frees the buffer if the counter is 0).

Moving an item from the stack into a bigint variable should not change the counter in the result. But the counter for the previous value of the variable (if any) should be decreased.

If named variables and constants are not enough (eg, to have user-defined arrays), you may need to introduce into the API the pointers (a kind of anonymous variables) or handlers to bigint objects.

Immutable objects

Another approach to implement option (2) is to have immutable objects and garbage collection loop. In this approach we don't need to count references, but need to maintain the list of external pointers (including variables).

A simple example of such garbage collection can be found in the implementation of s-expressions by Peter Sovietov: Функциональное программирование на языке Форт ("Functional programming in Forth language" in Russian, but it can be easy translated using Google Translate ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM