Live data from Hacker News

What I Learned Making My Own JIT Language

mikedrivendevelopment.com

91–100 of 120 posts

Re: What I Learned Making My Own JIT Language

#91

Earlier quoted context omitted.

You say all this as if JS's jit engines (V8, chakra, spidermokey, etc) did not destroy "better designed" languages when it comes to speed and efficiency. The only dynamic language that does not pale beyond what is achieved with V8 is LuaJIT.

The performance of JS is purely down to absolute compiler genius, which would have given better results and been better applied to a language that was not designed on the back of a napkin. JS does everything in its power to make life hard for the compiler. Outside JS, most compiler work goes into static languages (which I strongly prefer), but once WebAssembly DOM support comes through, better languages will run on V…

> JS does everything in its power to make life hard for the compiler.

This is a bit hyperbole. It could be worse, it could be python. Yes pypy does not have the investment of v8, but there is more to it than that. Yes js sucks but the language was relatively simple enough to get speedups that would not be possible in jitted python because frankly python is a steaming hodge lodge pile of shit when you take the system as whole (imnsho)

Re: What I Learned Making My Own JIT Language

#92
post #59

Earlier quoted context omitted.

> There is no need for the ability to redefine methods on an object In prototype-based languages like JavaScript and Lua redefining methods on an object is common at runtime, which makes them quite challenging to JIT. It may be most common early in execution, but there's no way to semantically define that boundary. Since Lua 5.2 (IIRC) certain metamethods are locked & loaded when you assign a metatable (a prototype d…

> In prototype-based languages like JavaScript and Lua redefining methods on an object is common at runtime, which makes them quite challenging to JIT. It may be most common early in execution, but there's no way to semantically define that boundary. It is common, but I do not think it is at all necessary. It always looks nasty whenever I see it in dynamic languages, and I never feel a need to do so in static languag…

Array languages like APL/K/J can be tremendously fast for an interpreter, since each bytecode works on entire arrays at a time. Not quite as fast as say, C or C++ compiled with a modern compiler, but I think they can match other static languages. And of course, when you're branching on or processing single values rather than whole arrays/matrixes, you lose the speed benefit.

Re: What I Learned Making My Own JIT Language

#93
post #64

Earlier quoted context omitted.

Then you either need to have "redefinition" checks, or an actual, full stop the world, which is also a performance nightmare and also affects unrelated code. The proper solution is to not have unnecessary dynamics. There is no need for the ability to redefine methods on an object. If you have functions as first-class objects, you can just let users store functions and call them at the cost of indirection if they wish…

How about a language that loses the ability to redefine structures and methods after a certain point? I've been thinking of making a scripting language where you can freely redefine things until you return the main function to the script's caller. At that point main gets compiled / JITed / otherwise locked and any redefinitions done by calling it are errors.

That's how RPython works, essentially. https://rpython.readthedocs.io/en/latest/getting-started.htm...

Re: What I Learned Making My Own JIT Language

#94
post #89

Earlier quoted context omitted.

Is it not fair to say that this is the same thing? My impression was that in designing a compiler you're explicitly determining the rules for language, which is the same as designing the language itself? Or do you mean that technically the compiler, not the language, is JIT? This is a new area for me so apologies if I'm just misunderstanding the mechanics here!

In theory the programming language is independent from the implementation. You could write an alternate implementation if you wanted. JIT-ness is a concept related to the implementation, not to the language.

Gotcha, that makes sense. So I'm guessing that java based python vs c based python is an example of theory vs implementation? Thanks for explaining!

Re: What I Learned Making My Own JIT Language

#95
post #64

Earlier quoted context omitted.

Then you either need to have "redefinition" checks, or an actual, full stop the world, which is also a performance nightmare and also affects unrelated code. The proper solution is to not have unnecessary dynamics. There is no need for the ability to redefine methods on an object. If you have functions as first-class objects, you can just let users store functions and call them at the cost of indirection if they wish…

How about a language that loses the ability to redefine structures and methods after a certain point? I've been thinking of making a scripting language where you can freely redefine things until you return the main function to the script's caller. At that point main gets compiled / JITed / otherwise locked and any redefinitions done by calling it are errors.

