freenode/#clasp - IRC Chatlog
Search
22:59:19
drmeister
Lets say I want generic function dispatch to be as fast as possible - (1) I want to dispatch on registers as much as possible but if there are more required arguments than registers I need to transition to a va_list once I run out of registers.
23:01:30
drmeister
(2) I need to save and rewind the va_list on entry to the generic function discriminator because the methods may need the argument list.
23:02:20
drmeister
(3) If we have fast-methods then in those cases I can dispense with #2 and just pass registers to the fast-methods.
23:28:01
drmeister
Here's a thought. The call-history is an alist of (specializers . effective-method-function/optimized-slot-(reader|writer) )
23:28:44
drmeister
If we wrap the effective-method-function in a struct that stores some additional information with it...
23:29:43
drmeister
Mostly I want to know in the dispatcher if I need to generate a vaslist and rewind it to handle all of the arguments.
23:30:13
drmeister
So if I know that none of the effective-methods need a vaslist - I won't bother allocating space or initializing it.
23:30:47
drmeister
Does the generic-function lambda-list reflect what all of the methods are looking for?
23:31:37
Bike
but all the methods have to have the same number of required arguments, optional arguments, and whether to accept rest arguments
23:31:43
drmeister
But if any of them take keyword arguments - then the generic function lambda list has to reflect that - correct? With &key and &allow-other-keys?
23:32:26
specbot
Congruent Lambda-lists for all Methods of a Generic Function: http://www.lispworks.com/reference/HyperSpec/Body/07_fd.htm
23:33:03
Bike
okay, so i guess actually no, you could have a method that takes &key while the generic function only has &rest.
0:26:25
drmeister
Basically, if we wrap the effective-method-functions in the call history with a struct that stores optimization information about them - specifically if they can use registers or they need a list of arguments...
1:53:56
drmeister
How could we manage that other than having llvm do the inlining? The discriminator compiler is a special purpose compiler that doesn't follow bclasp or cclasp conventions.
1:56:56
drmeister
I needed a compiler that wouldn't use any generic functions and bclasp generates shitty code - so I wrote a custom compiler for it.
1:57:50
drmeister
What goes on in GF dispatch is really simple compared to general code - (1) read stamp, compare to integer ranges - repeat.
1:58:17
drmeister
Also, there are no issues with closures or anything complicated - so inlining could be done perfectly well using llvm inlining.
2:02:07
Bike
i want to have it so that the discriminating function computer or whatever calls compute-effective-method, gets the effective method, and processes it in a lexical environment with helpful macros
2:02:34
Bike
So like, each outcome could have a call-method definition that looks at the method, and if it's a standard accessor, just expands into standard-instance-access for the particular class slot location
2:03:32
Bike
and we could expand it, so, for example, put a slot in methods that indicates whether it calls next methods
2:03:45
Bike
the call-method macro can look at that slot, and if the method doesn't do anything like that be more direct about it
2:04:09
drmeister
Can we set it up so that all of this processing happens ahead of time and the results are stored in the outcome of the call history. And do it in closfastgf.lsp or some other clos file.
2:05:08
drmeister
You could put all of that optimization information in a 'outcome' struct and the cmpfastgf.lsp compiler will act on it.
2:06:41
drmeister
Ahead of the time the discriminating function is compiled as a result of an invalidated-dispatch-function call.
2:07:21
Bike
well, it can be done whenever the compute-effective-method-maybe-optimize thing is called
2:08:09
drmeister
One stage happens during a dispatch miss. It does compute-applicable-methods-xxx and analyzes the methods that would go into the effective method, builds the effective method and stores the optimization analysis with it in the 'outcome' of a call-history entry.
2:09:21
drmeister
Yes, the slot location is calculated in the first stage and stored in an optimized-slot-reader or optimized-slot-writer structure.
2:09:47
Bike
well, t hat's fine then. we just reduce the "outcomes" back to being functions, but inline the functions
2:11:03
drmeister
Yes - that will work - we just need to store the llvm-ir in the outcome and then add it to the llvm Module of the discriminating function.
2:19:34
Bike
right now we have every outcome be something like (funcall emf args nil) as far as i can tell
2:20:02
drmeister
We are coming from different worlds - I don't see how inlining makes it simple - an llvm function still needs to accept arguments.
2:20:28
drmeister
Accessors are easy to inline - I'm essentially doing it already except the for some reason they aren't actually inlined.
2:20:59
drmeister
I'm thinking more general effective methods that take 0-4 required+optional arguments.
2:21:34
Bike
okay, so say we have (defgeneric foo (x y)), then our discriminator can be (once you fix things) (lambda (x y) (tagbody ... ...effective method...)), right? but with llvm weirdness.
2:22:02
Bike
and something in there puts x and y in a va-list, and effective methods are called with that va-list.
2:23:16
drmeister
But if none of the effective methods need a va-list and they all take two arguments - then you want (lambda (x y) (tagbody ... (funcall fast-effective-method x y)))
2:23:49
Bike
if we could compute the effective method form and just put that there instead, it could refer to variables directly
2:25:20
drmeister
Yes, in Common Lisp land - but we aren't quite in Common Lisp land. The discriminator is a special purpose, pure llvm-ir function that calls other llvm-ir functions.
2:26:25
drmeister
So you could compile fast-effective-method to an llvm-ir function that accepts a closure, number of arguments and two arguments and then in the discriminator you call foo(closure,2,x,y) and then inline the first function at that call site.
2:28:03
Bike
if there are effective methods, they just get the arguments to the gf and maybe the gf as arguments
2:29:45
drmeister
The general Clasp calling convention is foo(closure,num-args,farg0,farg1,farg2,farg3,...)
2:30:35
Bike
the effective method function is pretty special purpose and we basically want it to be inlined, so i don't see any need to conform to practically anything if it doesn't have to
2:32:35
Bike
an effective method is certainly not a closure, the clhs is even weirdly explicit about what's in its environment
2:33:30
drmeister
A closure is an environment and a function. When the function is called it is passed its environment.
2:35:54
Bike
and potentially whatever the user specifies but that's exotic and underspecified so i'm not worried about it
2:37:08
Bike
"When a method is actually called by an effective method, its first argument will be a list of the arguments to the generic function. Its remaining arguments will be all but the first argument passed to call-method."
2:37:48
Bike
but i'm not too worried about it because the closer mop guy wrote a paper about how much this sucks
2:40:01
Bike
i mean, there are a few other problematic things, like here call-next-method gets actual methods in the next-methods, but both clasp and sicl pass the method functions
2:59:36
Bike
anyway, if we're smarter with the result of compute-effective-method, we can use the fact that call-method is a macro but gets actual methods as argument to flexibly change the method invocation protocol
3:31:13
Bike
actually i guess method functions can be closures, if nothing else you can provide it manually