freenode/#clasp - IRC Chatlog
Search
17:00:24
drmeister
Currently, the only place anything like (simple-vector ext:byte8) -> core::SimpleVector_byte8_t_O is expressed in Clasp is here:
17:01:35
drmeister
And I knew that had a bad code smell to it when I wrote it - but "when needs must the devil drives".
17:01:57
Bike
in the most common case of (make-array ... :element-type some-constant) we could just call StrWNs_O::make or whatever directly
17:02:53
drmeister
Is there a way in Common Lisp to reduce a vector or array type specifier to a canonical type specifier?
17:03:57
drmeister
Meaning we make the map of type-specifier -> header-value(-range) use EQUAL and throw the canonical type specifier for every array type in as a key
17:05:04
drmeister
Then the typeq-instruction takes whatever type specifier it is given, canonicalizes it, looks it up in the map and if it's there generates code and if not it generates a call to typep.
17:06:52
drmeister
There is a call generated like this: add_range_typeq_test<core::SimpleMDArray_O,core::SimpleMDArray_int32_t_O>();
17:11:55
drmeister
The values above are the stamp values, the header value for these are ((stamp<<4)|1)
18:15:34
Bike
something is conceptually weird with typeq and i'm not sure how to fix it. type inference wants typeq instructions that deal with a sublattice of types. but typeq also means actual checks of actual user-provided types, which should not be a sublattice, and which should be efficient code
18:44:56
Bike
i guess (if (typeq foo bar) baz bad) could be compiled as (if ([check] foo bar) (progn (the bar foo) baz) (progn (the (not bar) foo) bad))
19:21:58
drmeister
It maps class symbols that correspond to types to either a fixnum (header-value) or a (CONS header-value-min header-value-max)
19:22:49
drmeister
Bike: Do you have any quick fixes for the looong (40 min) compilation of that one form in ironclad?
19:23:16
drmeister
I need to build a new docker image for the nglview stuff and a quick fix there would save me 40 min.
19:24:37
Bike
uhm, depends no your parameters for quick fix. i could add a policy to turn off dynamic extent analysis specifically that you could use
19:24:53
drmeister
It turns out that the Python version of nglview was old and the Javascript code that the Common Lisp code was using would use the old Javascript if I ran the Python version first and then use the new Javascript code if I ran the Common Lisp version first.
19:25:57
Bike
or you could just (declaim (optimize (clasp-cleavir::analyze-flow nil))) and then it wouldn't do any type inference or dx or anything.
19:27:51
Bike
the less principled thing to do would just be to comment out dx from my-hir-transformations
19:35:58
drmeister
It will take a little while to shake out the bugs of the typeq-instruction code generation.
22:58:51
Bike
one input. if the input is of the instruction's type, go to one branch. otherwise go to the other
0:00:56
Bike
well, the upshot for us is that profiling is nice. though we have a lot more fires to put out before we can care about this, probably
0:33:21
drmeister
We can get rid of fixnump-instruction, consp-instruction, characterp-instruction and replace them with typeq-instruction.
0:34:41
Bike
well, what i want to do is keep the existing typeq-instruction, and have eliminate-typeq turn it into mir instructions, one of which is a primitive-typeq-instruction
0:35:04
Bike
because like, we want (typeq x (or cons null)) to be like (or (primitive-typeq x cons) (eq x nil)), not a typep call
0:38:28
Bike
might be ok to organize it as having fixnump, consp, characterp, single-float-p, and then have a uh, "headerq" that does the bit starting with let* ((header-check-br
0:40:54
Bike
eliminate-typeq has its type, it checks type-header-value-map, if the type is present it generates a headerq-instruction using the header-value-min-max in the table
0:42:50
Bike
really, for a constant type the only reason we need to call typep is if the type is undefined or it's a class(name), and the latter we can eliminate later
0:45:49
Bike
anyway, that snippet and the variables should be enough for me to figure out the rest myself
0:52:41
drmeister
I dunno - I haven't used it yet. It's part of this function: http://llvm.org/doxygen/classllvm_1_1IRBuilder.html#a3393497feaca1880ab3168ee3db1d7a4
0:53:24
drmeister
I tried to make sure the comparisons are always in the sense where branch-weights mean the same thing.
1:00:10
Bike
so, on this topic, in each running thread there's a top-of-the-shadow-stack variable that holds information about the currently executing lisp function, right?
1:03:10
drmeister
Each mp:process points to a thread-local structure that contains a pointer to the top of the invocation history stack.
1:05:56
drmeister
There will always be something. It's so painful to debug without it - I can't tolerate it.
1:06:22
Bike
statistical profiling is done by just checking where running code is every millisecond or whatever. so, we can just start up a profiler thread that checks the current function in the profiled thread
1:15:18
drmeister
Every Clasp function is like a C++ function. The big issue are anonymous lambda's - they are everywhere.
1:16:04
drmeister
But if you (defun foo (...) ...) in package BAR the function name is something like FN_BAR::FOO
1:24:00
drmeister
Maybe it's used to fingerprint the sample? joker-eph in #llvm told me that they get around the limitation by spawning the compiler in another thread.
1:30:28
drmeister
I'm really annoyed. I installed an older version of nglview according to the nglview instructions and then started developing code to mimic it. I got it working - but only when I ran the python version of the nglview widget first - that loaded the old Javascript code into the browser.
1:31:49
drmeister
So things took longer to get working because more than half the time I was running the Common Lisp code without running the Python version first and it loaded a newer version of the Javascript code that it wasn't designed to talk to properly.
1:35:27
drmeister
Annoyance #2 is now I am rebuilding the docker image with (hopefully) the latest version of everything and then I have to change the Common lisp code to bring it up to talk properly to the latest version of the Javascript.
3:24:00
beach
It is still very early in the morning here, so I may not be very coherent, but I think TYPEQ is meant for the type inferencer, so there is no need for it to handle arbitrary types; only the ones that the type inferencer can deal with.
3:25:34
Bike
okay, say you have (declare (type B var)), where B is a strict supertype of A, which is an inferencer type. and it's safe code. how's that compiled?
3:25:38
beach
Nobody says that a call to TYPEP with a constant type argument or a declaration should turn into a TYPEQ with the same type given.
3:27:01
Bike
i mean, the basic issue is that typeq is for the inferencer, but it also has actual semantics
3:33:03
Bike
say A is fixnum and B is integer = (or fixnum bignum). typep will redundantly test fixnum, unless it expands into typeq(s) itself
3:35:32
Bike
because then the inferencer would have one join/meet set of operations, and then there'd have to be another one at generate-ast level subtracting things out of full common lisp types
3:37:49
beach
It seems to me the alternative, if you want to do things once only, is to avoid type inference and have everything done by TYPEP.
3:40:54
Bike
right now i'm moving forward as if typeq can handle anything, and in the near future generate-ast will convert typeq's type specifier into an environment-independent implementation-defined type object. then probably some phase in hir but before type inference breaks typeqs apart into usable pieces, and then the inferencer simplifies further into inference types.
3:42:10
Bike
but i'm only just getting to the point of avoiding full typep calls anyway, so i'm just thinking ahead and worrying'
3:43:15
beach
I can't parse the phrase starting with "then probably...". But it is probably not important.
3:44:36
Bike
like (if (typeq x list) a b) is turned into (if (typeq x cons) a (if (typeq x null) a b)), so that if there's an earlier (typeq x cons) it can eliminate that part of the test
3:46:07
beach
That is why I don't think any THE or TYPEP or DECLARE should turn into the same TYPEQ.
3:47:11
beach
It seems to me very complicated to let TYPEQ handle everything, only to remove it later.
3:49:29
Bike
right now i'm not doing anything major to rock the boat. probably moving loop invariants will do more good than a lot of this stuff, but that doesn't mean it's irrelevant, i don't think
3:51:02
Bike
...moving code might also be easier with typeq, since it has known semantics, unlike a function call where there have to be annotations introduced or something
3:51:57
beach
The way I see it is that TYPEP needs to exist anyway. TYPEQ can handle a subset, and is used for type inference. I don't see the additional separate facility here, other than type inference, which we need for reasons of performance.
3:52:43
Bike
typeq is used for type inference but it also affects control flow based on types of objects, same as calls to typep
3:53:30
beach
So there is nothing wrong with a combination of TYPEQ and calls to TYPEP. No additional separate facility here.
3:55:49
beach
Yes, the compiler macro for TYPEP can be arbitrarily complex, so that it contains knowledge of what TYPEQ can handle and what it can't.
3:57:29
beach
It is even possible to factor out the code that splits up a type into what TYPEQ can handle and the rest.
3:58:26
beach
This code would be entirely implementation specific, thereby avoiding yet another customization mechanism in Cleavir.
4:01:27
beach
Maybe Cleavir could provide some default that is coupled with what the type inferencer can handle.
4:14:21
Bike
i already have a couple functions like compile-or-typeq, compile-and-typeq, etc. hir level but no big