add a page on calling convention
This commit is contained in:
parent
18da395ed9
commit
ed0d766705
@ -14,7 +14,7 @@ body
|
||||
background: $body-background url("bkg.png") 0 0
|
||||
color: $body-foreground
|
||||
font-size: 16px
|
||||
line-height: 1.5
|
||||
line-height: 1.4
|
||||
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace
|
||||
|
||||
|
||||
@ -46,7 +46,6 @@ header
|
||||
margin: 0 0 40px 0
|
||||
h1
|
||||
font-size: 30px
|
||||
line-height: 1.5
|
||||
margin: 0 0 0 -40px
|
||||
font-weight: bold
|
||||
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace
|
||||
|
@ -4,3 +4,4 @@
|
||||
%li= link_to "Parfait", "parfait.html"
|
||||
%li= link_to "Debugger", "debugger.html"
|
||||
%li= link_to "Memory" , "memory.html"
|
||||
%li= link_to "Calling" , "calling.html"
|
||||
|
116
app/views/pages/rubyx/calling.html.haml
Normal file
116
app/views/pages/rubyx/calling.html.haml
Normal file
@ -0,0 +1,116 @@
|
||||
= render "pages/rubyx/menu"
|
||||
|
||||
%h1=title "Calling convention and method resolution"
|
||||
|
||||
%p
|
||||
Dynamic object oriented languages rely very heavily on dynamic method
|
||||
resolution and calling. Dynamic method resolution is the process of finding a
|
||||
method to call, and the calling convention defines how arguments are transferred and
|
||||
control changes and returns.
|
||||
|
||||
%h2 Calling
|
||||
%p
|
||||
To start with the "easier" problem, we'd define the calling convention first,
|
||||
and note that the process is very very similar when done dynamically at run-time.
|
||||
|
||||
%h3 Previous approaches
|
||||
%p
|
||||
A quick review of existing c-like, stack based conventions, will reveal what we
|
||||
need to consider and solve. Coming from assembler, C uses a stack pointer to
|
||||
push both return address and arguments. Subsequently the function may use the
|
||||
the same stack to push/pop local variables, and off course it usually does calls
|
||||
itself.
|
||||
%p
|
||||
Without going into detail, there are clear problems with this. For me the biggest
|
||||
is that this is not object oriented. The size of argument and frame (local)
|
||||
sizes of the stack are not locally known and require extensive knowledge of the
|
||||
compiler to extract at compile time.
|
||||
%p
|
||||
The approach used a constant of the time: that a method returns to where it was called.
|
||||
In the face of lambdas this is not true anymore. This is linked in with the
|
||||
lifetime of variables that arises from having code live after the calling function has
|
||||
returned.
|
||||
|
||||
%h3 Linked List
|
||||
%p
|
||||
To overcome some of the issues, and in general create an object oriented solution,
|
||||
a linked list approach was chosen over the traditional stack based.
|
||||
%br
|
||||
In rubyx the class that represents the elements of the linked list is called
|
||||
Message. In fact the linked list is doubly linked and holds several
|
||||
other necessary data, like return address, return value and others.
|
||||
|
||||
The arguments and local variables are separated out as separate objects.
|
||||
These instances are fully typed and as such the runtime information about the
|
||||
argument is easily retrievable.
|
||||
|
||||
%h2 Arguments and Locals
|
||||
%p
|
||||
To detail the handling of arguments and locals we'll demonstrate the approach
|
||||
with the arguments and not that locals are very very similar.
|
||||
%p
|
||||
The Arguments are passed in what is basically a normal object. Currently
|
||||
derived from NamedList, but this does not add much over basic object functionality.
|
||||
%p
|
||||
Argument names, as defined in the method, map to instance variable names on the
|
||||
object. This approach is logically equivalent to dynamically creating a class
|
||||
for each methods arguments, but we only create the Type. The Type being a mapping
|
||||
of names to indexes of where the variables are stored in the object.
|
||||
%p
|
||||
To have the information available at run-time the object-type of the Arguments
|
||||
instance has to be changed dynamically in the method setup. As the type is known
|
||||
in in fact stored in the Method, this is quite easy.
|
||||
|
||||
%h3 Allocation
|
||||
%p
|
||||
When allocating the objects needed, ie Message, Arguments and Locals, we pay some
|
||||
run-time price for this more explicit handling of information.
|
||||
%br
|
||||
But it is not as much as one might think. All the objects are of identical size
|
||||
and can be kept in a linked list. "Allocation" is then just grabbing the first link
|
||||
from a known (compile-time known) place and relinking. About 20 risc instructions
|
||||
in total.
|
||||
%br
|
||||
Also we need to update the type information in the objects as stated above, but this
|
||||
too is not much. (older) Test have shown that the calling convention is about 30-50%
|
||||
slower than C. This makes it very much faster than Interpretation, even taken into
|
||||
account the since added functionality. I would guess by now it is about 2x slower than
|
||||
c, which is very acceptable, given that it buys us many a simplification regarding
|
||||
lambdas, exceptions and fibers.
|
||||
|
||||
%h3 Control
|
||||
%p
|
||||
Transferring control is then quite simple, basically we jump to the next methods
|
||||
binary address. Before the actual jump, we have to
|
||||
%ul
|
||||
%li Store the return address
|
||||
%li Swap the current Message with the next one that we prepared
|
||||
%br
|
||||
This is quite equivalent to using the stack, and amounts to only one or two
|
||||
instructions more.
|
||||
%p
|
||||
Returning from a Method is equally simple. The convention is that any possible
|
||||
return value will have been stored in the current Message before the
|
||||
ReturnSequence is initiated. Then we:
|
||||
%ul
|
||||
%li Move the return address from the message to a register.
|
||||
%li Swap the previous message in (replacing the current)
|
||||
%li Jump to the stored address
|
||||
|
||||
%h3 Summary
|
||||
%p
|
||||
To summarise, we
|
||||
%ul
|
||||
%li use typed objects to store information
|
||||
%li use a linked list
|
||||
%li are well prepared for the future, lambdas etc
|
||||
%li can easily implement fibres
|
||||
%li do not have stack as a separate memory area, or concern
|
||||
%li have performance closer to c than mri
|
||||
|
||||
And maybe most importantly we have a relatively easy to understand mechanism that
|
||||
as such can be reviewed and improved by many.
|
||||
%br
|
||||
Which may in turn lead to an elaborate inlining scheme, thus eliminating the small
|
||||
performance hit completely.
|
||||
|
Loading…
Reference in New Issue
Block a user