Skip to content

Commit

Permalink
Rollback local call allowance.
Browse files Browse the repository at this point in the history
  • Loading branch information
virgil-serbanuta committed Nov 27, 2017
1 parent 71c3b31 commit 470502e
Showing 1 changed file with 0 additions and 56 deletions.
56 changes: 0 additions & 56 deletions gas.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,61 +384,8 @@ We assume that all operations interrogating the local state have complexity
+ jumpCost + callStackDepthCheckCost
requiredRegisterMemory(LOCALCALL(_, nARGS, _) _ rARGS) =
currentRegisterMemory + sum [registerSize(r) | r <- rVALUES]
- callMemoryAllowance
```

There are three ways of implementing the memory allowance, each with its
own strong points and drawbacks. The main question is whether doing a
`call f()` should have worse memory costs than doing: `call f1`,
`f1` ONLY doing `call f2`, ... `f1000` ONLY doing `call f`.

* The allowance is *global*: this means that when one executes a `LOCALCALL`,
we just subtract the allowance from the total amount of memory used. The
good part is that it's very simple to implement, the weird part is that one
is incentivized to wrap the actual function one wants to call into other
calls that do nothing except decreasing the memory usage, as in the example
above. This is implemented above.
* The allowance works only for the *local registers* in the current function.
The good part is that it removes some of the weirdness in the global
allowance option, the bad part is that it does not remove enough of it.
As an example, one can wrap a memory-intensive call into several function
calls that do nothing except moving things from memory into registers,
calling the next function, then moving things back. Still, one has to pay
a certain computation cost to do that, and it's somewhat more restrictive
than the first option.
* The allowance works for *both registers and memory*, but only for what is
*allocated by the current function*. When a function ends, its caller
must cover the extra memory allocated by the callee with its own allowance.
There are several subcases.
* The allowance works only for *extra memory* allocated by the current
function (i.e. when changing a memory value length from 5 to 7 bytes,
5 bytes are still accounted as before, while only the two extra bytes
count against the current allowance). When dealocating memory (going from
7 to 5 bytes), one has to *add back the freed bytes* to the allocation(s)
from which they were taken (if any). This is rather complex to implement
and would increase the cost of all memory/register operations. Also, it
has a similar problem as before, where one fills memory within the
allowance with a chain of functions, while the last method only changes
the previously allocated memory.
* The allowance covers the *memory changed* by the current function. One
will still need to subtract the memory which changed owners from the
previous owner's allowance/memory usage, but there is only one
owner for each memory piece so it's easier to account for that.

Problems:
* one can split a function in multiple parts in order to take advantage
of the allowance, but, although there are clear cases where it's doable
(anything that computes some data which is not changed afterwards can
call the next processing step at the end) this is very limited compared
to the previous options;
* it is still a bit complicated to correctly account for all the memory;
* it may work in a counter-intuitive way and may complicate proofs
involving memory costs.

I would choose either the first or the last option, as they lead to less
complex IELE programs (and, not to mention, less complex costs and less complex
virtual machine).

* `RETURN`
Copy values from return registers to caller locations restore local context,
including (the current register stack memory requirements), mark registers'
Expand Down Expand Up @@ -562,9 +509,6 @@ Definitions

* *callValueSize()* - the size in machine words of the call value

* *callMemoryAllowance* - an amount of memory which one gets for free for
the duration of a local call.

* Multiplication cost function *mulCost*.
```hs
mulCost l1 l2
Expand Down

0 comments on commit 470502e

Please sign in to comment.