<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Jan 11, 2014 at 7:34 PM,  <span dir="ltr"><<a href="mailto:fixplzsecrets@gmail.com" target="_blank">fixplzsecrets@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br>
I want to propose an idea and get feedback on viability of this or some related addition to the language.<br>
<br>
ES should have a way to build functions at runtime - like the approach of building a string of code and using Function(code) - but using API calls to assemble the code. Special support for this from language implementations would allow programs that depend on dynamic evaluation of large blocks of code to execute with less latency - bypassing the cost of concatenating a large string and then requesting the runtime to parse it character by character as with the use of Function().<br>
</blockquote><div><br></div><div>Can you provide some measurements where concatenating a string and parsing it is a bottleneck?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<br>
Here is my naive guess at what the API should look like:<br>
<br>
    func  = CompiledFunction.create()<br>
    arg0  = func.arg(0)<br>
    val   = func.get(arg0)<br>
    val2  = func.op('*', val, func.literal(2))<br>
    func.return(val2)<br>
    result = func.done()<br>
<br>
This builds "function(a){ return a * 2 }"<br>
<br>
As you can see, this API provides a LLVM-like language.<br></blockquote><div><br></div><div>LLVM-dev here. Other than this being an IR, I don't see any resemblance to LLVM at all.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<br>
There would be more methods: "get", "set" for reading and writing variables and fields, "call" for function calls, "startIfElse" for writing if/else blocks, "startFor", "startWhile" for loops, "break", "continue", and others for every possible construct.<br>
</blockquote><div><br></div><div>This is nothing like LLVM at all (not SSA).</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<br>
It is important that runtime implementations support these operations with low overhead. Ideally it should be a nearly direct means of writing to the intermediate representation format of the runtime.<br>
<br>
<br>
Motivation:<br>
There are a few types of programs that use generated Javascript in browsers:<br>
<br>
- PEG.js<br>
PEG.js is a library for facilitating parsing of custom text formats. It works by converting a parser notation to Javascript code that performs the specified parsing rules.<br>
Ability to use custom data formats is a piece of Unix philosophy that it seems should be supported on the Web. As is PEG.js has to depend on the Function() quirk, which may not work if content security policy is enabled.<br>

<br>
- Opal <a href="http://opalrb.org/try/" target="_blank">http://opalrb.org/try/</a> &c<br>
Opal aims to implement Ruby running in Javascript environments. It is among other projects with similar aims for different languages operating in different ways.<br>
If special support for this API is available, web applications depending on tools like this could deliver their code and initialize with lower latency.<br>
<br>
- Asm.js<br>
Asm.js is a special format of Javascript suitable for representing native executable code. However, one complaint concerning it is that it is not a suitable lexical representation of the content it encodes - Asm.js programs are larger than equivalent native executables, and parsing time is proportional to this size because content has to be scanned character by character and code size in present experiments can exceed 10 megabytes or more, and parsing can be inefficient unless the runtime implementation includes a specialized parser for this format. Because of this, I have seen criticism suggesting that proponents of Asm.js should design a bytecode format for this use case instead of sending blobs of Javascript.<br>

<br>
But defining an adequate future-proof bytecode format ahead of time is difficult, and is almost a separate concern to what Asm.js is concerned with.<br>
<br>
<br>
What if independent parties could design their own program representation format that can be converted to executable form as needed?<br>
<br>
A party delivering a web application can choose a format for their Asm.js code, and include a decoder for it in their application startup procedure.<br>
If the runtime receiving this application supports the code creation API, the decoder can bypass the usual process of decompressing megabytes of Javascript code and then having to parse it.<br></blockquote><div><br></div>
<div>I'm not convinced that decompressing megabytes of JavaScript and parsing it (all in native code) is going to be any slower than having to JIT a JavaScript code generation routine, build up some horribly cache-unfriendly "sea of GC-heap-allocated linked nodes in JS" AST structure, then convert that "sea of linked nodes in JS" to the JIT's internal program representation. Decompress+parse is already a highly optimized code path as it is on the critical path of virtually every page load.</div>
<div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
To illustrate what I mean:<br>
Eval example:<br>
<br>
    load("./blob.js", function(input) {<br>
      var ts = {}<br>
      ts.start = Date.now()<br>
<br>
      Function(input)()<br>
      MyBlob.foo<br>
<br>
      ts.end = Date.now()<br>
      console.log("Eval time", ts.end - ts.start)<br>
    })<br>
<br>
Codegen example:<br>
<br>
    load("./blob.js", function(input) {<br>
      var ast = esprima.parse(input)<br>
<br>
      var ts = {}<br>
      ts.start = Date.now()<br>
<br>
      Function(escodegen.generate(<u></u>ast))()<br>
      MyBlob.foo<br>
<br>
      ts.end = Date.now()<br>
      console.log("Codegen time", ts.end - ts.start)<br>
    })<br>
<br>
In the second example, the line "Function(escodegen.generate(<u></u>ast))()" is less efficient and takes longer to run, even though we started with the AST loaded in memory, which is a form more suitable to being converted to an executable function.<br>
</blockquote><div><br></div><div>Unless the program representation used internally by the JS engines is exactly the same as the standardized representation (it isn't, and I doubt JS engines would let that implementation detail be standardized), then they still need to do a format conversion, but this time walking a linked sea of GC-heap allocated JS objects instead of doing a linear scan of the program text.</div>
<div><br></div><div>Can you provide some measurements about the relative sizes in memory of the AST structure that you are using vs. the raw code string? I'm almost positive that keeping the AST structure in JS is way too cache-unfriendly to be a performance win (not to mention GC).</div>
<div><br></div><div>-- Sean Silva<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
What if we could make the second example execute faster than the first one?<br>
<br>
I think this seemingly cosmetic capability would give web programs a degree of freedom that could end up solving some design problems.<br>
______________________________<u></u>_________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" target="_blank">https://mail.mozilla.org/<u></u>listinfo/es-discuss</a><br>
</blockquote></div><br></div></div>