sillycross
> "there’s only so much one can do without touching the data model"
You probably want to look at the other link in that PR, which demonstrated how well copy-and-patch can do for another dynamic language (Lua): [1]
Of course, whether or not CPython could eventually make it to that point (or even further) is a different story: they are under a way tighter constraint than just developing something for academia. But copy-and-patch can do a lot even for dynamic languages :)
If LuaJIT interpreter were to employ IC, it would have to undergo a major rewrite (due to its assembly nature) to have the equally efficient code as LJR (that we generate automatically). This is one advantage of our meta-compiler approach.
Finally, although no experiment is made, my subjective opinion is already in the article:
> LuaJIT’s hand-written assembly interpreter is highly optimized already. Our interpreter generated by Deegen is also highly optimized, and in many cases, slightly better-optimized than LuaJIT. However, the gain from those low-level optimizations are simply not enough to beat LuaJIT by a significant margin, especially on a modern CPU with very good instruction-level parallelism, where having a few more instructions, a few longer instructions, or even a few more L1-hitting loads have negligible impact on performance. The support of inline caching is one of the most important high-level optimizations we employed that contributes to our performance advantage over LuaJIT.
That is, if you compare the assembly between LJR and LuaJIT interpreter, I believe LJR's assembly is slightly better (though I would anticipate only marginal performance difference). But that's also because we employed a different boxing scheme (again...). If you force LJR to use LuaJIT's boxing scheme, I guess the assembly code would also be similar since LJR's hand-written assembly is already optimal or at least very close to optimal.
However, I'm not sure if doing so is useful or necessary. Interpreter performance is sensitive to code layout (which affects hardware branch predictor accuracy), but I don't think there is a general way to optimize the code layout to make the branch predictor as happy as possible.
So if you changed your code alignment and saw a perf change, it's more likely caused by the random perf gain/loss due to code layout change, not because that 1-byte-alignment is better than 16-byte-alignment or vice versa.
[1] https://easyperf.net/blog/2018/01/25/Code_alignment_options_...
As explained in the article, LLVM already has the calling convention you are exactly looking for: the GHC convention (cc 10). You can use it to "pin" registers by passing arguments at the right spot. If you pin your argument in a callee-saved register of the C calling conv, it won't get clobbered after you do a C call.
I think the point you missed is: the function 'cellContainsLiveObject' is not used by GC, it is used by allocator to tell if the cell is available for allocation. So it's fine if the function returns true but the object is actually unreachable, but not the other way around.
I am in full support with this, though it seems to me this is too idealized to be practical in practice. How can one reach a fair judgement of a student only based on a 1000-word essay in his/her application (which might not even be written by him/herself)?
However, I'm still saddened by that the MIT response to this incident is simply "it is Abbot's right of free expression to say whatever he wants", but nothing about what he actually said, or whether it at least makes some sense. It's as if MIT treated Abbot as an unknowing child whose nonsense words shall be tolerated, which is disturbing. Below is part of the mail list letter I received:
> Freedom of expression is a fundamental value of the Institute.
> I believe that, as an institution of higher learning, we must ensure that different points of view – even views that some or all of us may reject – are allowed to be heard and debated at MIT. Open dialogue is how we make each other wiser and smarter.
> This commitment to free expression can carry a human cost. The speech of those we strongly disagree with can anger us. It can disgust us. It can even make members of our own community feel unwelcome and illegitimate on our campus or in their field of study.
> I am convinced that, as an institution, we must be prepared to endure such painful outcomes as the price of protecting free expression – the principle is that important.
It's actually an interesting example where undefined behavior allowed compiler optimization:
(1) dereferencing an invalid pointer is UD
(2) signed integer overflow is UD.
This allows the compiler to assume that the program never crashes and the counter never overflows. The loop is then optimized out knowing that it is read-only thus has no side-effects.
I never thought before that ISPs would really keep track of every user's browsing history, but apparently as cheap as the disks are today, this has become true. Can't think of any use of this data other than for mass surveillance.
> The emulator would identify hot code blocks, generate C like constructs (or ideally the AST)
The idea behind copy-and-patch should be able to handle your use case of quickly translating code blocks in another ISA to native instructions.
However, I think Pochi's metaprogramming capabilities might not be too relevant here. After all, you are translating from a block of CPU instructions (in another ISA). It's probably not necessary or helpful to translate them back to C-like control flow only to compile them again.
> The ability to call back to host methods, handle exception semantics and all the while being totally oblivious to the platform
I'm not sure what you mean here. Yes Pochi supports intuitive inter-operation with the host program (call methods, handle exception etc). This is important for metaprogramming use case (e.g., generating a program that executes a SQL query), but I don't see what it has to do with emulating a program in another architecture.
Probably reasonable if R<1 since it's only going to affect a limited number of people, but this is absurd for countries where the R is still >1. This is effectively putting everyone at life risk.
> which do JIT "compilation" in the business-logic/abstract sense of the term?
If I understood what you said correctly, you mean translating something to SQL?
The problem this paper is trying to solve is how we can generate binary code fast. If your target (i.e. the stuff you want to generate in the end) is not binary code, but some high level representation like a SQL text, then I think it doesn't have much to do with the technique in our paper.
The interesting part is the various improvements to this old idea that allows us to both compile fast and generate good code.
Would be interested to see a performance comparison with V8 JIT (instead of V8 interpreter).
The paper is very long and mostly math so I only skimmed it. It seems to me (as a practitioner) the key insight to alleviate primary clustering effects is the following:
At high loads, when you rebuild the hash table, you put k/2 "fake tombstones" evenly across the table, where k is the # of free slots in the table. This way, when one performs an insertion, the iteration length is going to be short (thanks to the evenly spreaded tombstone), thus alleviating the primary clustering effects.
I'm very interested in seeing some empirical numbers for graveyard hashing in both RAM and external storage use case.
Copy-and-Patch: Fast JIT Compilation for SQL, WebAssembly, and Others
You may also be interested by MS Edge's decision to abandon their ChakraCore engine, which is similar to what I reasoned above [1]
[1] https://blogs.windows.com/windowsexperience/2018/12/06/micro...
Yeah that's the point.
I would say, instead of blaming Trump for punching a hole in the cornerstone of democracy, it just demonstrated how fragile the system already is. So many people are already eagerly ready to do that to win. Trump only dog-whistled them by doing so as president.
I initially thought this is easily fixable (for example, by always request full power), but then I realized it isn't, since the extra power would then have to be dissipated as heat, which is a bad cellphone UX as well.
So if we already have a working tool, why do we want to spend the redundant work to invent more tools that solves the same problem, or to maintain the other tools so they are all standard-compliant?
Of course, it's a different story if the existing tool is monopolized by a commercial company. But Chrome is open sourced, and there is a committee steering the future Web standards.
So imo we don't need another Chrome, just like we don't need another Linux.
Understanding a static analysis pass in JavaScriptCore JIT
In fact, when I first started using LLVM, I created a basic block and put everything into it. Then LLVM complains, and I learnt that a basic block must be a list of straight-lined operations followed by a branch. At that moment I was feeling similar to the author in this post: "Why is there such a bizzare rule that makes me harder to write my program?" But after I was forced to rewrite my code to conform with this rule, surprisingly, I found my program logic much easier to understand. And when I gradually knew a bit more about LLVM, I understood that the basic block rule is there for other very good reasons as well.
So is this good design? Clearly it is. This design decision not only helps with the library itself, but also forces the users to write code in a less error-prone way.
However, is it possible to justify this in the document, so another user won't have to go through my initial frustration? I am doubtful. At least my personal feeling is that, I won't be able to understand why it is designed this way, unless I actually have played around and experienced it myself.
I hope this clarifies my point on why sometimes it is hard to communicate design philosophies.