Sounds like macros.

Re: What I Learned Making My Own JIT Language

#96
post #64

Earlier quoted context omitted.

Then you either need to have "redefinition" checks, or an actual, full stop the world, which is also a performance nightmare and also affects unrelated code. The proper solution is to not have unnecessary dynamics. There is no need for the ability to redefine methods on an object. If you have functions as first-class objects, you can just let users store functions and call them at the cost of indirection if they wish…

How about a language that loses the ability to redefine structures and methods after a certain point? I've been thinking of making a scripting language where you can freely redefine things until you return the main function to the script's caller. At that point main gets compiled / JITed / otherwise locked and any redefinitions done by calling it are errors.

> How about a language that loses the ability to redefine structures and methods after a certain point?

Sounds awesome! We could call the phases before that point "compile time" and "preprocessor time", and the phase after that point "run time".

/sarc

Re: What I Learned Making My Own JIT Language

#97

Earlier quoted context omitted.

I say screw deoptimization checks, and put the burden in the redefinition processing. When you redefine something, you stop the world at safepoints and update prior baked assumptions that are registered on the old definition. These redefinitions usually happen during development and initialization, not during performance-sensitive runtime. It would add more to the memory footprint, but that information is not accesse…

Then you either need to have "redefinition" checks, or an actual, full stop the world, which is also a performance nightmare and also affects unrelated code. The proper solution is to not have unnecessary dynamics. There is no need for the ability to redefine methods on an object. If you have functions as first-class objects, you can just let users store functions and call them at the cost of indirection if they wish…

Generally speaking, the most efficient solution for a problem is the one that can't solve any problems more difficult than the given one.

Re: What I Learned Making My Own JIT Language

#98
post #88

I wish http://terralang.org got more attention. It’s a great way to write a jitting library. Add in LuaPEG and it’s a great way to write a jitting language.

I'm not sure I'd put Terra together with dynamic language JITs. It a low-level statically typed language that is closer to C than to Lua.

Terra itself is static, yes. But, the idea is to use Lua to parse your own language then compose Terra on the fly to execute your language. So, it's a roll-your-own-language foundation rather than a language-specialized JIT.

http://terralang.org/api.html#embedding-new-languages-inside...

Re: What I Learned Making My Own JIT Language

#99
post #89

Earlier quoted context omitted.

In theory the programming language is independent from the implementation. You could write an alternate implementation if you wanted. JIT-ness is a concept related to the implementation, not to the language.

Gotcha, that makes sense. So I'm guessing that java based python vs c based python is an example of theory vs implementation? Thanks for explaining!

Yup

Re: What I Learned Making My Own JIT Language

#100

Sure, there are things that can be "poison pills" for performance, even in JITs. For example, another reason why my fib benchmark beats V8 is that V8 has to continually check if the fib function was redefined as a deoptimization check. I don't allow that in Vaiven, so I can produce faster code. Dart was designed to have fewer of these poison pills, for instance. Note to language designers: Reduce your language's pois…

I say screw deoptimization checks, and put the burden in the redefinition processing. When you redefine something, you stop the world at safepoints and update prior baked assumptions that are registered on the old definition. These redefinitions usually happen during development and initialization, not during performance-sensitive runtime. It would add more to the memory footprint, but that information is not accesse…

This seems nice but it is hard. Imagine the following scenario in a JavaScript where one has lisp like singly linked lists:

  function map(f, list) {
    if (list==null)
      return null;
    return cons(f(head(list)), map(f, tail(list)));
  }
Now as there is a call to map, a JIT compiled version will put in a redefinition check and if the check passes then it can call an optimised map which eg knows it has two arguments and f is a function. If the check fails then a slow path which does a full call is followed.

In your scenario there is no redefinition check and instead when one tries to redefine map, any optimised calls must be downgraded to the slow path.

But now imagine calling map with a function that redefines map after say the third recursive call. Then the redefinition downgrading magic needs to somehow modify one version of map halfway through a call so that when f returns it will call the new map, but the calls further up the stack frame don’t need to be modified as they won’t call map again.

Post reply on HN