57 lines
3.4 KiB
Plaintext
57 lines
3.4 KiB
Plaintext
%p
|
||
I was just reading my ruby book, wondering about functions and blocks and the like, as one does when implementing
|
||
a vm. Actually the topic i was struggling with was receivers, the pesty self, when i got the exception.
|
||
%p And while they say two steps forward, one step back, this goes the other way around.
|
||
%h3#one-step-back One step back
|
||
%p
|
||
As I just learnt assembler, it is the first time i am really considering how functions are implemented, and how the stack is
|
||
used in that. Sure i heard about it, but the details were vague.
|
||
%p
|
||
Off course a function must know where to return to. I mean the memory-address, as this can’t very
|
||
well be fixed at compile time. In effect this must be passed to the function. But as programmers we
|
||
don’t want to have to do that all the time and so it is passed implicitly.
|
||
%h5#the-missing-link The missing link
|
||
%p
|
||
The arm architecture makes this nicely explicit. There, a call is actually called branch with link.
|
||
This almost rubbed me for a while as it struck me as an exceedingly bad name. Until i “got it”,
|
||
that is. The link is the link back, well that was simple. But the thing is that the “link” is
|
||
put into the link register.
|
||
%p
|
||
This never struck me as meaningful, until now. Off course it means that “leaf” functions do not
|
||
need to touch it. Leaf functions are functions that do not call other functions, though they may
|
||
do syscalls as the kernel restores all registers. In other cpu’s the return address is pushed on
|
||
the stack, but in arm you have to do that yourself. Or not and save the instruction if you’re so inclined.
|
||
%h5#the-hidden-argument The hidden argument
|
||
%p
|
||
But the point here is, that this makes it very explicit. The return address is in effect just
|
||
another argument. It usually gets passed automatically by compiler generated code, but never
|
||
the less. It is an argument.
|
||
%p
|
||
The “step back” is to make this argument explicit in the vm code. Thus making it’s handling,
|
||
ie passing or saving explicit too. And thus having less magic going on, because you can’t
|
||
understand magic (you gotta believe it).
|
||
%h3#two-steps-forward Two steps forward
|
||
%p And so the thrust becomes clear i hope. We are talking about exceptions after all.
|
||
%p
|
||
Because to those who have not read the windows calling convention on exception handling or even
|
||
heard of the dwarf specification thereof, i say don’t. It melts the brain.
|
||
You have to be so good at playing computer in your head, it’s not healthy.
|
||
%p
|
||
Instead, we make things simple and explicit. An exception is after all just a different way for
|
||
a function to return. So we need an address for it to return too.
|
||
%p
|
||
And as we have just made the normal return address an explicit argument, we just make the
|
||
exception return address and argument too. And presto.
|
||
%p
|
||
Even just the briefest of considerations of how we generate those exception return addresses
|
||
(landing pads? what a strange name), leads to the conclusion that if a function does not do
|
||
any exception handling, it just passes the same address on, that it got itself. Thus a
|
||
generated exception would jump clear over such a function.
|
||
%p
|
||
Since we have now got the exceptions to be normal code (alas with an exceptional name :-)) control
|
||
flow to and from it becomes quite normal too.
|
||
%p
|
||
To summarize each function has now a minimum of three arguments: the self, the return address and
|
||
the exception address.
|
||
%p We have indeed taken a step forward.
|