libera/#sicl - IRC Chatlog
Search
3:24:06
hayley
Though I am not proposing such a design for SICL, a read barrier could also be used to avoid the indirection through a dyad for standard objects. Say, a rack could start with a word that was, say, 0 if the rack is up to date, or a pointer to the next rack. The barrier would test if that word of a standard object is non-zero, just after loading a reference to a standard object. This would also allow for concurrent compaction, but it has the downside
3:27:08
hayley
I don't recommend using this approach as I don't know if all the branching in the read barrier is faster than the additional indirection in the dyad-and-rack representation, especially when the rack can be cached in the latter. And the former requires another tag test to rule out cons cells and immediate values, by the barrier needing to be run just after loading a reference; whereas loading the rack from a dyad can be done at any time.
3:29:16
beach
I have systematically ruled out read barriers as being too costly, but I might have to start thinking about those.
3:30:02
hayley
I was thinking that the indirection is a bit like a read barrier, so in a way, we already use read barriers.
4:02:48
hayley
But the indirection is only used when we need to retrieve a slot, whereas we'd have to run this read barrier more "eagerly", and we'd have to test tags for every tagged pointer we load. So the cost model is quite different.
6:05:20
hayley
If one thread had run the read barrier earlier, and held onto that rack, and then another thread performed CHANGE-CLASS on the object, then gave the first thread the new rack, the racks would not be EQ. One could put a barrier on EQ (a la Shenandoah, replication coping) but that's just another slowdown.
6:07:00
moon-child
what if the normal state of a rack is that the first word is a pointer to that rack
6:07:43
moon-child
I guess that's more expensive than it would otherwise be, since you have to dispatch on _type_
6:09:06
moon-child
I remain unconvinced that change-class needs to be fast. But sm2n said he uses it...
6:16:16
moon-child
you allocate a separate header and rack, but you put the rack directly after the header in memory
6:17:25
moon-child
you load the rack pointer from the header, and then have a branch checking that the rack pointer is right after the header
6:18:01
moon-child
and then you start reading from the location two words after the header right away, in the happy path--you don't have to wait for the rack pointer load to get back before you continue
6:18:26
moon-child
for a change-classed object, the rack pointer will point somewhere else, and you take the mispredict
6:34:12
hayley
I had thought about EQ comparing another word, and putting the rack after the header, but not the branch trick.
6:37:33
hayley
And that is clever, but I would like the fast path to eventually happen after a CHANGE-CLASS, if possible. The read barrier does at least achieve it.
6:39:42
hayley
Maybe there's some way to push fix-up work onto GC, and to push for an earlier GC if we take the slow path too many times (oh dear, it's like replication for thread-local heaps again).
8:24:45
splittist
moon-child: you don't want those things to be self-fulfilling - no-one uses change-class so we can make it slow so no-one uses change-class...
12:32:23
scymtym
beach: did you see the suggestion for an improved documentation string? (context: https://github.com/scymtym/architecture.builder-protocol/issues/12)
12:37:51
beach
There is still the problem that the cardinality is indicated as (:map KEY) whereas elsewhere it is (:map . KEY).
12:38:29
beach
That was part of my confusion, since I have not seen a cardinality indicated as (:map KEY) anywhere else.
12:43:48
beach
It is of course also a bit confusing that that cardinality designator (:map KEY-VAR) designates a cardinality of the form (:map . KEY).
12:46:39
scymtym
seems like using (:map . KEY-VAR), that is, an improper list, in the clause syntax would fix most of if not all of the issues?
12:47:24
scymtym
i can definitely make that change as :MAP relations have been extremely rare so far
12:49:42
beach
There are two things. One is that, elsewhere, a cardinality can be one of 1, ?, *, and (:map . KEY), but here it is (:map SOME-KEY), and it is not clear whether here you introduce yet another kind of cardinality, whether it is just a mistake, or whether the mistake is elsewhere.
12:50:53
beach
If the mistake is here, then there is a second thing, namely that a cardinarlity designator of the form (:map KEY-VAR) designates the cardinality (:map . SOME-KEY) rather than the cardinality designator being (:map . KEY-VAR). I am not sure why you would do that.
12:51:49
beach
And if you have a good reason for doing that, it should be pointed out in the documentation string.
12:52:37
beach
Like "Notice that the cardinality designator (:map KEY-VAR) is a proper list, but it designates the cardinality (:map . SOME-KEY) which is a dotted list".
12:59:57
scymtym
i think using only improper lists is the right call. the CARDINALITY-CASE code should be changed and the documentation should reflect that change
13:27:04
beach
Speaking of which, wouldn't the (:map . KEY) cardinality be ideal for use with something like the class options of DEFCLASS?
13:27:48
beach
For the longest time, I couldn't figure out what it might be used for, and then it occurred to me that this could be a perfect use case. But when I checked, it is not used there.
13:46:34
scymtym
that is a good idea. one problem could be the fact that the key of a relation with cardinality (:map . KEY) is stored in a relation argument. see https://gist.github.com/scymtym/c82fa4831e0f47d956205e796b6fd774 for an example. relations arguments (like initargs) are not nodes of the result tree, but the parser turns the name of an default initarg into a node
13:47:39
beach
I see. I hadn't realized that, because of my (still) partial understanding of that cardinality.
13:49:10
scymtym
extending relations to connect more than two nodes would turn the graph into a hypergraph and that would require a different graph construction protocol, i think. so the appropriate representation of default initargs in the current framework probably is one node for the default initarg, one child node for the name and one child node for the value form
13:51:03
scymtym
the map cardinality would be appropriate for things like hash tables with simple keys, sparse arrays or arrays of some rank different from 1. in those cases, the mere order of related child nodes is not sufficient as a key