Re: Bytecode
It's my understanding that the vast majority of the CLR's dynamic language support is at the runtime level, not the bytecode level. The bytecode is strongly typed (with lots of instructions/mechanisms for boxing, unboxing and type casts), and dynamic support is done through something called the 'DLR' that sits on top of the CLR. The DLR provides machinery for things like late binding and inline caches. For this C# snippet: ``` using System; public static class Program { public static void Main (string[] args) { dynamic one = (Funcint)( () = 1 ); dynamic doubleInt = (Funcint, int)( (int x) = x * 2 ); Console.WriteLine({0} {1}, one(), doubleInt(1)); } } ``` The desugared (well, decompiled from IL - the arg_XXX_X variables are from the decompiler, not actually in the IL) C# looks like this: ``` public static void Main(string[] args) { object one = () = 1; object doubleInt = (int x) = x * 2; if (Program.Maino__SiteContainer0.p__Site1 == null) { Program.Maino__SiteContainer0.p__Site1 = CallSiteActionCallSite, Type, string, object, object.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, WriteLine, null, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } ActionCallSite, Type, string, object, object arg_15C_0 = Program.Maino__SiteContainer0.p__Site1.Target; CallSite arg_15C_1 = Program.Maino__SiteContainer0.p__Site1; Type arg_15C_2 = typeof(Console); string arg_15C_3 = {0} {1}; if (Program.Maino__SiteContainer0.p__Site2 == null) { Program.Maino__SiteContainer0.p__Site2 = CallSiteFuncCallSite, object, object.Create(Binder.Invoke(CSharpBinderFlags.None, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } object arg_15C_4 = Program.Maino__SiteContainer0.p__Site2.Target(Program.Maino__SiteContainer0.p__Site2, one); if (Program.Maino__SiteContainer0.p__Site3 == null) { Program.Maino__SiteContainer0.p__Site3 = CallSiteFuncCallSite, object, int, object.Create(Binder.Invoke(CSharpBinderFlags.None, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null) })); } arg_15C_0(arg_15C_1, arg_15C_2, arg_15C_3, arg_15C_4, Program.Maino__SiteContainer0.p__Site3.Target(Program.Maino__SiteContainer0.p__Site3, doubleInt, 1)); } ``` So you can see all the inline cache and binding machinery at work there. As far as I know there were 0 bytecode changes to introduce this feature; I certainly didn't have to implement any special bytecodes to support 'dynamic' in JSIL. There are certainly some aspects of the CLR bytecode that make dynamic languages easier/harder to build on top of it, though. I just don't know what they are. I know a lot of the pain was reduced with the addition of 'lightweight code generation' or LCG, which allows jitting a single method on the fly and attaching it to a given context (like a method) so that it can access private members. This is used heavily in dynamic languages on the CLR now. On Wed, May 14, 2014 at 10:54 PM, C. Scott Ananian ecmascr...@cscott.net wrote: On Wed, May 14, 2014 at 9:12 PM, Axel Rauschmayer a...@rauschma.de wrote: It'd be great if there was material on the limits of the JVM and the CLR. AFAICT these are the only virtual machines that are trying to be universal (run both static and dynamic languages well). Well, from experience, the JVM is/was handicapped by some incidental decisions in its original standard library[*] that have a large adverse impact on startup time. This has restricted the 'usefulness' of the JVM from its inception. There are projects to re-engineer the standard library around this, but they have been slow (and are not yet complete)[**]. Similarly, the support for dynamic languages is fairly recent (JDK 7, JavaScript implementation using these features in JDK 8), so it's a bit early to know how that will play out in terms of adoption and practical use. So I'm not sure how much you're going to learn from the JVM, other than no matter how good/bad your bytecode is, other factors may dominate. That is: I would doubt most conclusions about bytecodes drawn from the example of the JVM, since I don't believe the bytecode design was a first order effect on its trajectory to date.
Re: Iterators, generators, finally, and scarce resources (Was: April 10 2014 Meeting Notes)
Minor correction to Domenic's comments in this (interesting) discussion; IEnumerable and IDisposable are separate concepts in C#. Neither IEnumerable or IEnumerator are disposable objects in C#; *however*, if you use 'for each' on an object that yields an enumerator that is *also* disposable, the compiler-generated sugar for the enumeration will dispose it. This is an important distinction: As described in the discussion thread here, not all enumerables and/or enumerators are disposable. Many of them are not, and have zero cleanup logic, so there's no need to include or call a Dispose method. That sugar support is explicitly there for enumerators that, if disposed explicitly, can release important resources earlier than the garbage collector would (file handles, sockets, etc.) On the other side (enumerator/enumerable authoring), C# solves this rather lazily: You can use try/finally (but not try/catch) around a 'yield' in an enumerator function, allowing you to do basic cleanup - the cleanup logic is moved into the compiler-generated object's Dispose method. This means that if you want cleanup, you opt into it explicitly, and use the same mechanism you use in normal non-enumerator functions. There's one caveat that this causes unexpected disposal behavior in some corner cases (due to how C# initializes generators), but that's more of an issue with their generator implementation than anything else. On Tue, Apr 29, 2014 at 12:17 PM, Domenic Denicola dome...@domenicdenicola.com wrote: Dave and Andy's responses have me pinging back and forth as to which side I'm on. Both seem convincing. Dave's response especially brought the issue into focus for me in a way that I think is clear, so let me explain what I learned from it: What we are essentially talking about here are two types of things: - Disposable resources - Iterable resources We are talking about both the sync case, and the async case. Andy's contention is that most sync iterable resources are not disposable, whereas Dave's is that most async resources are disposable. Both of these positions seem plausible to me. The question then comes, should for-of handle iterable resources only (as it does today), or should it take care of disposable resources as well (as it does in e.g. C#)? Andy's code example, viz. ```js var file = openFile(foo.txt); try { for (var line of lines(file)) { if (line == '-- mark --') { break; } } } finally { file.close(); } ``` advocates for this separation, putting the burden on the user to handle the disposable part, letting for-of focus on the iterable aspect. Dave advocates that this code become ```js for (var line of lines(openFile(foo.txt))) { if (line == '-- mark --') { break; } } ``` and the disposableness be handled automatically, which is certainly more convenient for the user. This second code example, however, hides two kinds of magic: iterability, and disposability, in the same syntax. An alternative would be to introduce a construct specifically to handle disposability, like C#'s `using`. You could use it generically such that `using(x) { ... }` becomes `try { ... } finally { x.dispose(); }`. In particular the example would become ```js using (var file = openFile(foo.txt)) { for (var line of lines(file)) { if (line == '-- mark --') { break; } } } ``` This still isn't all that convenient, of course. And going along with Dave's argument, it will become especially inconvenient when async iterables, most of which will be disposable, start appearing. Perhaps this is why C# decided to include both iterable and disposable functionality in their `foreach`. But inconvenience is easily solved via MOAR SUGAR: ```js for (var line using files) { if (line == '-- mark --') { break; } } ``` I like this approach for a few reasons: - It decouples iterability and disposability, giving each distinct syntax constructs - Via sugar, it composes them into something just as convenient as if we had baked both of them into `for`-`of`, while giving you an explicit signal of what's going on and what the different semantics are. - It of course avoids any optimization hazards, being opt-in. - Most importantly, it pushes off this question into ES7, when we can properly design a counterpart `using` block to build on top of. The drawback of this approach is that it doesn't bake in a disposability protocol into the language. By saying that `for`-`of` will invoke `return()`, we are essentially saying if you want a disposable object, use the method named `return()` to dispose of it. This kind of ecosystem standardization is a good thing. But on the other hand, if in ES6 this disposability protocol is only useful for synchronous iterators---which, as Dave admits, are less likely to represent disposable resources than async ones---then it's unclear that much is gained. I'd
Re: setPrototypeOf vs obj.__proto__ assignment
Is my understanding correct that __proto__/setPrototypeOf are still required if you want to do things like that with instances of Function? Or did Function's constructor finally get patched to let you set a prototype? On Mon, Apr 7, 2014 at 2:26 AM, David Bruant bruan...@gmail.com wrote: Le 07/04/2014 11:05, Andreas Rossberg a écrit : On 4 April 2014 19:49, Allen Wirfs-Brock al...@wirfs-brock.com wrote: __proto__ is there for legacy compatibility. setPrototypeOf should be preferred for new code For new code, neither should be used. yup. For new code, in most practical cases, people can use classextend including to subclass Array and Date where __proto__ used to be the only way. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Value Types as map keys in ES7
I guess the analog for this in traditional JS 'Object' instances is that when you use the [] operator, i.e. obj[valueObject], it actually does obj[valueObject.toString()], so you can control the 'hashing function' in a sense by overriding toString. It seems natural to want something equivalent here, preferably not based on strings... (though I don't know how people feel about exposing hash internals and saying 'your hash key needs to be an integer') Map would certainly be far more useful if it had support for customizable hashing, otherwise it's just a slightly faster replacement for Objects with cleaner semantics. Maybe making it possible to get the same value back using two different keys that don't compare the same with === is against the purposes here, though. On Sat, Apr 5, 2014 at 10:21 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: I'd like to raise an issue with ES7 value objects with maps raised here: http://esdiscuss.org/topic/maps-with-object-keys To save you all time, let me sum things up: ES6 maps don't solve a particular (but common) issue for me - using compound objects as keys. I do a lot of statistical analysis and I need keys to be compound tuples or other values. This is currently not possible with ES6 since map key equality is checked with `===` so it is always reference equality ES7 introduces value objects - which are really cool anyway. This allows for compound keys.which partially solves my issue because value keys are compared structurally with `===`. However, it does not let me index on partial information (described in my last commend on that issues). Since it is impossible to override `===` in value objects from what I understand - It would be impossible for me to use partial objects as keys. To illustrate, if for example I have a lot of 10 dim vectors, and I want to index them as keys based on their first two dimensions - it is impossible at the moment and I have to project them into their 2d counterparts which have no further use for me. Is this somehow addressed? I'm unsure where to look for answers. It seems natural to me to allow specifying a hashing function in the `Map` constructor (rather than on every type) to solve this particular (but again, rather common in code that does crunching) problem. Thanks, Benjamin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Source maps (was: Multiline Strings)
The accuracy of this aside, history shows that most of my users are not satisfied by 'just debug the JS, it's fairly readable'. Maybe emscripten, gwt, etc. users are more fluent in JS and don't mind debugging it, but based on what I've seen, maybe not... I do think it's important that source maps don't obscure what's happening at the JS level, though - presumably all the modern debuggers let you toggle them back off once they're loaded, so that's satisfied? -kg On Sun, Mar 16, 2014 at 11:03 AM, Bill Frantz fra...@pwpconsult.com wrote: On 3/14/14 at 3:02 PM, fitz...@gmail.com (Nick Fitzgerald) wrote: I feel very strongly that users debugging their sources that were compiled to js should be able to set watch expressions and conditional breakpoints in their source language. My experience with debuggers says the while the vast majority of the time you want to be able to debug it in the language you wrote, sometimes you want to debug it in the language it broke in. Being able to look at the lower level language can clear up misconceptions about what a higher level construct means. It can also reveal compiler bugs. It should also be recognized that all compiled programs break in machine language. :-) Cheers - Bill --- Bill Frantz| Concurrency is hard. 12 out | Periwinkle (408)356-8506 | 10 programmers get it wrong. | 16345 Englewood Ave www.pwpconsult.com |- Jeff Frantz | Los Gatos, CA 95032 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Source maps (was: Multiline Strings)
I agree that the current source maps format does a poor job of handling many translation/transpiling/js-as-compilation-target scenarios. I do think it is worthwhile to try and build on the existing format instead of reinvent it or significantly overhaul it, though. The things it does, it does a pretty decent job of [1], and it seems to be composable, so you can update your source map at each stage in your JS build pipeline. It just needs to do a good job of mapping other things like scopes, stack frames, etc. I'll also point out that the current proposal (rev 3, as linked) is very opaque, and despite multiple readings I failed to understand core features until someone explained them to me. Even now, I can't really tell how variable name mapping is accomplished with the current proposal, and VLQ is barely understandable. A clearer description of the spec would probably make it much easier for people to generate usable source maps or write software that uses them. My particular projects would definitely benefit greatly from a usable version of the source maps spec, so I would love to help contribute to the process of improving them. I have not seen any obvious way to contribute in the past as the format seems to have been the result of private development at Google and/or Mozilla. I do applaud the original developers' attempts to keep the spec narrowly focused in terms of what problems it solves and how it solves them. -kg [1] One exception to this: Dear god, why are the mappings a giant string full of oddly-encoded variable-length data represented as base64? I cannot imagine a worse format. This fails on multiple counts: a) I can't see any way to efficiently stream in this data; you have to parse it all at once (especially since it's JSON) b) You have to perform multiple passes on this data to make sense of it, unless you create a customized parser: First you have to parse the JSON, then you have to parse the mapping string to find the split points (the semicolons), and then once you've done that you have to undo the weird base64+VLQ encoding to get actual integers that you can use as an internal representation. The third step can be deferred, at least. c) The fact that the data is all in one big chunk (even if it is condensed) means that you have to generate it all at once and load it all at once. That seems intrinsically awful for large source files and it increases memory demands on each stage of your compilation pipeline (this may be a big issue given that compilation can already be really demanding on memory.) The alternate 'sections' format seems to address some of this, but it is not clear if it addresses all of it. It is unclear to me why mappings is a single string instead of an array of smaller strings. In all honesty, I think this entire format could be replaced with a considerably simpler protobuf-based format, and all the parsing/generation code could be automatically generated by the tools that handle protobuf formats. It would be a win for everyone (but then we'd have to figure out a way to roll the new format out; yck.) JSON + base64 is simply not appropriate for a file format that will largely be handled by JS *runtimes* and debuggers with significant performance and memory concerns. On Wed, Mar 12, 2014 at 2:00 PM, Nick Fitzgerald fitz...@gmail.com wrote: 4) Browsers are still all over the place in how they report Error stack trace information. We (Firefox Developer Tools) purposefully don't expose source mapped stacks to the web because it would require adding some kind of API to know when source maps are done being fetched or blocking(!) on Error.prototype.stack until the source map is fetched. We also avoid fetching source maps unless the debugger is open, so this would expose to the web if the debugger is open. Furthermore, we wouldn't want to only have the source mapped stack, you would also want the plain JS stack if you think that the source map could be bogus or if you are debugging the source maps you are generating as a tool author. This would further complicate the stack string. 1) There is not yet a standard for sourcemaps. But see https://docs.google.com/a/google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k, https://developers.google.com/chrome-developer-tools/docs/javascript-debugging#source-maps, and https://github.com/mozilla/source-map/. Would someone care to champion this for inclusion in ES7? If a debug format for targeting JavaScript were to be standardized, it should do more than simply file/line/column translation. My thoughts on this subject outgrew an email reply, so I have collected them here: http://fitzgeraldnick.com/weblog/55/ _Nick_ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org
Re: Typed Objects / Binary Data Polyfills
(Re: minor off-list clarification on non-transparent objects) I see, it looks like this is the relevant bit of the strawman: There are three built-in types that are considered *opaque*: Object, string, and Any. For security, they are not allowed to expose their internal storage since they may contain pointers (see below). A struct or array type is opaque if it contains opaque fields or elements, respectively. A type that is not opaque is *transparent*. Overlooked it on my first read-through since it isn't directly referenced elsewhere. That seems like it addresses the problem. Looking at the strawman and the polyfill and the spidermonkey implementation, each one seems to have a different API for arrays. Is this something that will get standardized later? I've seen get, getItem and [] as 3 different ways to read values out of a typed object array; [] seems like an obvious poor choice in terms of being able to polyfill, but I can see how end users would also want typed object arrays to act like actual arrays. The spidermonkey implementation seems to expose 'fieldNames' in addition to fieldOffsets/fieldTypes for reflection, which seems like a good idea. If DataView were to also get optimized in SpiderMonkey, that would release a lot of the pressure (use-case wise) for Typed Objects to expose fine-grained control over alignment/padding and it would make it less immediately necessary for them to exist. That's probably a good thing. What is the intended use scenario when trying to pass a typed object array to WebGL? Pass the array's .buffer where a typed array would normally be passed? Or is it basically required that WebGL be updated to accept typed object arrays? It's not totally clear to me whether this will work or if it's already been figured out. The elementType property on typed object arrays is a great addition; I'd suggest that normal typed arrays also be updated to expose an elementType. i.e. (new Uint8Array()).elementType === TypedObject.uint8 On Mon, Nov 18, 2013 at 2:35 AM, Dmitry Lomov dslo...@chromium.org wrote: We definitely are looking for feedback on the proposal! Please keep it coming. Here are some answers reflecting our current thinking. On Sun, Nov 17, 2013 at 4:07 PM, K. Gadd k...@luminance.org wrote: Since the strawman is close to the final spec, questions/nitpicks: I noticed the current spec explicitly provides no control over element alignment/padding. Are there specific reasons behind that? It dramatically reduces the value of typed objects for doing file I/O (aside from the endianness problem, which actually doesn't matter in many of those cases), and it means they can't be used to provide direct compatibility with C struct layouts in specific cases - for example, filling vertex buffers. I understand that there is no desire to provide the *full* feature set available in C (fixed-size arrays, variable-size structs, etc.) but alignment/padding control is used quite a bit. DataView has significant performance issues (some due to immature v8/spidermonkey implementations, some due to the design) that make it unsuitable for most of these use cases, even if it's the 'right' way to handle endianness (disputable). The handwaving that WebGL implementations can 'just introspect' in these cases seems shortsighted considering the reality of WebGL: hundreds of shipped libraries and apps using current WebGL cannot be guaranteed to keep doing the right thing when interacting with typed arrays. If a typed array full of Typed Objects can still be treated like an array full of bytes or float32s, that allows existing WebGL code to keep working, as long as you ensure the layout of the objects is correct. That means people can start incrementally adding uses of Typed Objects to their code right away - and it means they can introduce them based on a polyfill of Typed Objects instead of waiting for the browser to implement *both* Typed Objects and new WebGL support for Typed Objects. The idea for alignment/padding is to _specify_ it for typed objects. There is a rule that tell the user how the typed object will be aligned and that rule is set in stone. If the programmer declares a typed object, she/he knows what the memory layout is. However, we do not (at least in the first version) provide any explicit API for changing the alignment. The rule is Each field is padded to reside at a byte offset that is a multiple of the field type’s byte alignment (specified below via the [[ByteAlignment]] internal property). The struct type’s byte length is padded to be a multiple of the largest byte alignment of any of its fields. So every field is at its natural boundary, and the natural boundary of the struct is the largest of the natural boundaries of its field types. This rule is pretty much what C compilers do anyway. This appears to us a good compromise between API and implementation complexity and expressiveness. BTW, DataView are indeed
Typed Objects / Binary Data Polyfills
Are there any known-good polyfills for the current draft Typed Objects / Binary Data spec? Presently, JSIL has a set of primitives that roughly correspond with a big chunk of the draft specification. I'm interested in seeing whether they can work atop ES6 typed objects, which means either adapting it to sit on top of an existing polyfill, or turning my primitives into a polyfill for the draft spec. If it's useful I might be able to find time for the latter - would having a polyfill like that be useful (assuming a good one doesn't already exist)? Having an efficient equivalent to the spec in JS VMs is pretty important for JSIL to ever be able to deliver emscripten-level performance (a single emscripten-style fake heap is not an option because .NET relies on garbage collection). If a polyfill (even a partial one) could help move the process along for the spec, that'd be great. If what the process actually needs is some sort of feedback, maybe I could offer that instead. The status of the spec is unclear to me :) -kg ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Typed Objects / Binary Data Polyfills
Since the strawman is close to the final spec, questions/nitpicks: I noticed the current spec explicitly provides no control over element alignment/padding. Are there specific reasons behind that? It dramatically reduces the value of typed objects for doing file I/O (aside from the endianness problem, which actually doesn't matter in many of those cases), and it means they can't be used to provide direct compatibility with C struct layouts in specific cases - for example, filling vertex buffers. I understand that there is no desire to provide the *full* feature set available in C (fixed-size arrays, variable-size structs, etc.) but alignment/padding control is used quite a bit. DataView has significant performance issues (some due to immature v8/spidermonkey implementations, some due to the design) that make it unsuitable for most of these use cases, even if it's the 'right' way to handle endianness (disputable). The handwaving that WebGL implementations can 'just introspect' in these cases seems shortsighted considering the reality of WebGL: hundreds of shipped libraries and apps using current WebGL cannot be guaranteed to keep doing the right thing when interacting with typed arrays. If a typed array full of Typed Objects can still be treated like an array full of bytes or float32s, that allows existing WebGL code to keep working, as long as you ensure the layout of the objects is correct. That means people can start incrementally adding uses of Typed Objects to their code right away - and it means they can introduce them based on a polyfill of Typed Objects instead of waiting for the browser to implement *both* Typed Objects and new WebGL support for Typed Objects. My primitives have control over alignment/padding and it doesn't seem to be that hard to implement (in JS, that is) - are there things that make this hard to provide from inside a VM? Being able to add extra padding, at least, would be pretty useful even if alignment has to remain locked to whatever the requirements are. I see reference types are exposed (string, object, any) - the way this actually works needs to be clearly stated. Is it storing a GC pointer into the buffer? Are there safety concerns if it's overwritten, or loaded from a json blob or something else like that? How big are string/object/any in the internal representation? Does their size depend on whether the running browser is 32-bit or 64-bit? I'd be open to collaborating on a polyfill of Typed Objects once it's clear how they actually work. We can repurpose JSIL's existing implementation and modify it to get the semantics in the spec. On Sun, Nov 17, 2013 at 5:04 AM, Till Schneidereit t...@tillschneidereit.net wrote: On Sun, Nov 17, 2013 at 10:23 AM, K. Gadd k...@luminance.org wrote: Are there any known-good polyfills for the current draft Typed Objects / Binary Data spec? I want this, too, and will start working on it soon-ish if nobody else does or already did. Presently, JSIL has a set of primitives that roughly correspond with a big chunk of the draft specification. I'm interested in seeing whether they can work atop ES6 typed objects, which means either adapting it to sit on top of an existing polyfill, or turning my primitives into a polyfill for the draft spec. If it's useful I might be able to find time for the latter - would having a polyfill like that be useful (assuming a good one doesn't already exist)? Having an efficient equivalent to the spec in JS VMs is pretty important for JSIL to ever be able to deliver emscripten-level performance (a single emscripten-style fake heap is not an option because .NET relies on garbage collection). If a polyfill (even a partial one) could help move the process along for the spec, that'd be great. If what the process actually needs is some sort of feedback, maybe I could offer that instead. The status of the spec is unclear to me :) The strawman at [1] is fairly close to what's going to end up in the spec, content-wise. Additionally, the implementation in SpiderMonkey is pretty complete by now, and there are lots of tests[2]. I don't know what the timing for integrating Typed Objects into the spec proper is, cc'ing Niko for that. cheers, till [1]: http://wiki.ecmascript.org/doku.php?id=harmony:typed_objects [2]: http://mxr.mozilla.org/mozilla-central/source/js/src/tests/ecma_6/TypedObject/ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Weak callbacks?
Finding out at runtime (by doing a sanity check in the finalizer) is a way to catch bugs in the application that were not caught at compile/development time, so you can log/report them and go back and fix them. This is an incredibly useful facility since (generally speaking) promise libraries have lots of opportunities for human mistakes to hide failures at runtime. When you have error handlers written properly for something like 95% of your promises, catching the other 5% when they rarely fail gets pretty complicated. Consider how a developer testing out some network code might only ever run the application in the office, so they'll never see the kind of exceptions you get when running an application over a modem. Getting useful diagnostic information when one of those rare exceptions isn't handled correctly lets you fix those problems without being able to necessarily reproduce them on demand. On Tue, Nov 12, 2013 at 8:07 PM, David Bruant bruan...@gmail.com wrote: Le 12/11/2013 13:42, Kris Kowal a écrit : One of the concerns with promises is that they consume exceptions that may or may not be handled. I have been looking forward for WeakRef as one of the avenues available to mitigate this problem. A post-mortem finalizer would be able to surface an error that was trapped by a promise or promises that were eventually garbage collected, and therefore provably never-to-be-handled. It is true that this problem can be decisively mitigated in other ways, like requiring a promise to forward to a terminal done() in the same turn of the event loop, but I find this particular solution unpalatable. I do find a promise inspector compelling, one that will show an error until it is handled, but even in this case, I think it is compelling to visually elevate an unhandled error to a provably never-to-be-handled error, and this is not possible, at least outside chrome-space, without WeakRef. I understand the need to know when a promise has an unhandled error at development time, I'm less clear on why you need to know it at runtime. Why would you do with this information? handle the error? If you think of wrapping promises in weakrefs, why not just add error handling? To me, it looks like the same amount of effort. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Dispatching entirely off argument types and not anything else (like count) is an interesting idea. I'm not sure it's on topic for this discussion though. Is there a way to actually do type dispatch in ES at present, let alone efficiently? Based on my understanding of current VMs, you'd have to do a song and dance (per argument) like this: Is it undefined? Terminate argument scanning. Check typeof to see if it is a special type; dispatch based on that if so. If it's not a special type, check to see if it's null. If so, dispatch based on 'object' since you can't know more about the type than that and have to guess. If it's not null, call Object.getPrototypeOf and then somehow look up that prototype against the type information you're doing overload dispatch against. It's not clear to me how this would interact with newish features like proxies, either, but I suppose it would at least work. At present doing fast dispatch based on argument count and THEN only doing per-argument type checks if necessary is a huge performance boost because VMs can actually generate relatively fast native code for an arguments.length check. Typeof checks and getPrototypeOf do not generally produce fast code in my experience so it would be problematic to do them for every overloaded call site instead of just call sites that actually care about the types of particular arguments. Doing this type of dispatch is comparatively simple in .NET since for any non-null value you can request a Type object for it (via GetType) and then use that as a key into a lookup table/dictionary - so the operation becomes 'if (x == null) typeId = 0 else typeId = typeTable[x.getType()]' or something along those lines, which you can optimize down to a set of conditionals when the number of types you care about is small. The fact that ES does not allow setting properties on all values means it's impossible to hang type information off values like that. To put it another way, if I have an overloaded functions with two signatures - like say writeline(s) and writeline(f, s) - then in practice I just dispatch off the argument count. Because there are not multiple signatures with the same count, there's no way the user could have intended to call something else. In use cases where correctness is more important, you'd probably want to rigorously check every argument and dispatch off that. From a performance perspective I also find the idea of having to 'scan' the arguments list sequentially looking for an undefined sentinel to be pretty gross. Do we really need to introduce the awful null terminated string pattern, along with all its problems, in more places? On Sun, Nov 10, 2013 at 1:49 PM, Mark S. Miller erig...@google.com wrote: On Sun, Nov 10, 2013 at 1:30 PM, K. Gadd k...@luminance.org wrote: JSIL and embind both need arguments.length for efficient method call dispatch when dealing with overloaded functions. Is it your intent that all such scenarios must now pay the cost of creating an array (to hold the rest arguments) and then destructuring it, for every call? At present it's possible to avoid this overhead in V8 and SpiderMonkey by using arguments.length + arguments[n] or by using arguments.length + patterned argument names. Hi Katelyn, No one is taking arguments away. Perhaps we would if we could but we can't. So as I said just now to Allen, if you really need to do this, go ahead and use arguments.length. But do you really need to do this? Assuming for a moment that we were all agreed that the best practice is to treat absence the same as undefined, why not go with the best practice and be done? On Sun, Nov 10, 2013 at 1:24 PM, David Bruant bruan...@gmail.com wrote: Le 10/11/2013 22:19, Brendan Eich a écrit : On Nov 10, 2013, at 9:12 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Not sure why this is so needed though. Allen's posts make the case: webidl and varargs-style functions. Not all legacy. WebIDL creates spec, not code. The language syntax doesn't need to evolve for that. Allen showed that rest params+destructuring allows self-hosting without |arguments| Varargs functions have rest parameters. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Weak callbacks?
More tooling is great for developing new software in ES, but it does nothing to address use cases where existing software and algorithms can't be ported without Weak References. Perhaps enough research will allow us to arrive at some sort of general 'best practice' for replacing the use of weak references with something else; sounds like something some people with PhDs could write a paper on :) On Fri, Nov 8, 2013 at 8:57 AM, David Bruant bruan...@gmail.com wrote: Le 08/11/2013 17:09, Jason Orendorff a écrit : (As a bonus, the weirdness will happen in one implementation and not another, and you and your users will blame the implementation. So there will be pressure on implementers to reduce the nondeterminism by doing GC more frequently—which trades off against other performance measures.) Super-bonus: Heisenbugs (bugs that happen in prod, but not while debugging) https://en.wikipedia.org/wiki/Heisenbug And in this case, it all seems unnecessary. There is apparently already explicit code for both removing B and C, and later coping with their disappearance (since the weak reference may go null). That code could just as easily set a bit on B and C marking them as removed, and then test that in the chasing code. Agreed. In a way, Kevin conceded it when he wrote in an earlier message: I had to manually remove the event listeners at an appropriate time (and finding an appropriate time can be difficult!) And this looks very much like a software engineering issue, not a language issue. Maybe we (JavaScript developers!) should invest in better memory tooling see how far it gets us. We have fantastic tooling for studying time perf (Chrome has 2 types of profilers and the timeline view to help with the 60fps, Firefox and IE11 getting there too), how come we're still doing low-level heap snapshots for memory perf? Is space fundamentally that much harder to study than time? Taking the tooling road first, worst case, we throw the tooling away... not an option when a feature is in the wild. Let's try at least? David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Weak callbacks?
The difference is that if the large cycle is only uncollected because the weak references haven't been zapped, in a low memory/out of memory situation, the runtime's collector can go through and zap all weak references. If I write an ES application and do my own cycle collection/weak reference zapping, I have no way to respond to that low/out of memory situation by doing a collection on demand, so instead my application will run out of memory at arbitrary points in time. The latency is not actually a major concern here, and I wouldn't argue that weak references improve on latency. Weak references make it *possible* for the language's collector to collect those cycles *at all*. Without them, the only way they can be collected is if the *application* collects them, and it has no trivial way to do so at the correct time. I can't comment on how weak references would work in an ES collector either, but I can imagine weak reference implementations that would not prevent collection in the first place, so zapping would not be necessary in order for those cycles to be collected. IIRC, some weak reference implementations work by having the strong object maintain a list of the weak references that point to it, and the weak references do not actually keep the strong object alive. In such a scenario, you would not need to zap references for the object to be collected; rather, collecting the object would replace all the weak references with null, thus ensuring that the dead object stays unreachable. On Fri, Nov 8, 2013 at 2:42 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Nov 7, 2013, at 3:16 PM, Mark Miller wrote: I agree. This is a good use for weakrefs without the need for finalization. Thanks! On Thu, Nov 7, 2013 at 3:12 PM, K. Gadd k...@luminance.org wrote: The problem is that the cycles remain uncollectable for a very long period of time, even though functionally the references don't need to be strong. Ah, these are all basically the same problem and you will likely see the same latency effects for all of them. Any GC design where you may have serious latency for collection cyclic structures (for example, a generational heap where the circular structure crosses generations) is very likely to also have similar latency for zapping weak references that are used in the similarly shaped data structures. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Weak callbacks?
When I talk about the importance of weak references I am *not* talking about the importance of finalization for managing native/remote resources; that's an important consideration but it's a separate one. When I talk about why weak references are important, I mean for the purposes of building large applications without creating uncollectable cycles in object graphs. Doing this without weak references is *very* difficult in some scenarios, and in other scenarios requires manual management of all object lifetimes (addref/release style, or having a single lifetime owner that 'deletes' an object on demand). That's the sort of obstacle that factors into a developer's choice of language and toolset. I've seen this particular concern with ES crop up in the past on real projects, and I've seen firsthand how difficult it is to avoid uncollectable cycles in a language environment without any sort of weak reference mechanism. Leaking large uncollectable cycles can have catastrophic consequences in multimedia applications and games, where those cycles might be retaining images or sounds or other huge game assets. On Thu, Nov 7, 2013 at 9:19 AM, Terrence Cole tc...@mozilla.com wrote: On 11/06/2013 07:37 PM, K. Gadd wrote: Generally speaking, all the discussions on this list about WRs so far have not suggested that there is any way to introduce WeakRefs without making GC behavior observable in some fashion. WeakRefs functionally make GC observable because when you try to get at the target of the weakref, you either get it or you don't. Once you introduce the ability to get back 'null' when asking for the target of a WR (or any similar failure case), you can use that to determine things about GC behavior. If you somehow eliminate this weakness, WRs no longer solve the problems they are intended to solve. Or at the least, they solve only a small reduced subset of the problems solved in real software via the use of weak references. Being able to access the target of the WR (and have this operation fail) is core to their value (even if finalization notifications are also used quite often). I've already argued in the past about why weak references are important, and why not having solutions for those problems will kneecap the development of web applications by either preventing certain types of software from running in the browser, or forcing implementers to write their own GCs (or entire runtime environments) inside the browser, as is done with environments like emscripten and native client. Once that becomes the solution, the ES spec is irrelevant for those applications because they have had to abandon the language. While the risk of something like this happening is still relatively low, the risk increases over time as more people begin seriously considering solutions like emscripten and nacl - we're starting to see companies ship real products using them already. If this spreads to popular reusable libraries (physics libraries, rendering libraries, etc), there's a risk that those libraries will pull new applications out of the ES realm because it's not possible to use those libraries without abandoning ES in favor of a custom GC/runtime environment. Based on the conversations thus far, a choice just has to be made between the two downsides: exposing some amount of GC internals, or making it impossible to write some subset of applications in ES. It's possible that exposing GC semantics has such catastrophic security consequences that ruling those applications out is merited. It's also possible that workarounds can be applied to reduce the harm of GC visibility (I think in the past someone - maybe Mark? - suggested that disabling cross-realm WRs would mitigate the damage considerably?) This is a false dichotomy. At the extreme, we could simply ship a new builtin resource manager which has it's own GC behaviour that we can expose at will. Given that the sorts of resources that people want to use the memory GC to manage generally have very different cost and volume tradeoffs than memory [1], this is actually much more reasonable than it sounds. The real problem with weak things is that they do have a performance impact on the GC, even when not used. Missing weak-maps can at least be worked around; a slow environment cannot. -Terrence 1 - http://www.mail-archive.com/dev-tech-js-engine-internals@lists.mozilla.org/msg00572.html On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt oli...@apple.com wrote: On Nov 6, 2013, at 3:14 PM, Rick Waldron waldron.r...@gmail.com wrote: On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola dome...@domenicdenicola.com wrote: Thanks Mark for the education, especially on the pre- vs. post-morterm finalization distinction. I don't think I was specifically advocating for pre-mortem in my OP, since I didn't really understand the difference :P. Post-mortem finalization
Re: Weak callbacks?
I'll try and restate an example I used before. Let's say you're building a somewhat simple tab-based application, where each tab represents a different 'mode'. In this case, you need a higher level coordinating object that manages the tab bar, and it needs to own references to all of the active modes in order to manage the tabs. Similarly, each mode may need to have a reference to the coordinator in order to interact with it - like by setting the title of the tab, or opening a new tab containing another mode - and it may need to have references to other modes in order to communicate (like if one tab opens a tab containing related information). In a model like that, you can trivially end up with object cycles. All the references (going in every direction) are strong, so to successfully collect a mode you need to ensure that every reference to it from live objects is released. This is problematic because it means that, for example: If Mode A opens a new tab containing Mode B, and Mode A wants to respond to things happening in Mode B, Mode A now has to register some sort of event listener on Mode B. This means that Mode A and Mode B have now formed a strong cycle: Mode B's event listener list contains a strong reference to Mode A (to fire the event notification), and Mode A has a strong reference to Mode B in order to be able to respond to those events. Now, if you close Mode B, the coordinator gets rid of the tab and drops its strong references to Mode B - the tab is 'gone' - but there's no trivial way to ensure that everyone else holding a reference to it is dead. If multiple tabs interact in this way it's possible for a huge graph of objects to be hanging off one live tab. Eventually, if you close enough tabs you might 'free' the graph, but if you aren't careful the coordinator itself can end up keeping dead tabs alive, with things like event listener lists. In the real apps I've worked on like this, the solution was some form of weak references - making event listeners own weak self-references instead of strong self-references, so that in normal circumstances event subscriptions expire along with the subscriber, along with using weak references directly in cases like 'tab a spawns tab b' in order to ensure that you aren't keeping an object alive just to monitor it. IIRC, cycles like this are already common in some DOM scenarios, where event subscription and such result in big graphs of objects hanging off a single live object? I've certainly run into it in a few cases, where an event listener hanging off an audio element caused a huge graph of objects to leak, and I had to manually remove the event listeners at an appropriate time (and finding an appropriate time can be difficult!) On Thu, Nov 7, 2013 at 2:33 PM, Mark S. Miller erig...@google.com wrote: Could you give an example, hopefully simple, of such a problem you can solve better with GC + weakmaps + weakrefs but without finalization, vs just GC + weakmaps ? Thanks. On Thu, Nov 7, 2013 at 1:46 PM, K. Gadd k...@luminance.org wrote: When I talk about the importance of weak references I am *not* talking about the importance of finalization for managing native/remote resources; that's an important consideration but it's a separate one. When I talk about why weak references are important, I mean for the purposes of building large applications without creating uncollectable cycles in object graphs. Doing this without weak references is *very* difficult in some scenarios, and in other scenarios requires manual management of all object lifetimes (addref/release style, or having a single lifetime owner that 'deletes' an object on demand). That's the sort of obstacle that factors into a developer's choice of language and toolset. I've seen this particular concern with ES crop up in the past on real projects, and I've seen firsthand how difficult it is to avoid uncollectable cycles in a language environment without any sort of weak reference mechanism. Leaking large uncollectable cycles can have catastrophic consequences in multimedia applications and games, where those cycles might be retaining images or sounds or other huge game assets. On Thu, Nov 7, 2013 at 9:19 AM, Terrence Cole tc...@mozilla.com wrote: On 11/06/2013 07:37 PM, K. Gadd wrote: Generally speaking, all the discussions on this list about WRs so far have not suggested that there is any way to introduce WeakRefs without making GC behavior observable in some fashion. WeakRefs functionally make GC observable because when you try to get at the target of the weakref, you either get it or you don't. Once you introduce the ability to get back 'null' when asking for the target of a WR (or any similar failure case), you can use that to determine things about GC behavior. If you somehow eliminate this weakness, WRs no longer solve the problems they are intended to solve. Or at the least, they solve only a small reduced subset
Re: Weak callbacks?
I am not aware of any way to implement my described scenario using WeakMaps without having the same cycle collection issues. I haven't seen any examples of WeakMap used for this in the wild either. On Thu, Nov 7, 2013 at 2:48 PM, felix lee feli...@gmail.com wrote: That example looks to me like it could be implemented with WeakMap instead of WeakRef. Am I missing something? On Thu Nov 07 2013 at 2:43:45 PM, K. Gadd k...@luminance.org wrote: I'll try and restate an example I used before. Let's say you're building a somewhat simple tab-based application, where each tab represents a different 'mode'. In this case, you need a higher level coordinating object that manages the tab bar, and it needs to own references to all of the active modes in order to manage the tabs. Similarly, each mode may need to have a reference to the coordinator in order to interact with it - like by setting the title of the tab, or opening a new tab containing another mode - and it may need to have references to other modes in order to communicate (like if one tab opens a tab containing related information). In a model like that, you can trivially end up with object cycles. All the references (going in every direction) are strong, so to successfully collect a mode you need to ensure that every reference to it from live objects is released. This is problematic because it means that, for example: If Mode A opens a new tab containing Mode B, and Mode A wants to respond to things happening in Mode B, Mode A now has to register some sort of event listener on Mode B. This means that Mode A and Mode B have now formed a strong cycle: Mode B's event listener list contains a strong reference to Mode A (to fire the event notification), and Mode A has a strong reference to Mode B in order to be able to respond to those events. Now, if you close Mode B, the coordinator gets rid of the tab and drops its strong references to Mode B - the tab is 'gone' - but there's no trivial way to ensure that everyone else holding a reference to it is dead. If multiple tabs interact in this way it's possible for a huge graph of objects to be hanging off one live tab. Eventually, if you close enough tabs you might 'free' the graph, but if you aren't careful the coordinator itself can end up keeping dead tabs alive, with things like event listener lists. In the real apps I've worked on like this, the solution was some form of weak references - making event listeners own weak self-references instead of strong self-references, so that in normal circumstances event subscriptions expire along with the subscriber, along with using weak references directly in cases like 'tab a spawns tab b' in order to ensure that you aren't keeping an object alive just to monitor it. IIRC, cycles like this are already common in some DOM scenarios, where event subscription and such result in big graphs of objects hanging off a single live object? I've certainly run into it in a few cases, where an event listener hanging off an audio element caused a huge graph of objects to leak, and I had to manually remove the event listeners at an appropriate time (and finding an appropriate time can be difficult!) On Thu, Nov 7, 2013 at 2:33 PM, Mark S. Miller erig...@google.comwrote: Could you give an example, hopefully simple, of such a problem you can solve better with GC + weakmaps + weakrefs but without finalization, vs just GC + weakmaps ? Thanks. On Thu, Nov 7, 2013 at 1:46 PM, K. Gadd k...@luminance.org wrote: When I talk about the importance of weak references I am *not* talking about the importance of finalization for managing native/remote resources; that's an important consideration but it's a separate one. When I talk about why weak references are important, I mean for the purposes of building large applications without creating uncollectable cycles in object graphs. Doing this without weak references is *very* difficult in some scenarios, and in other scenarios requires manual management of all object lifetimes (addref/release style, or having a single lifetime owner that 'deletes' an object on demand). That's the sort of obstacle that factors into a developer's choice of language and toolset. I've seen this particular concern with ES crop up in the past on real projects, and I've seen firsthand how difficult it is to avoid uncollectable cycles in a language environment without any sort of weak reference mechanism. Leaking large uncollectable cycles can have catastrophic consequences in multimedia applications and games, where those cycles might be retaining images or sounds or other huge game assets. On Thu, Nov 7, 2013 at 9:19 AM, Terrence Cole tc...@mozilla.com wrote: On 11/06/2013 07:37 PM, K. Gadd wrote: Generally speaking, all the discussions on this list about WRs so far have not suggested that there is any way to introduce WeakRefs without making GC behavior observable in some fashion
Re: Weak callbacks?
The problem is that the cycles remain uncollectable for a very long period of time, even though functionally the references don't need to be strong. On Thu, Nov 7, 2013 at 3:10 PM, David Bruant bruan...@gmail.com wrote: Le 07/11/2013 22:46, K. Gadd a écrit : That's the sort of obstacle that factors into a developer's choice of language and toolset. I've seen this particular concern with ES crop up in the past on real projects, and I've seen firsthand how difficult it is to avoid uncollectable cycles in a language environment without any sort of weak reference mechanism. Leaking large uncollectable cycles can have catastrophic consequences in multimedia applications and games, where those cycles might be retaining images or sounds or other huge game assets. The repeated use of the word cycle worries me. Cycles aren't a problem by themselves with mark and sweep, do we agree? David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Weak callbacks?
Please reread my example, events are a part of it but it is not exclusively about events. My example explicitly demonstrates the modes holding references in *both* directions, and only one of them is an event listener. You're correct that weak event listeners solve some of the problems that are usually used to justify weakrefs, but they're not the only problems. Sometimes objects really do need to interact bidirectionally without keeping each other alive :) To restate things, part of the problem here is that objects need to interact, so they need to either have references to each other or have a third party act as an intermediary. You can remove references entirely with some sort of message bus or other intermediary (interacting through opaque handles?) but at that point you've just moved all the lifetime management concerns around, and now you're manually calling addref/decref or doing things like that. Alternately, you can keep the strong references and carefully plumb 'release' code through every object that holds references, so that for example when a tab dies, it tells literally every object in the application to let go of any references to the tab. I hope the complexity inherent to *that* method is evident. Apologies if my contrived example is not clear enough for these purposes; the applications I write on a day-to-day basis do not use WRs much. I'm speaking from past experience and the things I hear from users of my compiler, and my past experience was on closed-source projects I can't easily reproduce here verbatim. To contrive a scenario that might illustrate where event listeners aren't necessarily enough: Let's say I have an entity system for a game that is modelling thousands of independent entities that interact. In this system, entity A might decide to chase after entity B, so it grabs a reference to entity B in order to chase after it. Meanwhile, entity B might be chasing after entity C, so it has a reference to entity C. Now, let's say entity C and entity B both are removed from the simulation. At this point, as long as entity A is alive, so are B and C (in GC terms) even though the latter two are not participating in the simulation. Now every place where an entity can refer to another entity has to be manually audited to ensure that 'dead' references are actually nulled out, which means you're basically doing your own GC sweeps over your heap using your own lifetime rules. On Thu, Nov 7, 2013 at 4:27 PM, Marius Gundersen gunder...@gmail.comwrote: On Thu, Nov 7, 2013 at 11:42 PM, K. Gadd k...@luminance.org wrote: I'll try and restate an example I used before. Let's say you're building a somewhat simple tab-based application, where each tab represents a different 'mode'. In this case, you need a higher level coordinating object that manages the tab bar, and it needs to own references to all of the active modes in order to manage the tabs. Similarly, each mode may need to have a reference to the coordinator in order to interact with it - like by setting the title of the tab, or opening a new tab containing another mode - and it may need to have references to other modes in order to communicate (like if one tab opens a tab containing related information). In a model like that, you can trivially end up with object cycles. All the references (going in every direction) are strong, so to successfully collect a mode you need to ensure that every reference to it from live objects is released. This is problematic because it means that, for example: If Mode A opens a new tab containing Mode B, and Mode A wants to respond to things happening in Mode B, Mode A now has to register some sort of event listener on Mode B. This means that Mode A and Mode B have now formed a strong cycle: Mode B's event listener list contains a strong reference to Mode A (to fire the event notification), and Mode A has a strong reference to Mode B in order to be able to respond to those events. Now, if you close Mode B, the coordinator gets rid of the tab and drops its strong references to Mode B - the tab is 'gone' - but there's no trivial way to ensure that everyone else holding a reference to it is dead. If multiple tabs interact in this way it's possible for a huge graph of objects to be hanging off one live tab. Eventually, if you close enough tabs you might 'free' the graph, but if you aren't careful the coordinator itself can end up keeping dead tabs alive, with things like event listener lists. In the real apps I've worked on like this, the solution was some form of weak references - making event listeners own weak self-references instead of strong self-references, so that in normal circumstances event subscriptions expire along with the subscriber, along with using weak references directly in cases like 'tab a spawns tab b' in order to ensure that you aren't keeping an object alive just to monitor it. IIRC, cycles like this are already common in some DOM scenarios
Re: Weak callbacks?
Generally speaking, all the discussions on this list about WRs so far have not suggested that there is any way to introduce WeakRefs without making GC behavior observable in some fashion. WeakRefs functionally make GC observable because when you try to get at the target of the weakref, you either get it or you don't. Once you introduce the ability to get back 'null' when asking for the target of a WR (or any similar failure case), you can use that to determine things about GC behavior. If you somehow eliminate this weakness, WRs no longer solve the problems they are intended to solve. Or at the least, they solve only a small reduced subset of the problems solved in real software via the use of weak references. Being able to access the target of the WR (and have this operation fail) is core to their value (even if finalization notifications are also used quite often). I've already argued in the past about why weak references are important, and why not having solutions for those problems will kneecap the development of web applications by either preventing certain types of software from running in the browser, or forcing implementers to write their own GCs (or entire runtime environments) inside the browser, as is done with environments like emscripten and native client. Once that becomes the solution, the ES spec is irrelevant for those applications because they have had to abandon the language. While the risk of something like this happening is still relatively low, the risk increases over time as more people begin seriously considering solutions like emscripten and nacl - we're starting to see companies ship real products using them already. If this spreads to popular reusable libraries (physics libraries, rendering libraries, etc), there's a risk that those libraries will pull new applications out of the ES realm because it's not possible to use those libraries without abandoning ES in favor of a custom GC/runtime environment. Based on the conversations thus far, a choice just has to be made between the two downsides: exposing some amount of GC internals, or making it impossible to write some subset of applications in ES. It's possible that exposing GC semantics has such catastrophic security consequences that ruling those applications out is merited. It's also possible that workarounds can be applied to reduce the harm of GC visibility (I think in the past someone - maybe Mark? - suggested that disabling cross-realm WRs would mitigate the damage considerably?) On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt oli...@apple.com wrote: On Nov 6, 2013, at 3:14 PM, Rick Waldron waldron.r...@gmail.com wrote: On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola dome...@domenicdenicola.com wrote: Thanks Mark for the education, especially on the pre- vs. post-morterm finalization distinction. I don't think I was specifically advocating for pre-mortem in my OP, since I didn't really understand the difference :P. Post-mortem finalization sounds quite reasonable. What do people think of introducing it into ECMAScript? This may be a naïve question, but how would the handler know which object/weakref had been gc'ed? You wouldn’t :) I’m kind of anti-finalisers in JS for all of the reasons people have raised - they are extremely hazardous, expose non-deterministic behaviour, etc Given our general desire to avoid exposing internal GC semantics, and the difficulty in defining observable GC behaviour (I suspect this would be a non-starter in any case), I can’t see any specification that would allow useful finalisers or WeakRefs. If MarkM has an idea for WeakRefs that don’t leak observable GC behaviour i’d love to hear, but in general i’m opposed to both them and finalisers :-/ —Oliver Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promises and Decidability in Asynchronous Error Handling
Requiring early registration prevents the use of futures as value containers; i.e. kicking off an operation and storing the Future somewhere so anyone can use it at a later date. I agree that an improved error handling policy would be very, very good to have, though. On Mon, Oct 21, 2013 at 9:40 AM, Kevin Smith zenpars...@gmail.com wrote: A well-known problem with Promises, as implemented in various Javascript libraries, is that program errors are silenced by default. Consider the following program, which simply makes an HTTP request and then prints out the HTTP response headers: fetchUri(http://someauthority.com/;).then(response = { for (let header of repsonse.heders) // Note the misspelling! console.log(header.key, header.value); }); On line 2, the property headers is misspelled, which should cause the program to report an unhandled error. Under the current Promises specification, however, the error will be silenced and the program will end happily with success. Various solutions have been proposed for dealing with this problem, such as: - Extending debugging tools so that unhandled rejections are visible through a specialized tab or view. - Using the garbage collector to determine when rejections can no longer be handled, and therefore constitute a program error. - Adding a `done` method to the promise type which propagates rejections as program errors. While each of these approaches provides a partial solution to the problem, they are ultimately inadequate because they do not address the underlying cause. The root cause of this issue is that, as currently specified, **the problem of determining whether a particular runtime error has an associated handler is Turing undecidable**. This is *not* a desirable property for an error handling mechanism to have, and it is not a design choice that can be reversed at a later date. In order to make error handling decidable, it is sufficient to require that an error handler must be attached to the promise *within a well-defined window*. One such window would be the lifetime of the currently executing user call stack. The designers of Dart have made a similar decision with their Future API. In the following document, users are instructed to register error handlers early: https://www.dartlang.org/articles/futures-and-error-handling/#potential-problem-failing-to-register-error-handlers-early A quick search on StackOverflow relating to Futures and early error handling in Dart yielded no results. This cursory evidence suggests that requiring early registration of error handlers is not a significant problem for Dart users. In my view, it would be a mistake to standardize the undecidable error handling model of current Promises design. Thanks, { Kevin } ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Non-extensibility of Typed Arrays
Did anyone address what should be done in the use case where it's necessary for information to 'tag along' with an array or typed array, for interop purposes? The existence of interior binary data objects seems to complicate this further; for example I had said that it seems like WeakMap allows attaching information to a typed array in that case even if it isn't extensible. If interior objects lose identity, though, it now becomes *literally impossible* for data to follow an instance of Uint32array (or whatever) around the runtime, which is kind of troubling. Obviously I understand *why* this is the case for interior objects. Is the meaning of an assignment to an interior object well specified? The data is copied from the source typed array into the interior object, I assume. I'm going to describe how I understand things and from that how it seems like they could work: At present when you construct a typed array it is a view over a particular buffer. You can construct an array with a size `new Uint32Array(32)` in which case a buffer is allocated for you behind the scenes; you can construct an array from a buffer + offset/size pair in order to create a view over a subregion of the buffer. In both cases, the 'array' does not actually represent or contain the data, it is merely a proxy of sorts through which you can access elements of a particular type. It is my understanding that this is the same for binary data types: you can construct a heap instance of one, in which case it has an invisible backing buffer, or you can 'construct' one from an existing buffer+offset, in which case it is more like a proxy that represents the given data type at that given offset in the buffer, and when you manipulate the proxy you are manipulating the content of the buffer. In both cases, I believe it is consistent that these objects are all 'views' or 'proxies', not actual data. The fact that you can create an instance directly creates the *illusion* of them being actual data but in every case it is possible for multiple instances to share the same backing store without sharing referential identity (via ===). In both cases, I don't believe a user should expect that attaching an expando to one object instance should modify the expandos on another object instance. Given this, it seems perfectly reasonable to be able to attach expandos to a typed array, and I've previously described why this use case is relevant (interop between compilers targeting JS, and native hand-written JS, for one). In the same sense, if typed arrays must be constructed to act as proxies for the 'interior' arrays in a binary data type, being able to attach expandos to them does not cause much harm, other than the fact that the lifetime of the expando does not match the lifetime of the underlying binary data. But this is already true for typed arrays, in a sense. I think the best way to address the confusion of expandos on interior arrays is simply non-extensibility, as has been discussed. I don't see why non-extensibility for interior arrays requires crippling the functionality of typed arrays in general, since JS already seems to have 2-3 exposed concepts in this field (seal, freeze, preventExtensions) along with query methods to find out if those concepts apply to a given object (isSealed, isFrozen, isExtensible) If interior arrays are not extensible, I should hope that Object.isExtensible for them returns false. If it were to return true when they have no expando support that would be incredibly confusing. Anyway, given all this I would propose that the optimal solution (in terms of usability, at least - can't speak for the performance consequences) is for typed arrays to be extensible by default, as they are Objects that point to underlying sequences of elements, just like Array. This gives good symmetry and lets you cleanly substitute a typed array for an Array in more cases (resizability and mixed types being the big remaining differences). In cases where extensibility is a trap for the unwary or actively undesirable, like interior objects, the instance should be made non-extensible. This allows all end user code to handle cases where it is passed an interior array or object without reducing the usefulness of typed arrays. FWIW I would also argue that a free-standing instance of any Binary Data type (that you construct with new, not using an existing buffer) should maybe be extensible by default as well, even if 'interior' instances are not. However, making binary data types always non-extensible wouldn't exactly break any compatibility or use cases, since they're a new feature - but it does mean now we have to add checks for extensibility/typeof in more cases, which is awful... (A related area where this is a big problem for me and authors of similar packages is emulating the java/C# 'getHashCode' pattern, where objects all have an associated static hash code. Implementing this often requires attaching the computed hash to the object as
Re: Non-extensibility of Typed Arrays
To me the compelling argument against using encapsulation instead of extensibility is that it breaks compatibility with existing JS code. Once you encapsulate an array, the encapsulated object no longer acts like an array and you can't use it in contexts where a normal array is expected. The ability to do python style 'quacks like an array' duck typing simply doesn't exist for arrays in JS. This is a huge problem for JSIL interop - I can't preserve type information for arrays, or expose other array features, without either breaking interop with pure JS or otherwise eating some enormous perf hit (proxies, spidermonkey's deopt from named slots on arrays, etc). Baking this limitation into the spec for typed arrays is kind of awful, but I can understand if it's absolutely necessary... Maybe WeakMap is the right solution for this? I can't remember what the performance consequences are for that use case. (Can you use an Array as a weakmap key? I forget, since it's an object-like type but it has special properties...) Note that I'm not arguing for array subclassing here, just the ability to 'bless' an array instance with extra information. Such use cases are no doubt fairly rare, even if it's possible to come up with a handful of them. I assume StructType and ArrayType will address a lot of this, but I'm not sure how I feel about having to wait for those features when (were typed arrays specced to allow named expandos) you could do this stuff in a mostly cross-browser way and ship it right now. (WeakMap fails this test since IIRC it's still only available in Firefox. :/ I love it and wish I could use it in the wild!) On Tue, Aug 27, 2013 at 3:49 PM, David Herman dher...@mozilla.com wrote: On Aug 27, 2013, at 9:47 AM, Filip Pizlo fpi...@apple.com wrote: I do. Placing named properties on arrays makes sense. Consider a matrix implemented as a Float32Array, with named properties telling you the numRows and numCols. Just one example. There are of course other ways to achieve this that don't involve patching the array object, such as building a data abstraction for matrices that has-a Float32Array, or creating a new array type with additional methods: var Matrix = new ArrayType(float32); Matrix.prototype.numRows = function() { ... } // or Object.defineProperty(Matrix.prototype, { get: function() { ... }, ... }); TA instances having no indexed expandos but allowing named ones is weird. Better to be consistent to users Consistency would imply doing what other indexed types do. Consistency arguments won't get you very far. The indexed properties of typed arrays by design act very differently from other indexed types. That's their whole reason for existence. And the other consistency dimension is between array types and struct types. Is anyone arguing that structs should also have expandos? Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Binary Data types in window context (was Some Typed Objects Confusion)
moving back onto list It might be worth doing. On the one hand, I don't really feel like these names *should* collide with anything, but it seems like the risk is kinda high... and it's a little weird seeing them in global scope and having to figure out that they're actually types for binary data and not, for example, the constructor for boolean or some sort of value type ctor. Once 64-bit signed/unsigned ints are in will there be two names for those as well? I.e. Uint64(...) produces one of the new 64-bit unsigned ints, while uint64 is the name you use when creating a StructType to specify the type of a field? If the type names used by binary data actually work as constructors to get an instance of that type, that might make it more justified for the names to be in global scope, but that seems like probably unmerited scope creep. Having the types be in a single 'BinaryTypes' namespace or something at window-level seems like it would be pretty reasonable; if you're going to be referring to types a lot you can pull them into locals, or use 'with' in a gross non-strict function (yuck yuck yuck) I assume specifying type names as strings, i.e. { field: uint32 } was considered and ruled out (it would definitely be strange to mix that with passing in actual StructType instances). -kg On Wed, Aug 21, 2013 at 10:36 AM, Dmitry Lomov dslo...@chromium.org wrote: On Wed, Aug 21, 2013 at 6:50 PM, K. Gadd k...@luminance.org wrote: Does this mean the addition of binary data to a browser defines dozens of new names in 'window' scope, like 'string' and 'boolean' and 'uint32' alongside existing names? That's kind of surprising to me (though I can understand why it might be necessary) Yes, this is where we are at now. Maybe we should pack the whole thing into a module. Dmitry On Wed, Aug 21, 2013 at 4:21 AM, Dmitry Lomov dslo...@chromium.orgwrote: string, boolean, object and any are all lowercase (we should fix the wiki) FWIW, I am already working on a new version of polyfill. It is fully ES5. Here is a pull request: https://github.com/dherman/structs.js/pull/12 - I'll merge it soon, and work more to cover everything in the proposal. Thanks, Dmitry On Wed, Aug 21, 2013 at 3:21 AM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: sorry, point 3 was actually the question about point 2 On Tue, Aug 20, 2013 at 6:20 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Uhm, just a couple of extra question about that page if/when you have time: 1. string and boolean are mentioned, but nowhere in your `struct.js` prolyfill code. Will string and boolean be accepted? 2. `Object` and `Any` are mentioned, but exported as object and any in your `struct.js` prolyfill example. W 3. Which is the right way? The reason I am asking is to be able to create code that does absolutely nothing (for performance reason) but will look like the real thing so I can start experimenting with static structures and possibly a develop VS production version of an ES3 to ES5 compatible polyfill since I believe your code won't run anywhere except in SpiderMonkey (which is OK but it's not suitable for a lightweight migration to structure like logic) Thanks. On Tue, Aug 20, 2013 at 4:55 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Awesome, thanks! On Tue, Aug 20, 2013 at 4:12 PM, David Herman dher...@mozilla.comwrote: On Aug 20, 2013, at 1:31 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: [In this page]( http://wiki.ecmascript.org/doku.php?id=harmony:typed_objects), and in the latest meeting note too, I can read both uint8 and Uint8, as example. Bug. Fixed, thanks. **The Question** How is `new StructType({x:Uint32, y:Uint32})` supposes to understand the type? `instanceof Uint32` or `typeof v === uint32` or ... both in case of `boolean` and `string` ? Neither. It tells you that the x and y fields have typeof 'number' and that their values are constrained to be integers in the range [0, 2^32). A bonus question would be: does anybody know when this stuff is planned to go out? Not a single beta/alpha channel is exposing anything at all so far. Nikhil Marathe and Niko Matsakis are actively working on the implementation for SpiderMonkey: https://bugzilla.mozilla.org/show_bug.cgi?id=578700 Dmitriy Lomov is actively working on updating the prollyfill to match the current API: https://github.com/dherman/structs.js https://github.com/dherman/structs.js/pull/12 Not sure if anyone on the V8 team (which includes Dmitriy) has started implementation but I believe they're interested. Right now Dmitriy is focused on the prollyfill and spec. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org
Re: setImmediate
Why is the slow script dialog box even relevant for setImmediate? As I understand it, setImmediate is equivalent to DoEvents in Visual Basic/Windows Forms and pumping the message loop in a normal C application. That is, you can use setImmediate to make your application run as fast as possible while still allowing the browser to pump messages, which ensures keyboard/mouse inputs are processed and the window does not get flagged as unresponsive. This is *ideal* (especially compared to setTimeout 0, which introduces the use of timers and slows everything down in this use case, and compared to requestAnimationFrame which needlessly would slave computation to vsync). People who are writing long computation loops right now that hang the browser main thread for multiple seconds can split them up with setImmediate without causing any major performance regressions. Whether or not setImmediate would increase battery usage is something you'd have to test; this isn't a case where timers would be waking the CPU up and keeping it awake, though; this is a case where *computation* would be keeping the CPU awake, and ultimately computation has to finish sooner or later. You're not going to save power just by making computation take longer unless you can ensure the CPU and other components remain in a low-power state during the computation. On Thu, Aug 8, 2013 at 1:26 PM, David Bruant bruan...@gmail.com wrote: Le 08/08/2013 22:04, Jason Orendorff a écrit : On Thu, Aug 8, 2013 at 9:40 AM, David Bruant bruan...@gmail.com wrote: Small delays between (micro)task sounds like a local maximum it's hard to get away from unfortunately :-( I think I was wrong here when it comes to microtasks. Microtasks bypass the event queue, so delaying them delays all the other messages in the queue by definition. Forcing a delay on microtasks means an irresponsive UI. What if, instead of a slow script dialog, browsers responded to microtask/setTimeout(0) abuse with gradual throttling? Well-behaved applications would get immediate setTimeout(0) callbacks. Badly behaved applications would run slowly. That's already the case with setTimeout in a way. Try: setTimeout(function f(){ setTimeout(f, 0); }, 0) You never get the slow script dialog. The 4ms clamping is here to make that code this code runs yet does not burn the CPU. Other than that, the browser with the shortest delay wins the battle, I believe. my application runs faster in X than in Y forcing Y to reduce the delay and align with X. Now that I think about it, maybe the proposal I made for microtasks [1] could work for setImmediate. setImmediate would be guaranteed to run asap (in a different task, not microtask) without clamping. The mitigation for browsers is possible via kill too-deeply-nested setImmediates (preferably before running one and not in the middle of one :-p) and telling the script if it asked to be notified. That's a version of setImmediate I would agree with as it would be a significant improvement over what we have today. David [1] https://mail.mozilla.org/**pipermail/es-discuss/2013-** August/032630.htmlhttps://mail.mozilla.org/pipermail/es-discuss/2013-August/032630.html __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: WeakRefs leading to spec-imposed memory leaks?
If memory serves, http://point.davidglasser.net/2013/06/27/surprising-javascript-memory-leak.htmlwas also complaining about a similar closure/scope leak in v8 where locals that you wouldn't expect to be retained are retained by closures in some cases. Arguably those cases just need to be fixed. Locals that aren't ever reachable from a closure being retained by the closure is definitely non-obvious and it's difficult to even identify or debug these cases with current debugging tools. JSIL has had huge memory leak issues caused by this in a few cases. Of course, I don't know how difficult it actually is to fix this. I agree that WeakRefs going in with these sorts of leaks remaining would be a big problem, but it would be worse for developers if these leaks just stuck around and kept WRs from ever getting into the language. Better to put them in and have them serve as a strong motivator for fixing those leaks for good, IMO. On Sat, Jul 27, 2013 at 8:52 AM, David Bruant bruan...@gmail.com wrote: Hi, There seems to be a consensus on bringing in WeakRefs in the language. I came around to the idea myself as some use cases seem to require it (as in: some use cases can't be achieved even with a .dispose convention like distributed acyclic garbage collection). However, I worry. Recently, some memory leaks where found in Gaia (FirefoxOS front-end). The investigation led to a subtle nested function scopes condition under which the reference to some variables are kept alive unnecessarily [1]. One of these days the SpiderMonkey folks will certainly fix this bug and will that creates 2 worlds. A before world where some objects *never* gets collected because of the bug and an after world where some of the same objects get collected. If all current major JS engines have common limitations ([1] or any other), I worry that code using WeakRefs could implicitly (and mistakenly!) rely on these common limitations and break if one of these limitation is fixed. We know the rest of the story; it involves browser competition, don't break the web and this time would put in spec to require some missed opportunities for optimization. Phrased differently, we could end up with memory leaks imposed by the spec... I understand the necessity of WeakRefs for some use cases, but I worry. David [1] https://bugzilla.mozilla.org/**show_bug.cgi?id=894971#c0https://bugzilla.mozilla.org/show_bug.cgi?id=894971#c0 __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: new Symbol(obj)
The builtin could have weak values (i.e. Symbol instances expire when no longer referenced by JS) instead of weak keys, which is not something we can currently express in JS. This would also make it possible to use strings/integers/floats as Symbol keys without leaking those Symbol instances forever. This is not something we can express in JS either. Both of these behaviors would not, as I understand it, be directly observable since keeping an old Symbol instance around (to compare with) would prevent the cached one from being collected. On the other hand, I think if you were to resynthesize the number/string used as a symbol key and make a new symbol, that might allow you to observe whether the symbol had been collected. This doesn't seem like a huge problem to me but I forget the exact reasoning why weak references were unacceptable in the past; maybe it still applies to this. On Mon, Jul 15, 2013 at 9:08 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Jul 15, 2013, at 6:49 AM, Jeremy Martin wrote: In some (most?) cases, but not all. There's already a consensus that the garbage collection semantics of WeakMaps aren't always appropriate [2]. By parameterizing the Symbol constructor, developers can create custom map/set types without the overhead of a Symbol Factory (as previously suggested by Allen). I believe this would be a useful building block for interesting and innovative custom types. [1]: https://en.wikipedia.org/wiki/Injective_function#Definition [2]: http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets An implementation of your proposal is going to have to have to internally use some wort of weak-keyed table, in practice an implementation would probably use the same GC mechanisms that are there to support WeakMap. So, I doubt there would be much performance difference between a built-in and a roll-your-own implementation. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Why is .bind so slow?
Sorry Jeff, but this is actually not the case. The performance consequences from using .bind() can be quite severe because it pollutes type information and disables fast paths. Not 'your entire application runs in the interpreter' slow, but surprisingly slow. It can even slow down code paths where .bind()/bound functions are not being used because of how inline caches and such tend to work in modern engines. The problem here isn't that 'calling a bound function is slow'; it's a more general problem that the introduction of bound functions into an existing application can make the application get slower in places where the bound functions aren't being used. I do agree with the general principle that it is not likely to be the biggest performance problem, but it's surprisingly harmful. On a related note, it would certainly be unwelcome if arrow functions had the same downsides. -kg On Sat, Jul 13, 2013 at 12:15 PM, Jeff Walden jwalden...@mit.edu wrote: On 07/12/2013 02:54 PM, Allen Wirfs-Brock wrote: Looking at it another way, if implementation haven't found it straightforward to optimize ES5 bound functions why would you expect that would have an easier time with Proxys? I'm pretty sure no implementation has seriously tried to optimize bound functions, and that that's the major reason for any slowness. I don't think there's anything fundamentally difficult about optimizing bound functions. It's just never been a priority for engines, because it doesn't show up in benchmarks and because the perf bugs for it are less pressing than other perf work is, as bound functions remain underused on the web. Chicken and egg? Sure. In the meantime, while I wouldn't currently question (as a purely pragmatic choice) avoiding bind in highly intensive code where every bit of perf matters, I do think bound functions are fast enough for the vast majority of cases. The overhead of calling a bound function will rarely be the difference between adequate and inadequate performance. Jeff ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Why is .bind so slow?
I've had some back and forth with v8 devs about this since it affects my compiler. I believe they already have open issues about it but I don't know the bug #s. In general, the problem seems to be that Function.bind creates functions that have different type information from normal functions you wrote in pure JS; they're 'special' native functions in the same fashion as say, a DOM API: document.createElement function createElement() { [native code] } function f () {} f function f() {} f.bind(null) function () { [native code] } This is important because v8 tries to gather information about callees at various call sites. Having a mix of these special and non-special functions means that the JIT is not able to make safe optimizations based on all the callers being the same type. IIRC there are also some other problems specific to v8, like it only being able to optimize Function.apply and Function.call if the .apply/.call methods are the implementations used for pure-JS functions (so bind breaks those too). I can't comment on why it's slow in SpiderMonkey (I've never asked... I should file a bug) but it is indeed the case that f.bind(null) produces a 'native code' function in SpiderMonkey, so I expect some of the same optimization consequences apply. I also expect that it is much harder for v8 and spidermonkey to inline a function that contains native code, if not entirely impossible. All of these problems, as I understand them, are completely fixable. It might be as simple as making bind return a pure-JS function instead of a native function. This is supported by the fact that a pure-JS polyfill for .bind is usually faster in my tests. In general VM authors are much more helpful when shown real world applications affected by these issues, based on my experience. They tend to ignore jsperf microbenchmarks, etc. I don't know that this could be addressed at all from a specification perspective. The only thing I can think of would be specifying that the result of Function.bind should somehow be indistinguishable from a hand-written JS function (no 'native code' in tostring, etc) but I don't think that sort of spec requirement would actually prevent any of these performance traps. Hope this helps, -kg On Fri, Jul 12, 2013 at 10:59 AM, Brendan Eich bren...@mozilla.com wrote: Allen Wirfs-Brock wrote: you might consider ticketing performance bugs against the various implementations. Right, and at most summarize with links to those issues for es-discuss. This is not a language issue, rather a quality of implementation one. /be Allen On Jul 10, 2013, at 9:16 AM, Claus Reinke wrote: The TypeScript project tries to emulate arrow functions through the _this = this pattern and keeps running into corner cases where a semi-naïve renaming is not sufficient. I have been trying to suggest using .bind to emulate arrow functions instead, but the counter-arguments are (a) .bind might not be available (supporting pre-ES5 targets) and (b) .bind is slow. The polyfill isn't the problem, but I'm a bit shocked every time someone reminds me of the performance hit for using .bind. Given that a bound function has strictly more info than an unbound one, I wouldn't expect that (I expected a bound function to be roughly the same as an unbound function that does not use this). Unless there is no special casing for the just-add-this case, and .bind is always treated as a non-standard (meta-level) call. While playing with test-code, I also found that v8 does a lot better than other engines when using an .apply-based .bind emulation. Can anyone explain what is going on with .bind, .apply and the performance hits? The TypeScript issue is https://typescript.codeplex.**com/workitem/1322https://typescript.codeplex.com/workitem/1322. My test code (*) is attached there as bind-for-arrows.html. Claus http://clausreinke.github.com/ (*) I also tried to make a jsperf test case, but the way jsperf runs the loop seems to prevent the optimization that makes v8 look good for the .apply-based bind. __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: new Symbol(obj)
I would welcome (with fanfare and parades) a new Symbol(obj) that worked for strings and integers. Such is not possible using the WeakMap shim (you'd have to detect the type of the value and have multiple dictionaries, or something, and you'd leak the symbols forever...) Of course, what that means is I'm asking for weakly cached symbols with referential identity, which means it would allow detecting garbage collections, so this is probably around the point where people chime in and say it's not possible. Oh well. :( On Fri, Jul 12, 2013 at 12:42 PM, Jeremy Martin jmar...@gmail.com wrote: Good point, that's definitely a usable solution (also a better representation of what I was attempting to describe). I'd still be interested in a less-verbose/more-efficient approach using the Symbol constructor, but it may not be a common enough scenario to justify it when a workaround does exist. On Fri, Jul 12, 2013 at 3:32 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Jul 12, 2013, at 12:14 PM, Jeremy Martin wrote: In brief: allow Symbol's to be constructed with a single parameter, with the following behavior: var obj = {}; undefined new Symbol({}) === new Symbol({}) false new Symbol(obj) === new Symbol(obj) true You can use a WeakMap to build your own object-selected Symbol factory: let known = new WeakMap; function ObjSymFactory(obj) { //handle obj === undefined however you want let sym = known.get(obj); If (!sym) { sym = new Symbol; known.set(obj,sym); } return sym; } Allen -- Jeremy Martin 661.312.3853 http://devsmash.com @jmar777 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: thisArg in Array#find and Array#findIndex
In addition to the perf savings from not having to allocate (to call bind) not needing to use bind() for cases like .find() can have beneficial effects for JITs as well. It's my understanding that at a recent point in time (maybe even still today?) functions created by bind() had the ability to deoptimize call sites in V8 and Spidermonkey in certain scenarios. If the existing design lets developers use free functions without having to use bind(), that makes it easier for them to end up in the performance sweet spot we know about when it comes to crunching data. The longer they can stay in that sweet spot and still use built-ins like find/findIndex, the better. On Wed, Jul 10, 2013 at 10:28 AM, Brendan Eich bren...@mozilla.com wrote: David Bruant wrote: I can't find it anymore, but I read a message from Mike Shaver (I think it was him) saying that these methods have been standardized after SpiderMonkey implementation without other form of rationale. Who needs this particular consistency anyway? Users generally benefit from this kind of consistency; we hear complaints about reduce/reduceRight. The perf savings is an allocation, but the cognitive load win seems more important. Telling people to use .bind (polyfilled) involves more typing and thinking. /be __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Object#extra hazard
I think at this point we have a long history of language designs where random stuff has been tacked onto the core base class (i.e. Object) that really shouldn't have gone there - hashCode/toString in Java/C#, etc - such that any proposal to put something on Object instances deserves extreme skepticism. Static methods on Object aren't nearly so bad. In this case, the problem being solved can almost certainly be solved through composition or some other design mechanism. Bolting it onto every instance of Object, even if the only universally paid cost is a reserved name on the prototype, is simply not the right solution unless the downsides of other approaches are intolerable. Which they aren't. In practice a lot of these use cases call for event subscription and broadcasting to occur through a separate coordinator ('event bus') object and not through the object in question, anyway. This addresses a bunch of reference cycle problems that are caused when you subscribe directly to an object. You don't need to look much further than the DOM for examples... On Wed, Jul 10, 2013 at 3:57 PM, Rick Waldron waldron.r...@gmail.comwrote: I don't want any of this on my Object objects. Not all objects represent something that can or should emit/publish/trigger/broadcast. For example... class Light { constructor() { // initialize Light control instance } on() { // send bits to turn Light on } off() { // send bits to turn Light off } } So what happens now? All of my Led instances have emit, trigger, once and boundTo methods that are actually useless now. No thanks. I also don't want Object.prototype.* and Object.* to suffer the same way that the [[Global]] (window) object in browsers has suffered. Give a hoot, don't pollute. Post ES6 world makes creating emitter objects trivial—so why not a blessed standard lib module that can be imported and used to extend a class declaration? import { Emitter } from @event; class Foo extends Emitter {} Easy. More inline... On Wed, Jul 10, 2013 at 3:58 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: I know but people use prefixes and unique ids for events too and I am not sure if that would work so well. Also, this is not backward compatible, or better, this is impossible to polyfill so it won't bring benefits to the current scenario. If only I could already `Object.mixin(Object.mixin({}, EventEmitter), EventTarget)` and alias those prolix names as `on()` and `off()` it would be already great but this is too much in between the DOM, behind WebIDL, and ECMAScript ... something I know already historically incompatible, that's why I've proposed new names hopefully one day (and hopefully soon) in core, something that will be inherited in current implementation in any case, as it was in my case simply polluting the `Object.prototype` with those non enumerable properties luckily inherited in hosted DOM objects too. best regards On Wed, Jul 10, 2013 at 12:46 PM, Matthew Robb matthewwr...@gmail.comwrote: You can do chainability at object define time with the sugar form: var obj = { on type1(){}, on type2(){}, on type3(){} } This is the dark days of DOM element properties as event handlers: elem.onclick... Assigning to this paves over the previous assignment, leaving no way to have multiple handlers registered for the same event type. OR add to it using one of the following options: Object.mixin(obj, { on type1(){}, on type2(){}, on type3(){} }) obj.{ on type1(){}, on type2(){}, on type3(){} } obj := { on type1(){}, on type2(){}, on type3(){} } On Wed, Jul 10, 2013 at 12:41 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: my implementation works already with `DOM` nodes and browser environment, including `window`. I've also already written an `EventTarget` mixin object but in my case I'd use that via `Object.mixin(Object.prototype, EventTarget);` 'cause almost every object I use in my logic should be observed or should emit something to some other object. Standard lib approach (a la node) works today and tomorrow. Of course Dictionaries are out of the game but that's OK, as long as it's possible to promote them later on via `Object.setPrototypeOf(dict, Object.proottype)` I find the `Object.addEventListener(obj, type, handler)` approach very boring for the simple reason that it does not make sense to use chainability there, another de-facto thing when it comes to events. It's also (subjectively) hideous. ```javascript // current eddy.js status var obj = {} .on(type1, handler1) .on(type2, handler2) .on(type3, handler3) ; ``` That's great for your use case, but I would never want this by default. Rick (snip) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___