Conversation
| { | ||
| if(callNodes.containsKey(pc)) | ||
| { | ||
| return callNodes.get(pc).execute(frame, primitives, refs); |
There was a problem hiding this comment.
-
this must be a constant expression from the point of view of Truffle partial evaluation, i.e., simply computable from
finaland@CompilationFinalfields (note: allfinalfields are implicitly@CompilationFinal) and other partial evaluation constants (e.g.,pc). For now you can use just sparse array indexed withpc, maybe it can be optimized to some compact representation later on. JDK's collections and most of the JDK classes in general are usually not suitable for partial evaluation (exception: strings, but notStringBuilder/Buffer). -
all nodes must be stored in
@Childor@Childrenannotated fields and unless you initialize them in the constructor, you must notify Truffle when you change them:mychildField = insert(new MyNode()).@Child(ren)annotation is implicitly@CompilationFinal. -
you should use
DirectCallNodeconstructed usingTruffle.getRuntime().createDirectCallNode(). These nodes are known by Truffle and mark invocation of some other method, i.e., anotherRootNode. This allows Truffle to do method inlining. -
the pattern to lazy initialization of a node is:
if (node == null) {
CompilerDirectives.transferToInterepreterAndInvalidate(); // because we are about to change something that is compilation final
this.node = insert(new MyNode())
}
// ... work with node
from 4-5x times slower than dotnet to 1.75-2x
* foreign method calls with dependent assembly loading * ManagedReferences * Table loading now actually compliant with big tables
* long[] instead of byte[] accessed with unsafe * temporarily deleted narrowing and widening to find raw performance issues
* pop opcode support * function call fix
BACILHelpers + BACILConsoleType + BACILConsoleWriteMethod = stdout
Creating a bogus 0-element array is better optimized than possibly having null pointers
This allows caching of type for BOX (type lookup should never be on compiled path) and caching of the string value for LDSTR.
|
|
||
| While writing an interpreter for even a fairly complicated language is achievable for a single person interested in the topic, state-of-the-art optimizing compilers are usually created over several years by large teams of developers at the largest IT companies. Not only was kickstarting such a project unthinkable for an individual but even introducing changes to an already existing project is far from simple. | ||
|
|
||
| For example, Google's state-of-the-art JavaScript engine V8 currently has two different JIT compilers and its own internal bytecode. An experiment of adding a single new bytecode instruction to the project can mean several days of just orientating in the codebase. |
There was a problem hiding this comment.
minor: místo currently bych používal všude "as of 2022" nebo podobné
There was a problem hiding this comment.
a/nebo citace by byla pekna, oponenti maji radi citace
|
|
||
| For example, Google's state-of-the-art JavaScript engine V8 currently has two different JIT compilers and its own internal bytecode. An experiment of adding a single new bytecode instruction to the project can mean several days of just orientating in the codebase. | ||
|
|
||
| As cybersecurity becomes a more important topic, another factor to consider is that creating manual optimizations in JITs is very prone to bugs which can have very grave security implications. Speculated assumptions of JIT compilers introduced whole new bug families including "type confusion". Implementing a JIT that is not only performant but also secure is proving to be difficult even for state-of-the-art projects. |
There was a problem hiding this comment.
Na tohle by taky mohla byt nejaka hezka citace
| To implement a high-performance CLI runtime, we alleviate the | ||
| [Truffle language implementation framework](https://www.graalvm.org/graalvm-as-a-platform/language-implementation-framework/) (henceforth "Truffle") and the [GraalVM Compiler](https://www.graalvm.org/22.1/docs/introduction). These two components are tightly coupled together and we'll mostly be referring to them that way. | ||
|
|
||
| The Graal Compiler is a general high-performance just-in-time compiler for Java bytecode that is itself written in Java. It is state-of-the-art when it comes to optimization algorithms - according to official documentation, "the compiler in GraalVM Enterprise includes 62 optimization phases, of which 27 are patented". |
|
|
||
| Also, it is often useful to make sure some exceptional code paths are never included in the compilation - for example, if dividing by zero should result in an immediate crash of the application with a message being printed out, there is no use in spending time compiling and optimizing the error-message printing code, as it will at max be called once. | ||
|
|
||
| For that, Truffle uses guards - statements that when reached by the runtime result in de-optimization. De-optimization is a process of transferring evaluation from the compiled variant of the method back to the interpreter (at the precise point where it was interrupted) and throwing away the already compiled variant, as its assumptions no longer hold. |
There was a problem hiding this comment.
Timto jsou myslene guards v Graal IR? V Tuffle DSL, ktery jsi, myslim, nepouzil, je take koncept guardu a je to trochu neco jineho. Nevim, jestli to neni matouci.
|
|
||
| The Graal Compiler is a general high-performance just-in-time compiler for Java bytecode that is itself written in Java. It is state-of-the-art when it comes to optimization algorithms - according to official documentation, "the compiler in GraalVM Enterprise includes 62 optimization phases, of which 27 are patented". | ||
|
|
||
| Truffle on the other hand is a framework for implementing languages that will run on Graal. From the outside, it behaves like a compiler: its job is to take guest language code and convert it to the VM's language. Unlike a hand-crafted compiler, Truffle takes an interpreter of the guest language as its input and uses [Partial evaluation](#partial-evaluation) to do the compilation, performing a so-called "first Futamura projection". |
There was a problem hiding this comment.
will be compiled by Graal? or will run on GraalVM? Nekdy se rozlisuje Truffle framework nebo API (implementacni framework pro autory interpretru) a Truffle compiler == Graal compiler + compiler pluginy pro partial evaluation, ktere rozumneji tomu Truffle API
|
|
||
| As long as the virtual call is effectively static at runtime, we only spend time compiling the actual target function (which can be specialized for the environment) and during invocation only pay the price of a simple equality check. | ||
|
|
||
| Once the comparison fails, this version of the compiled method is thrown away, and a generic one is created: |
There was a problem hiding this comment.
Mozna by se hodilo vysvetlit v cem je to lepsi nez:
if (obj.type == expectedType) return cache.call();
// else no deopt
return obj.Type.ResolveVirtualFunc(method).call();
takhle delal .NET profile-guided optimalizace posledne, kdyz jsem se na to dival, protoze jeste neumeli deopt, ale umeli tiered kompilaci
| return vars[a] | ||
| ``` | ||
|
|
||
| The original control flow of the method was reconstructed from flat bytecode just by unrolling the interpreter loop and merging the instances having the same bytecode offset. |
There was a problem hiding this comment.
Neni mi to ted jasne: "was reconstructed from flat bytecode just by unrolling the interpreter loop" -- jakoze jsme si to ted rucne udelali, abychom pak chapali, co dela Graal/Truffle compiler? Nebo was reconstructed by Truffle compiler? V tom pripade by tu mohl byt skec toho interpreter loopu?
|
|
||
| ### Design goals | ||
|
|
||
| Before we started designing and implementing the parser, we considered what additional constraints have to be put on a parser in order for it to be partial-evaluation friendly. For partial-evaluation friendliness, the key metric is how trivial can every piece of code (that can be called a hot path) be partially evaluated to. While our goal was for the parser to never be called on a hot path, for some possible scenarios including reflection it would be necessary. |
There was a problem hiding this comment.
"hot path" se bezne mezi Truffle vyvojari pouziva, presnejsi je asi neco jako "included in partial evaluation" nebo tak podobne. Mozna bys mohl nekde na zacatku definovat, co pro nas bude znamenat "hot path". IMO performance parseru je taky dulezita, coz je jedna z vyhod tve prace oproti te praci z Lince, a tak i v parseru budou nejake "hot paths" v urcitem slova smyslu
There was a problem hiding this comment.
Premyslim, jestli to nejak nedostat do problem statementu, protoze v jistem smyslu to byl tvuj goal udelat tohle lip nez to mel ten clovek z Lince. Objektivne vzato, pokud by bylo cilem jen udelat rychly interpreter, pak zkraceni cesty k tomuto cili pres zjenoduseni parsovani by mohlo byt validni. Dalsi hezka vec je, ze mas i language launcher podle Truffle "best practices", treba by se to taky dalo prodat i s tim
…ust to get 7 more successful tests ValueTypes are unrolled (flattened) to their respective LocationsHolder. On evaluation stack they exist as plain LocationHolders. Most changes are caused by the fact that LocationDescriptor has to remember offsets to both the primitives and refs arrays to fully mark a beginning of ValueType. A GetHashCode internalcall had to be implemented for them.
Required to generate the instanceFieldsDescriptor
Apart from abstract and conclusion the thesis should be content-complete!
Finally added a link to the thesis
No description provided.