I want to propose an idea and get feedback on viability of this or some related addition to the language.

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().

Here is my naive guess at what the API should look like:

    func  = CompiledFunction.create()
    arg0  = func.arg(0)
    val   = func.get(arg0)
    val2  = func.op('*', val, func.literal(2))
    func.return(val2)
    result = func.done()

This builds "function(a){ return a * 2 }"

As you can see, this API provides a LLVM-like language.

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.

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.


Motivation:
There are a few types of programs that use generated Javascript in browsers:

- PEG.js
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. 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.

- Opal http://opalrb.org/try/ &c
Opal aims to implement Ruby running in Javascript environments. It is among other projects with similar aims for different languages operating in different ways. If special support for this API is available, web applications depending on tools like this could deliver their code and initialize with lower latency.

- Asm.js
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.

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.


What if independent parties could design their own program representation format that can be converted to executable form as needed?

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. 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.

To illustrate what I mean:
Eval example:

    load("./blob.js", function(input) {
      var ts = {}
      ts.start = Date.now()

      Function(input)()
      MyBlob.foo

      ts.end = Date.now()
      console.log("Eval time", ts.end - ts.start)
    })

Codegen example:

    load("./blob.js", function(input) {
      var ast = esprima.parse(input)

      var ts = {}
      ts.start = Date.now()

      Function(escodegen.generate(ast))()
      MyBlob.foo

      ts.end = Date.now()
      console.log("Codegen time", ts.end - ts.start)
    })

In the second example, the line "Function(escodegen.generate(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.

What if we could make the second example execute faster than the first one?

I think this seemingly cosmetic capability would give web programs a degree of freedom that could end up solving some design problems.
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to