add method resolution page
This commit is contained in:
parent
ed0d766705
commit
5c7367d8f5
@ -5,3 +5,4 @@
|
|||||||
%li= link_to "Debugger", "debugger.html"
|
%li= link_to "Debugger", "debugger.html"
|
||||||
%li= link_to "Memory" , "memory.html"
|
%li= link_to "Memory" , "memory.html"
|
||||||
%li= link_to "Calling" , "calling.html"
|
%li= link_to "Calling" , "calling.html"
|
||||||
|
%li= link_to "Method Resolution" , "method_resolution.html"
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
%p
|
%p
|
||||||
Dynamic object oriented languages rely very heavily on dynamic method
|
Dynamic object oriented languages rely very heavily on dynamic method
|
||||||
resolution and calling. Dynamic method resolution is the process of finding a
|
resolution and calling.
|
||||||
|
=link_to "Dynamic method resolution" , "method_resolution.html"
|
||||||
|
is the process of finding a
|
||||||
method to call, and the calling convention defines how arguments are transferred and
|
method to call, and the calling convention defines how arguments are transferred and
|
||||||
control changes and returns.
|
control changes and returns.
|
||||||
|
|
||||||
@ -113,4 +115,3 @@
|
|||||||
%br
|
%br
|
||||||
Which may in turn lead to an elaborate inlining scheme, thus eliminating the small
|
Which may in turn lead to an elaborate inlining scheme, thus eliminating the small
|
||||||
performance hit completely.
|
performance hit completely.
|
||||||
|
|
||||||
|
98
app/views/pages/rubyx/method_resolution.html.haml
Normal file
98
app/views/pages/rubyx/method_resolution.html.haml
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
= render "pages/rubyx/menu"
|
||||||
|
|
||||||
|
%h1=title "Dynamic Method resolution"
|
||||||
|
|
||||||
|
%p
|
||||||
|
Dynamic method resolution is the process of finding a method to call.
|
||||||
|
The
|
||||||
|
=link_to "calling convention" , "calling.html"
|
||||||
|
defines how arguments are transferred and control changes and returns.
|
||||||
|
|
||||||
|
%h2 Resolution in general
|
||||||
|
%p
|
||||||
|
To determine a Method in Rubyx, we need to determine the
|
||||||
|
%b Type.
|
||||||
|
%p
|
||||||
|
Types store the methods, and with the method name we can then find the appropriate
|
||||||
|
Method.
|
||||||
|
%p
|
||||||
|
Ruby has a fallback for when a method is not found: we then call
|
||||||
|
%em method_missing.
|
||||||
|
This is defined on Object, and as every object is an object,
|
||||||
|
%em method_missing
|
||||||
|
is guaranteed to be found.
|
||||||
|
%p
|
||||||
|
This is the same process for dynamic and static resolution.
|
||||||
|
|
||||||
|
%h2 Static Resolution
|
||||||
|
%p
|
||||||
|
The need to resolve a method dynamically stems from an inability to determine
|
||||||
|
the Method at compile-time.
|
||||||
|
%p
|
||||||
|
Currently the only way to be sure of an expressions type, or the only case
|
||||||
|
the compiler recognises, is an assignment directly before the call. This
|
||||||
|
"types" the variable that is assigned and we can retrieve the method.
|
||||||
|
%p
|
||||||
|
Off course calls on constants are also recognised. But otherwise
|
||||||
|
a dynamic resolution is initiated.
|
||||||
|
|
||||||
|
%h2 Dynamic Method Resolution
|
||||||
|
%p
|
||||||
|
When static resolution has failed, the compiler emits code to resolve the
|
||||||
|
method at runtime. This process resolves around a cache, and currently a
|
||||||
|
cache of one, captured by the class
|
||||||
|
=ext_link "CacheEntry" , "https://github.com/ruby-x/rubyx/blob/master/lib/parfait/cache_entry.rb"
|
||||||
|
|
||||||
|
%h3 Vool
|
||||||
|
%p
|
||||||
|
Static resolution is done at the Vool level, where the CacheEntry is also created
|
||||||
|
and then used as any other constant. Ie there is exactly one CacheEntry for every
|
||||||
|
call site (SendStatement).
|
||||||
|
%p
|
||||||
|
Vool breaks the resolution into it's logical component steps, ie:
|
||||||
|
%ul
|
||||||
|
%li Check the current type against cached type
|
||||||
|
%li Update cached type if needed
|
||||||
|
%li Update cached method if needed
|
||||||
|
%li Call the cached method
|
||||||
|
|
||||||
|
Breaking down means that Mom Instructions are emitted to effect the logic above.
|
||||||
|
Most of the logic (like the if that is needed) already exists. But the last two
|
||||||
|
steps require special instructions described below.
|
||||||
|
|
||||||
|
%h3 Mom
|
||||||
|
%p
|
||||||
|
The method cache update described above is basically an assignment where
|
||||||
|
we assign the resolved method to the cache. But to do that, we need to finally
|
||||||
|
do the method resolution.
|
||||||
|
%p
|
||||||
|
The implementation of the
|
||||||
|
%em ResolveMethod
|
||||||
|
is quite a bit longer than most other Mom instructions, but basically does:
|
||||||
|
%ul
|
||||||
|
%li Load methods from current (cached) type
|
||||||
|
%li Enter a while loop until we hit nil (goto NOT_FOUND if nil)
|
||||||
|
%li compare the name of the method with the given name and goto OK if equal
|
||||||
|
%li get the next method (they too are a linked list) and start at while
|
||||||
|
%li NOT_FOUND find method_missing and save in cache (similar process)
|
||||||
|
%li OK: save method in cache
|
||||||
|
To achieve readable code for this low level assembler programming a DSL is
|
||||||
|
used. The
|
||||||
|
=ext_link "result", "https://github.com/ruby-x/rubyx/blob/master/lib/mom/instruction/resolve_method.rb#L32"
|
||||||
|
is quite understandable.
|
||||||
|
|
||||||
|
%p
|
||||||
|
The actual dynamic call does differ from it's static counterpart, but maybe
|
||||||
|
surprising little. In essence both static and dynamic calls:
|
||||||
|
%ul
|
||||||
|
%li create a label and save the return address
|
||||||
|
%li load the methods jump address
|
||||||
|
%li swap in the next message, replacing the current
|
||||||
|
%li jump to the address
|
||||||
|
%p
|
||||||
|
The main difference is in loading the method's address (step 2). Where a static
|
||||||
|
setup just loads the method constant, the dynamic one load the CacheEntry first, and
|
||||||
|
the method from that.
|
||||||
|
%br
|
||||||
|
That is basically the main difference. Currently (4/18) a FunctionCall/DynamicJump is
|
||||||
|
still issued, but they are so similar that they will probably be unified soon.
|
Loading…
x
Reference in New Issue
Block a user