freenode/#clasp - IRC Chatlog
Search
14:44:35
Bike
Ok. So, say you have a class that defines a slot and a subclass of that class. The effective slots end up having different locations, but the same reader method can read both, since it's specialized on the superclass.
14:45:10
Bike
So for fastgf to do an optimized read outcome that doesn't look up the location at all, it has to have a different outcome depending on the actual class of the reader argument, not just the list of applicable methods.
14:45:52
beach
Yes, and it already does, because the call history contains actual stamps of instances.
14:46:33
Bike
Right. But, so the method outcome computer can't use compute-effective-method or something too similar to it, since it's not that particular and only gets the effective methods. Right?
14:47:36
beach
Right. When an accessor method is returned, the location has to be computed using the class of the argument.
14:48:08
beach
Hence the CLASS-SLOTS, find the right slot definition, find the location in that slot definition.
14:49:05
Bike
Okay. I see. We weren't doing that so we hit this problem. Just wanted to confirm that you had more specificity in mind.
14:50:15
Bike
we have call histories and stuff worked out this way, but the otucomes were being computed by basically compute-effective-method
14:51:29
beach
<beach> I think you can use CLASS-SLOTS to find all the effective slot-definitions of a class.
14:54:02
Bike
Dunno. I'm only peripherally involved in fastgf, though I'm going to look at effective methods closer later
15:07:23
Bike
We ran into it with unbound-slot for whatever reason, to add another layer of confusion
15:08:48
beach
By the way, I had an idea for avoiding the test for unbound slots in most cases (at least I think so).
15:10:10
beach
It relies on the fact that instance of many (most?) classes never have unbound slots, because the class has initforms or default initargs, or simply because all initargs are always supplied.
15:12:16
beach
So the idea is to check that all slots are bound after :INITIALIZE-INSTANCE, and if so, generate discriminating functions that don't check. Whenever there is a violation of this condition, perhaps because someone called slot-makunbound, then the class is marked, and subsequent slot readers check whether the slot is bound.
15:14:18
beach
Unfortunately, once there has been a violation of this condition, then slots must be checked in all future accesses.
15:15:22
Bike
but yeah, there are tons of optimizations that can be done with this combination of compilation and good invalidation
15:16:01
beach
So, assume that slots are always bound. Whenever a slot is unbound as a result of initializing an instance or as a result of a call to slot-makunbound, then mark that slot as having to be checked and invalidate all slot readers of all classes with that slot.
15:17:22
beach
Again, not sure much will be gained. It avoids a test that will almost always be true, so perhaps the branch prediction logic will make it almost free.
15:17:26
Bike
so whenever slot-makunbound is called, it gets the class of the instance, gets the readers out of it, invalidates them
15:20:19
Bike
one thing i think would be good is if we could compile method bodies to inline accessors all the way to referencing the instance slot vector with the location
15:27:05
beach
The other day I think I understood how it is done, but now I can neither remember it nor figure it out.
15:29:27
beach
Oh, I know. The test for the exact class can't be avoided, but it is no more expensive than a call to an accessor generic function.
15:35:05
beach
Same reason as before. The class of the argument can be a subclass, and the location of the slot can differ in different subclasses.
16:02:17
beach
You are right that there are many interesting optimizations to explore. But, in order to do that, it must not be too hard to debug such code.
16:19:38
Bike
well, i think at present meister has twice as much debug code as actual code, so we have something there at least
16:36:02
drmeister
Thank you both for helping me understand how to generate these optimized slot accessors.
17:22:11
Bike
clhs says ensure-generic-function gets a method combination object, so when initializing a generic function you shouldn't need the gf to compute the method combination
17:23:13
Bike
the method combination can get the gf as an argument, but that's okay, the effective method isn't computed until later
17:24:06
drmeister
Guidance is appreciated. A new problem cropped up in conditions.lsp - I'm tracking it down.
18:06:50
drmeister
Read: (DEFSTRUCT (RESTART (:PRINT-FUNCTION RESTART-PRINT)) NAME FUNCTION REPORT-FUNCTION INTERACTIVE-FUNCTION (TEST-FUNCTION (CONSTANTLY T)))
18:07:03
drmeister
Could not find slot - starting from method #S(STANDARD-WRITER-METHOD ) got specializer class #S(BUILT-IN-CLASS NULL ) and slot-defs NIL and slot-name KEYWORDS : maybe-instance -> NIL
18:08:21
drmeister
That is the error that is being generated. It looks like it's in the process of generating an optimized slot writer on the NIL object.
18:11:09
drmeister
I can't print a backtrace with arguments because it crashes. So I'm adding code to carefully investigate the backtrace.
18:13:43
drmeister
I wish I could stop it from blowing up every time I print something that it isn't prepared to print.
18:37:58
Bike
it seems like if you have defgeneric then defmethod in the same file, teh defmethod will define the gf at compile time, and then the defgeneric will just reinitialize it upon load. that's... pretty weird?
18:54:15
drmeister
Whoops - I did it again. Writers arguments are ( value instance ) and readers are (instance)
20:43:07
Bicyclidine
the sandbox environment doesn't know keywords are constants bound to themselves. that's something
21:06:18
Bicyclidine
if you put :foo in the normal repl you get :foo back, because all keywords are constants bound to themselves
21:06:28
Bicyclidine
but the sandbox isn't clued into that, so if you put :foo in its repl it says unbound variable
21:16:48
drmeister
And black is white and up is down - it seems perfectly fitting for the times we find ourselves within.
22:09:41
drmeister
The only thing that's not working is multithreaded slime - and I'm working on that.
22:12:49
drmeister
fastgf lets me do this because it has an ancillary benefit, it recognizes invalid objects in a very, very inexpensive way.
22:13:40
drmeister
ECL needs to check if an object is invalid with every access - that spoils efficiency.
22:14:28
drmeister
Don't run profiling on the compiler. That's like trying to figure out inefficiencies in the US economy by looking down from the ISS.
22:30:23
drmeister
More constructively - do run profiling on small test cases that run a lot slower than sbcl and figure out where they are spending their time.
23:08:15
Bike
i have some ideas about effective methods that i think can shave generic function dispatch down more, though that might not be a bottleneck now
23:21:40
drmeister
I have a simple test case. I can't compile anything in a separate thread - it locks up.
23:22:02
drmeister
(mp:process-run-function 'foo #'(lambda () (funcall (compile 'nil '(lambda () (dotimes (i 100) (format t "Hello ~a~%" i)))))))
0:22:22
specbot
compute-discriminating-function: http://metamodular.com/CLOS-MOP/compute-discriminating-function.html
0:34:46
drmeister
Bike: I'm wracking my brain - trying to figure out how to identify what llvm value might be leaking across threads and causing this problem (if indeed this is the problem).
0:36:58
drmeister
On another tack - a DEFPARAMETER or DEFVAR in the main thread as Clasp is starting up would write into the value slot of the symbol - right?
0:37:28
drmeister
What if I put a check in symbol-value that checked if the value slot is read and an LLVM value was read out?
0:39:04
Bike
it was a few weeks ago... i'd start when the llvm5 stabilized and binary search up from there
0:49:35
drmeister
I'm looking for a DEFVAR or DEFPARAMETER in the cmp directory that would contain an LLVM value.
0:56:09
drmeister
The target-triple and the data-layout are calculated at startup and put into global variables.
0:57:16
drmeister
I don't know. They have string representations and I think llvm internal representations. The former should be fine to share, the latter - probably not.
1:01:10
drmeister
cmp::*default-target-triple* -> "x86_64-apple-macosx10.12.0" cmp::*default-data-layout* -> #<DATA-LAYOUT >
1:06:50
drmeister
I was a busy boy - destroying all of Clasp's multithreaded compilation capabilities.