Function.create
Katelyn Gadd
kg at luminance.org
Mon Jun 16 15:47:20 PDT 2014
Claude: Thanks, I was under the impression that existing ES6 class
inheritance wouldn't allow this to work. If it does, that's a big
improvement and I'll have to try it once class syntax is working in
one of the browsers I target.
Scott: The problem isn't a 'sync issue'; the body of the function
isn't *accessing* the prototype, the body of the function *depends on*
the prototype. For example, the number of arguments the function takes
depends on how many arguments the type's actual constructor has; I
can't know that until I've enumerated all the methods of the type (one
of the operations I have to do when building the type graph). A method
has a list of argument types and a return type; those types are,
naturally, type objects. It's possible for a type to have a method
that accepts its own type as an argument, so at that point you have a
very trivial cycle. This is why I end up having to create highly
inefficient delegating constructors in this scenario.
I solve a lot of the trivial cycles by basically doing my own
manually-collected weak references, where I assign types unique
identifiers and store those inside of reference tokens and resolve
them at runtime. This solves the simpler cases (at the cost of
destroying my performance and bloating the heap). However, there are
nastier cycles that can't be broken this way. I currently have
something more like a 'four part construction' algorithm and it is
still not enough to break all these cycles. The introduction of manual
weak references, manually auditing code to ensure references don't
escape when they shouldn't, and manually arranging things so that type
initialization occurs in a sensible order is all a huge pain and
produces fragile code. Being able to create a Function instance with a
prototype solves almost all of this. :)
The 'create a placeholder object and pass it around until the real
object is ready' solution could work right now in a language with
better auditing tools; the problem there is purely that I have no way
to enforce that the placeholder object doesn't escape into the heap.
Once it escapes, everything is ruined because I now have two versions
of type T floating around, and various code will be doing gets and
sets onto its version of T. I don't have any way to scan the heap and
replace all references to the old object with the new object, or make
the old object magically replace itself with the new object. (I
suppose I could *sort of* do this by making the old object a proxy?)
On Mon, Jun 16, 2014 at 8:24 AM, C. Scott Ananian <ecmascript at cscott.net> wrote:
> On Mon, Jun 16, 2014 at 3:06 AM, Katelyn Gadd <kg at luminance.org> wrote:
>> emscripten/asm.js) will face similar issues. The other compilers I've
>> seen that tackle this solution efficiently do so by abandoning the
>> 'new' keyword in favor of magic methods, which I consider a poor
>> solution.
>
> I'd be interested in hearing more about why you feel this is a poor
> solution. It seems to me that two part construction would work fine
> -- that is, don't let the code inside the Function object access the
> prototype until the appropriate properties have been set, so you don't
> have a sync issue.
> --scott
>
> ps. alternatively, it seems like you could use proxies to attack the
> sync issue directly.
More information about the es-discuss
mailing list