Live data from Hacker News

What I Learned Making My Own JIT Language

mikedrivendevelopment.com

31–40 of 120 posts

Re: What I Learned Making My Own JIT Language

#31

Earlier quoted context omitted.

> I think "unknown type at compile time" and "JIT-able constructs" are opposites. Not opposites exactly. Types enforce a phase separation between compile time and runtime, but there's no reason you can't have a compilation phase at runtime too. This leads to staged programming, like MetaOCaml.

Well, to phrase it simply, in my mind a dynamic type is not a very JIT-able construct. I suppose it comes down to what people consider "very JIT-able", but I don't consider the same code possibly JIT'ing in separate ways in the same execution as very JIT-able.

It depends what you mean by "dynamic type". Since we're talking about some hypothetical dynamic language which is JIT-friendly, "dynamic type" could mean a "staged type" of some kind.

It's kind of like how some static languages use code generation, say, based on a database schema, which is then compiled, except this would happen at runtime. It would have to let you programmatically guide this process dynamically, but the result is very close in performance to a statically compiled language.

Re: What I Learned Making My Own JIT Language

#32
post #9

Earlier quoted context omitted.

Is there a list of common language poison pills? I'd like to learn more.

Well, I can't do a full list, but: Memory non-locality. On modern systems, thrashing through RAM just kills you on performance. I don't know that you have to hand full control over to the programmer, but if you're randomly flinging values on the heap everywhere (a.k.a. "hash tables"), you're gonna hit a wall long before you get to "C performance". For JITs, any time the JIT has the ability to make an assumption, but…

I'd like to add: Don't define your array as nothing but a hashmap with strings as array indexes, with two assignment hooks: One that on assignment updates that sets length = max(length, ToUint32(assigned key)), and one on "length" assignment that iterates over all keys in the hashmap, and for those that can be parsed as uint32's, delete those that have a numerical value larger than the value assigned to length.

That is how JavaScript "Array" objects work. Array indexes are coerced to a strings, as they are for all objects.

For the curious, here is full definition from ECMA-262 1st edition, which describe what browsers currently implement (https://www.ecma-international.org/publications/files/ECMA-S..., page 65):

Array objects give special treatment to a certain class of property names. A property name P (in the form of a string value) is an array index if and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal to 232−1. Every Array object has a length property whose value is always an integer with positive sign and less than 232. It is always the case that the length property is numerically greater than the name of every property whose name is an array index; whenever a property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant. Specifically, whenever a property is added whose name is an array index, the length property is changed, if necessary, to be one more than the numeric value of that array index; and whenever the length property is changed, every property whose name is an array index whose value is not smaller than the new length is automatically deleted. This constraint applies only to properties of the Array object itself and is unaffected by length or array index properties that may be inherited from its prototype.

Re: What I Learned Making My Own JIT Language

#33

Earlier quoted context omitted.

Well, to phrase it simply, in my mind a dynamic type is not a very JIT-able construct. I suppose it comes down to what people consider "very JIT-able", but I don't consider the same code possibly JIT'ing in separate ways in the same execution as very JIT-able.

It depends what you mean by "dynamic type". Since we're talking about some hypothetical dynamic language which is JIT-friendly, "dynamic type" could mean a "staged type" of some kind. It's kind of like how some static languages use code generation, say, based on a database schema, which is then compiled, except this would happen at runtime. It would have to let you programmatically guide this process dynamically, but…

I mean it in the most traditional sense of the term, a type that nothing can be assumed about it until runtime (especially since GGP mentioned Ruby or Python, type hints notwithstanding). The more you can determine before execution, of course the more you can help your JIT/compiler and it becomes less dynamic. Code generation, macros, type providers, etc do not affect the language's type-dynamicness IMO.

Re: What I Learned Making My Own JIT Language

#34

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 accessed at all except during recompilation.

Re: What I Learned Making My Own JIT Language

#36

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…

Is there a list of common language poison pills? I'd like to learn more.

a JIT is one! time is wasted doing compiling while running, the compiler has strict time constraints so can't do as many optimizations, claims about theoretical benefits from runtime data collection and-recompilation for optimization are rarely reazlied in the actual world and profile guided optimizations can achieve similar things for AOT compiled programs. soooooooooooo

AOT master race

Re: What I Learned Making My Own JIT Language

#37

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…

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 to have such dynamics.

Re: What I Learned Making My Own JIT Language

#38

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…

Is there a list of common language poison pills? I'd like to learn more.

Mike Pall of LuaJIT fame opined on that on the luajit mailing list a few years back. Can't find the discussion right now, but only https://news.ycombinator.com/item?id=8605225 which is somewhat relevant.

Re: What I Learned Making My Own JIT Language

#39

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…

Most of the poison pills are someone else's convenience features, sadly.

Re: What I Learned Making My Own JIT Language

#40
post #13

Earlier quoted context omitted.

Isn't there some kind of static analysis possible for such cases?

JavaScript is too dynamic for such analysis. JavaScript at its core is not a very well designed language, and it's a bloody miracle that a JIT can make it usable. If you're designing a new language, don't make everything (even arrays!) a hashmap.

[1]In clojure the array type is basically a hashmap to enable high perf/low memory immutability.

So I would say "Yes[1]" ^^

Post reply on HN