freenode/#sicl - IRC Chatlog
Search
13:26:03
Bike
did you see what i mentioned about change-class and dfuns/disembodied call sites? i'm going to try things anyway, but it's a pretty critical caveat
13:26:59
beach
I took note, and I'll try to keep it in mind when I get back to this idea. Or, maybe you will figure it out first.
13:29:03
Bike
maybe on sicl you can determine quickly if an object has been allocated in the thread local nursery, so other threads don't have access to it?
13:30:37
beach
One could also put a lock on change-class. It is bound to be an infrequent operation.
13:32:33
Bike
it would be any region between testing the class of an object and calling a dfun/specialized function/whatever
13:33:26
Bike
a lock on change-class itself to avoid the mutant instances i mentioned before would probably be fine, though
13:33:54
Bike
well, are you okay with, like, grabbing a lock every time a method function is entered? because i don't know about that one.
13:38:20
Bike
and of course for instances of built in classes, or possibly structures depending on how sicl wants to do that, none of this matters
13:38:44
Bike
(i mean, i know sicl structure instances are the same as standard object instances, but you could still forbid change-class)
13:40:31
beach
Now, the only built-in classes are those for which there are no instances, or only immediate instance, and of course CONS.
13:41:17
beach
So CONS, CHARACTER, SINGLE-FLOAT, FIXNUM, and all the ones with no direct instances like SEQUENCE, LIST, etc.
13:47:02
beach
Well, there can't be a single global lock since most of the time of any thread would probably be spent in a method function. Now, it is a problem if that method function is not an accessor?
13:52:41
beach
So, apparently "air con" is a frequent abbreviation for "air conditioning" but "I have air con" does not translate to "Je l'air con" in French.
13:53:27
Bike
i suppose that depends on how deep it goes. If you have a function FOO that calls a function BAR that calls an accessor, and with dfuns only FOO does any discrimination, you probably still have an issue
13:54:11
Bike
like have (defmethod put ((x class-a)) (push x *class-as*)) (defmethod put ((x class-b)) (push x *class-bs*)) and then have class-a's in *class-bs*
13:54:56
beach
Sure, but aren't those bugs due to bad programming again? And I maintain that we can't protect programmers from themselves.
13:56:09
beach
I mean, in your example, having class-a's in *class-bs* can happen without any threads what so ever.
13:56:49
Bike
depends on what you mean by bad programming. the standard of course doesn't define any concurrent behavior. i think "change-class concurrent with generic function dispatch is defined" and "...is undefined" are both reasonable ideas of how things ought to work
13:58:21
Bike
i mean, of course sicl can say it's undefined, and then the programmer is hitting undefined behavior, so it's bad programming.
13:58:25
beach
And I am willing to accept that, as long as the system is safe, we can let things like that happen, if they are due to programming that will make the outcome depend on relative speed of threads.
14:00:05
Bike
speaking of: to include machine atomic read-modify-write operations i'm probably going to need to define more cleavir instructions. this means some redundancy, like, there will be an aref instruction, an aset instruction, and then acas, and then armw or something for atomic increment and so on
14:00:21
Bike
and i'm wondering if there isn't a better way to arrange this. i mean, for a start i can just give aref and aset instructions a common superclass
14:00:30
beach
Oh, and I don't want any "impossible situations" to be possible. As in two events that are clearly ordered in time, and the first one seeing a change that the second doesn't.
14:04:44
Bike
hm, dunno. the problem pretty much comes when you swap out a rack, so you need adjust-array or change-class or something.
14:06:23
beach
My take is that, if there is a loop of some kind, and a function call inside the loop, then there could be some side effect of that function call, so a slower version may be required.
14:07:39
Bike
and if there's some primitive operation that has a side effect, that also rules out the fast version?
14:08:27
Bike
doesn't seem like there are a lot of loops like this that could actually grab the rack, then?
14:10:59
beach
I don't know. You may very well be right. Though things like summing up the elements doesn't seem to have any side effect in it.
14:12:07
Bike
probably tricky to determine that for anything beyond a lexical variable that's not closed over (though that's an important case)
14:12:17
beach
And didn't we conclude that a simple test to check that the rack has not changed before each loop would be enough to give the right to continue?
14:14:28
beach
I guess you are well on the way, but there might be things that are highly implementation specific.
14:15:53
beach
By the way, are you changing the way Clasp represents standard objects. Your conversations are a bit to long for me to follow, and they involve lots of C++ which I don't really understand.
14:17:25
Bike
well, i was rearranging some things. right now in clasp we have kind of a funny arrangement with funcallable instances. since the code pointer is directly in the instance instead of in the rack, and matches the offset of the code pointer in functions that aren't instances, it's hard to arrange for the rack to be at the same offset in both instances and funcallable instances
14:17:58
Bike
for a while we fixed this by having a useless spacer in non-funcallable instances, so i was trying to arrange things so that the rack can be at different offsets with no problem
14:18:22
Bike
i'd still like to do that, but for now i just have the class at a different offset instead. it's not as important to access quickly, i think
14:18:53
Bike
and i might try putting the class in the rack and using triples and so on, at some point, but first i think i'll play with dfuns a bit
14:19:48
Bike
i just set it up so that the ctor mechanism is used for make-instance calls even when the class isn't constant, and that works fine
14:20:08
Bike
doubles the speed of instance creation in some really basic tests, from skipping the keywords check and the loops in shared-initialize
14:22:13
Bike
might have to reconsider how effective method functions are passed their arguments. i think a general case might mean passing all the required arguments, all those objects' racks, and then further arguments could maybe be spread out to avoid reprocessing
14:22:35
Bike
like if you have a method with (&key a) and another with (&key b), the discriminating function could look for both keys and pass them along as regular arguments
14:24:20
beach
Certainly, argument passing within a generic function may be very costly if done the most general way.
14:24:50
Bike
yeah, right now on clasp each method function with &key deconstructs it. it's obviously suboptimal
14:26:17
Bike
i don't know how SBCL generic functions handle keyword arguments. but yeah i should figure it out, let's see
14:27:26
Bike
nope, looks like the fast method function still takes &key, so there will be reprocessing
14:28:33
beach
Also, SBCL doesn't depend as much on generic functions as, say, SICL will, and Cleavir already does.
15:45:37
heisig
Inlining the keyword parsing step is one of the most rewarding features of fast-generic-functions. But it is hard to do it without sealing all involved entities.
15:47:15
heisig
If we had an extensible annotation/recompilation mechanism for functions then "Doesn't call change-class" would be an excellent annotation.
15:50:54
heisig
Another convenience feature could be that (maybe only on safety 3) change-class inspects the stack and asserts that no method dispatch assumptions are violated.
16:34:39
jcowan
The Oracle JVM has a concept of lightweight locks, which are used initially. If a lot of contention takes place, the lock is upgraded to a heavyweight lock.
16:44:22
jcowan
Spin locks are used first, but if they time out, then the regular locking mechanism kicks in. A lightweight lock involves only single CaS operation that gets inlined, whereas a heavyweight lock maintains a per-lock queue and a non-inlined procedure to manage it.
16:48:13
beach
My (admittedly small) family just announced that dinner is served. After dinner, I will spend time with her. I might check in later. If not, I'll be back tomorrow morning (UTC+2).
21:17:02
Bike
i realized i could reuse most of the ctor code for a dfun for reinitialize-instance, so i tried that out. in the simplistic case of one keyword argument and no custom methods, it's about fifty times faster than calling reinitialize-instance