7 ms·
*JS : Low-Level JavaScript
- stcredzero 15y agoI'm a bit confused by the "it compiles to JavaScript" part. I would've expected it to compile to C.
- dherman 15y agoThink of it more like C (really more like a hybrid of C and JS) compiling to JS. It runs on the web, but it compiles to a very stylized kind of JS: it allocates a large typed array that represents a C-like heap and does its memory access on that typed array. This is the same basic approach that Emscripten uses for running C/C++ programs. The purpose of this project is to experiment with a dialect of JS that integrates well with regular JS, so you can write performance-sensitive parts of your application in this dialect, and they can interoperate smoothly with the other parts of your normal JS code.
- drivebyacct2 15y agoI was skeptical at first, but I've been writing so much Go lately that the struct syntax, typing and pointers would be lovely to be able to utilize in a web app without having to go so extreme as to use Dart.
- keyle 15y agoI understand low level languages going high level. But high level languages going low makes me frown very intensely. Btw if you like this kind of thing, you will love Caterwaul JS. My best frowning faces are made reading that language. http://spencertipping.com/ http://spencertipping.com/ / http://caterwauljs.org/doc/caterwaul-by-example.pdf http://caterwauljs.org/doc/caterwaul-by-example.pdf
- dherman 15y agoIn practice, most safe languages provide back doors and foreign interfaces to unsafe code. Look at Obj.magic in Ocaml, or unsafePerformIO in haskell, or ffi/unsafe in Racket. But on the web, you obviously can't tolerate true unsafe back doors. This project gives you something that is "unsafe" in that you can read or write to parts of the allocated "heap" buffer that you aren't supposed to, but it's not possible for that to violate JavaScript's safety. And the compiler is generating extremely optimizable code, so it JITs very, very well. On top of that, the fact that it's all implemented on top of a simple API (typed arrays) means that you could compile in a safe mode that does extra checks, or even trap all memory traffic and build valgrind-like diagnostic tools. It's starting out as a virtualized abstract machine, which means it's easy to hook into and provide great development tools. I probably wouldn't reach for this kind of dialect for most purposes. But for very performance-sensitive kernels, it's got promise. But it's an experiment, so we'll see!
- hermanhermitage 15y agoDave, is there any way to get involved? There would always be the option of running the code out into a raw VM host using NaCL or Xax style container (I know Mozilla dont see these approaches as necessarily compatible with the open web). But to take an approach like boot to gecko to the next level and being compatible with low power usage, I dream of running near native code - inline SSE/Neon with a fallback to generic code.
- dherman 15y agoSure! Right now there's just Michael's GitHub repo (this is literally only a few weeks old) but I've created an IRC channel -- join us at #lljs on irc.mozilla.org. You may have better luck getting attention during the work week, though. ;-)
- mbebenita 15y agoWhy not extend the typed array API to include SIMD operations on multiple array elements, we can compile to use those and special case them in the JIT.
- hermanhermitage 15y agoMakes perfect sense. I'm also thinking how the vm/language could self extend in the field. How the SIMD extensions (or any feature) could be introduced a-posteriori or independent from browser release cycle.
- jhrobert 15y agoPerformance matters. An efficient JavaScript dialect is very much needed indeed. Another solution would be to include a C compiler in every browser, with some DOM thing binding and a convenient JavaScript bridge. It will be interesting to see what optimizing interpretors can get, performance wise, when source code uses "performance friendly" features only.
- voidr 15y agoIt's not that bad actually, the only thing JavaScript needs actually is a real array object in the standard.
- ilaksh 15y agoSerious question. Do you browse the web with Internet Explorer? V8 and the new Mozilla engine are optimized to hell already. And they compile to native code. http://kailaspatil.blogspot.com/2011/08/jaegermonkey-architecture.html http://kailaspatil.blogspot.com/2011/08/jaegermonkey-archite... And they are efficient.. These engines have proven that you don't need pointers or explicit types to be an efficient Javascript implementation. The only reason that I can see for these types of features like explicit types and pointers are to support systems programming, where they are required for certain activities (probably less that you would think though). For that, I would really love to see a CoffeeScript with those features available for use optionally. I think to do that you would want to find a way to compile directly to machine code or assembly or LLVM bytecode or something like that.
- davux 15y agoI think it's safe to say that if you're browsing HN with IE, you are using 9 or 10, which have very fast Javascript engines.
- hermanhermitage 15y agoThere is still a lot of performance slippage out there in high level languages (eg look at the need for assembly when people write raw codecs in C - x264 etc). We are rapidly approaching the battery wall on mobile devices and the clock wall is already here. ISA's may be extended to support dynamic languages more efficiently (tags, direct uop translation from user specified instructions) - but right now at a given TDP static execution is greener for many applications than dynamic, and history has shown us cpu vendors are unwilling to go down this path. Javascript is anything but efficient right now - some code paths are fast but with a high startup cost. Look at the startup problem with Chrome/V8 for instance, or watch a nodejs application hit the GC wall with 800MB of live data. There are times when static is faster than dynamic and vice-versa. Times when heavy upfront compilation is better than incremental run time analysis and vice-versa. As the clock wall, TDP wall and process communication wall hits we need all the tools available to exploit maximum performance.
- geoffschmidt 15y agoWhy does malloc take a byte count, just to divide it by sizeof(u32)? Why not embrace the fact that natural "word" in the JavaScript VM is a boxed value that stores an int, float, or string, and define sizeof(u8) === sizeof(u16) === sizeof(u32) === 1? Unless you really want each cell in your memory arena to literally emulate a byte and always store a value between 0 and 255? In a similar vein, why not use the native JavaScript object type to back the structs? This will cooperate nicely with the inline caching in typical JavaScript JITs. The result will be native assembler that indexes directly into the structs in the way you'd hope, since your static typing system forces every object reference to be monomorphic. Does this language actually eliminate GC pauses? Isn't the GC still going to run, except now it has to walk every single cell in your memory arena every time, defeating the very heuristics that GCs use to reduce pauses? There's definitely something alluring about the static typing, but I'm less sold on the manual memory management. Maybe there is a way that the language could help you generate less garbage, without actually requiring you to manually control the lifetime of each object? From your linked-list example, it's eminently clear that it needs a C++-style template system and a port of the STL :) If you wrote a C-to-*JS translator, you could hypothetically use a pre-existing cfront (C++-to-C translator) and STL implementation to get that working.
- azakai 15y ago> Does this language actually eliminate GC pauses? Isn't the GC still going to run, except now it has to walk every single cell in your memory arena every time, defeating the very heuristics that GCs use to reduce pauses? Yes, this eliminates GC pauses. The JS GC will only run if allocations occur, allocations in the sense of actual JS objects. If you do malloc which amounts to manually handling indexes in a single array, no JS objects are created and destroyed. Also, JS GC's would not walk the memory arena. The memory arena is just an array of numbers, it does not contain native JS references which is what the JS GC traces.
- geoffschmidt 15y agoI meant the synthetic memory arena, the JS array that malloc() and free() manage. That certainly could contain JS references and needs to be examined by the GC. I don't think you can actually avoid GC by avoiding JS object allocations. Any form of string manipulation, any form of IO (event handling, DOM manipulation, XHR), any use of timers, etc, is going to allocate objects, right? Also, the JS runtime could generate garbage internally. For example, since JS has closures, it wouldn't be totally unreasonable for the runtime to manage the lifetime of activation records (JS stack frames) using the GC.
- hermanhermitage 15y agoI like to see this line of work. I'd really love to see a Frankenstein of: * C/Javascript/Lisp on an augmented LuaJit (structs, efficient array slices, machine word types). * dual syntax interchangable S-EXPR and C{}. * lang(machine) { instr over machine } blocks. Where machine is either a syntactic transformation or a way of hosting binary code in another language and interchanging objects. * raw continuations and stack management. * explicit and implicit memory management. * language profiles to allow assert() and compilation failures based on feature set used to allow different restricted forms of the language to be used according to the position in the software stack the code is targeting (embedded, client, server, enterprise boilerplate). eg. profile(no-gc, no-lang, must-types) * full ability to specify code to execute and participate at: edit/view, compile (pre-process, parse, code-gen etc), link, load and runtime (debugging, re-jit, trace analysis).
- petegrif 15y agoThis is interesting - who is doing this? and where?
- dherman 15y agoThis is a project run by Michael Bebenita at Mozilla Research, along with our colleague Shu-Yu Guo.
- phamilton 15y agoAs a C programmer I like the concept but debugging is going to be a nightmare. Look at how pointers translate to Javascript. I don't foresee being able to debug anything with code like that in Chrome Developer Tools.
- sounds 15y agoThe code is still very young (less than a month old). Debugging in C is done by printing hex values and using valgrind, so debugging here can be done by printing hex values (array indexes in the heap or stack) and creating a valgrind that runs at about the same speed as a non-valgrind session, since valgrind can be implemented in the js engine.
- mbebenita 15y agoActually, you could build something like Valgrind quite easily. You can replace the underlying heap with a JS proxy and trap all read/writes, it would be a fun project.
- ErikD 15y agoOnce Chrome and *JS support SourceMap it shouldn't be that hard to debug.
- psykotic 15y agoCool! For a while I've been pondering a similar idea with the goal of cross-compiling the language to idiomatic C and JavaScript. The JavaScript translation would necessarily be less than perfectly idiomatic, but it would be more idiomatic and have better performance and smaller size than the code generated by Emscripten. The intent was to use it for high-performance applications like games.
- dysoco 15y agoI love how they name languages like *JS or C! so I can't google them later.
- mbebenita 15y agoWell, the * was supposed to be a pointer. JS is dereferencing JS, so JS would be more appropriate since it implies static typing and pointers, but it sounds awkward when you say it, so we went with *JS for now.
- dherman 15y agoJust a temporary name. We're tossing around name ideas. Michael's a true hacker. He writes code first, asks questions later. I'm more useless, so I like to think about names. ;-)
- doubleconfess 15y agoI'm going to throw 'J--' into the suggestion box. :-)
- olliesaunders 15y agoPlease don’t. Googleable names only please.
- gbog 15y agoJscape?
- yuchi 15y agoEcmalang?
- FuzzyDunlop 15y agoSince the IRC channel is called 'lljs', then 'low level javascript' is a fairly functional - if not totally imaginative - name. On a more bizarre level, use the same logic as coffeescript (java - coffee), and get something like 'C-matra' (Sumatra being another Indonesian isle, like Java).
- pixie_ 15y agoCool. Does anyone else write their code with the * after the type, instead of before the variable? Like int* x; as opposed to int * x; to me int* is the type of x, so keeping it together makes sense. Like a function returning an int pointer would be - int* myfunction(); or type casting something (int* ). Putting the * before the variable and not as part of the type just seems unintuitive. Anyone else agree/disagree? edit: another point - putting * before the variable makes me think of a dereferencing operation, and that's part of why putting it before the variable name in declaration is unintuitive, and very confusing to people learning C.
- james4k 15y agoThe emphasis with 'int *x' is that the variable is no longer really a variable anymore. It is a pointer to your variable. It doesn't really have anything to do with the type.
- pixie_ 15y agoYes it is still a variable, a variable of type int* , not int. Which can be returned by a function that returns type int* or type casted int* . Variables of type int are assigned numbers, while variables of type int* are assigned memory addresses.
- mbebenita 15y agoI totally agree, but it just sounds weird when you say it, JS* vs. *JS.
- pixie_ 15y agoI have no problem with the name, just wanted to bring up the issue with other programmers. How is it pronounced anyways? starJS, pointerJS, astrickJS?
- modeless 15y agoYes, it is unintuitive. However, there's a reason people do it the unintuitive way, and that's due to the C spec. float* foo, bar; This code declares bar as a float, not a pointer! To make things less misleading, most C programmers have adopted the convention of putting the star next to the variable name instead of the type: float *foo, bar; even though it looks weird.
- aphexairlines 15y agoHas Typed Scheme shown that this approach yields significant performance gains or do js typed arrays not have a scheme counterpart?
- bsaul 15y agoNot really into high speed javascript, but wouldn't you be able to achieve the same kind of memory reuse by simply using factory methods patterns that would reuse object instance from a pool instead of reallocating ? It's the same kind of tricks we use in ios / android programming when we want to avoid memory allocation or garbage collections...
- VMG 15y agoUsing the pattern you describe you could only reuse the same kinds of objects. With a general heap you could reuse the memory for arbitrary structures.
- IsaacSchlueter 15y agoI have a problem with this line: Objects in JavaScript are not cheap, they need to carry around lots of extra information and can be many times larger than their C style counterparts, moreover property access is slow. It's easy to say "X is not cheap, Y is slow". It's much more valuable to actually prove it with numbers that show where it's fast and where it's slow. In my experience, object creation and property access is almost never the bottleneck, and GC pauses only are relevant (in v8 at least) if you're leaking a large number of objects, especially where those objects are of mixed generations. (Ie, have a lot of long-lived and short-lived objects that refer to one another and occasionally leak.) That is, if you are getting hit with long GC pauses, then it's worth re-thinking your design and tracking down objects that may be leaking. Newer JS engines (ie, the ones that implement TypedArrays) already highly optimize object creation and property access. The benefit therefor seems slim and highly niche. Looking at the generated code, it seems like the debugging cost is going to be very high, and it drastically increases the number of lines that the programmer has to write, which will increase bugs. I could see the value in certain niche situations, but I would really like to see the performance characteristics explored more fully.
- dherman 15y agoIt's easy to say "X is not cheap, Y is slow". Yeah, I probably wouldn't have worded it that way. I think the better way to look at it is, it's hard to know how to predict the performance of JavaScript, given the complex, dynamic, heuristic optimizations performed by modern engines. This project is better thought of as an attempt to build a dialect of JS that can be more easily tuned for performance, because its performance model is simpler than that of JS. If I were going to try to make that claim more precise, I might do some experiments to demonstrate the high variance of object performance in modern JS engines. I could see the value in certain niche situations... That's really the idea. This isn't meant to be an alternative to JS, but rather a tool for performance-sensitive kernels. Interoperability will therefore be key, because it has to be easy to write just a small component of a larger app in this dialect while smoothly integrating into the rest of the app. ...but I would really like to see the performance characteristics explored more fully. Perhaps. I'm skeptical of our ability to accurately measure general claims like "objects are slow" or "X is easier to program in than Y" or "*JS is easier to performance tune than JS." But I do think it's easier to evaluate those claims, at least informally, after you've built something you can experiment with. Hence this experiment!
- wowoc 15y agoIf it ever gets popular, it will happen _despite_ its name. Googgling it would be a flicking nightmare. Or change the name now, before it spreads.