RE: Aligning from() and map()
Agreed, index is the index of the destination where the value returned from the closure parameter will be placed. This is the right way to think about index. Using it directly on the source is at best redundant since element === collection[index]. The fact that the destination isn't available yet doesn't make the destination index useless. One use case that comes to mind is a convolution like a blur function in image processing. The index indicates the location in the destination where the newly created value is to be placed. - Rick -Original Message- From: Allen Wirfs-Brock [mailto:al...@wirfs-brock.com] Sent: Friday, December 06, 2013 4:07 PM To: Hudson, Rick Cc: Niko Matsakis; es-discuss@mozilla.org Subject: Re: Aligning from() and map() On Dec 6, 2013, at 12:18 PM, Hudson, Rick wrote: Allen 1) For the map method, the source and destination collection are the same object so the collection argument to the closure parameter identifiers both the source and destination object Not sure I'm following you here. The collection passed to the closure parameter (aka callback function) in map is the source and not the destination. As far as I can tell the destination isn't available until map returns it. Right, sorry first post of the morning. Coffee wasn't active yet. There is still a difference. With map, the source collection is the this value of the map method and has implementation level visibility of the source collection. The map method is specified to do explicit index iteration over the indices of the source collection. With the from method, the source may simply be an Iterable Iterator (an Iterator with a @@iterator method). The ultimate source of the data isn't necessarily known to the from method and since index-based iteration isn't used to access the iterator, any index passed to the closure would be a destination index. But, as you point out, the destination object isn't available to the closure. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Parallel JavaScript: exception throwing vs. sequential fallback
Parallel JavaScript: exception throwing vs. sequential fallback When a parallel method such as mapPar is called with an elemental function that prevents parallelization, for example by writing to a global, we can either throw an exception or fall back to sequential execution. The current TC39 POR is to throw an exception. I think falling back to sequential execution is the better alternative. To maintain temporal immutability and determinism the exception needs to be thrown before any global state is altered. This implies that that the elemental (callback) function needs to be instrumented to prevent writing to non-local variables before even being run once. Some JITs execute a few iterations using an interpreter in order to do gather type information. Instrumenting this code to throw before global state is modified comes at not only a performance hit but also will imposes considerable reworking of the JIT infrastructure for it to be reused to do the instrumenting. This is potentially a heavy implementation burden. The second problem is that throwing an exception prior to modifying global state will also complicates a JavaScript implementation of a sequential polyfill since such a polyfill would have to instrument the elemental function. Given that closures can easily hide aspects of code that needs to be instrumented such a polyfill is unlikely to be possible. On the other hand falling back to a sequential implementation avoids both of these problems. If and when a write to a global is detected falling back to sequential code would be straightforward. The Interpreter/JIT could run the first few iterations sequentially, checkpoint where it is in the sequential iteration space, JIT the code, including any instrumentation that is needed, run the code concurrently, and if a write to a global is detected then fall back to the checkpoint and resume sequential iterations. The semantics of Parallel JavaScript make maintaining such a checkpoint trivial. We should revisit the decision to throw an exception in light of these implementation issues and change to semantics that allow a sequential schedule to be a legal scheduling for any elemental function whether it is temporally immutable or not. -Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: Why does Array.from also take a mapFn?
I'm trying to understand this particular line. var squaredSmalls_try3 = Int16Array.from(smalls, map(v= v*v)); //the plan is for this to work. To me I would expect a complaint that map is undefined. Should map be implied? var squaredSmalls_try3 = Int16Array.from(smalls, (v= v*v)); //the plan is for this to work. Or specified var squaredSmalls_try3 = Int16Array.from(smalls, Array.map, (v= v*v)); //the plan is for this to work. - Rick -Original Message- From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Allen Wirfs-Brock Sent: Monday, June 24, 2013 3:50 PM To: Domenic Denicola Cc: es-discuss Subject: Re: Why does Array.from also take a mapFn? First, you normally want map and other iterative array functions to return the same type of collect it was applied to: var smalls = Int8Array.of(34, 78, -150, 127, -3, 12); var negatedSmalls = smalls.map(v= -v); //negatedSmalltalk should also be a Int8Array but sometimes you don't var squaredSmalls_try1 = smalls.map(v= v*v); //no good if result is Int8Array because many values will be truncated var squaredSmalls_try2= Int16Array.from(smalls.map(v= v*v)); // still no good, because intermediate array is Int8Array var squaredSmalls_try3 = Int16Array.from(smalls, map(v= v*v)); //the plan is for this to work. filter, etc. doesn't have this sort of problem because the values placed in the target array are all values that were retrieved from the source array. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: another rivertrail question
(typeError instanceof Error) is true so an implementation is free to throw typeError. It does not count as a side effect. What happens when a kernel throws an exception is not covered in the strawman. I suggest that an exception coming from within a kernel function will result in an exception being thrown from the high level ParallelArray method. If more than one kernel throws an exception the ParallelArray method is free to choose which one is thrown to its caller. -Rick From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Norm Rubin Sent: Friday, April 05, 2013 8:54 AM To: es-discuss@mozilla.org Subject: another rivertrail question In an elemental function does throwing an error, count as a side effect? For instance V2 = new Array(10, function(){return 23} ,14) V1 = ParallelArray(14,12,10) V1.map( function(e,i) { var temp = array[e-12] = v2[i].toFixed() ; ... }) Since the toFixed will throw a type error when i =1, and a range error when e = 10 If this is a side effect, then it is not an elemental function and should throw Error, not typeError or rangeError This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: parallel map and dot product
In this case it is the same as with a normal array. function dotProduct(v1, v2) { return v1.map(function (e, i) {return e*v2[i];}).reduce(function (a, b) {return a+b;}); } -Rick From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Norm Rubin Sent: Thursday, April 04, 2013 2:31 PM To: es-discuss@mozilla.org Subject: parallel map and dot product I've started to read through the parallel JavaScript proposal and have a novice question How would you write a dot product Given: P1 = parallelArray(1,2,3) P2 = ParallelArray(4,5,6) We want to compute 1*4 + 2*5 + 3*6 As far as I can tell, you need a reduce to do the sums, so you first need to construct P12 = ParallelArray(1*4, 2*5, 3*6) Is there a way to generate this using map? This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: memory safety and weak references
This brings up another interesting point. Do WeakRefs change a compiler's liveness analysis? This could complicate some apparently useful optimizations. { var x = new Something(); someWeakRef.set(x); // Is x dead? (yes) Is x required to contribute to the root set? (I hope not.) gc(); someWeakRef.get() // null or foo? ... } -Rick For the optimization see @inproceedings{Agesen:1998:GCL:277650.277738, author = {Agesen, Ole and Detlefs, David and Moss, J. Eliot}, title = {Garbage collection and local variable type-precision and liveness in Java virtual machines}, booktitle = {Proceedings of the ACM SIGPLAN 1998 conference on Programming language design and implementation}, series = {PLDI '98}, year = {1998}, isbn = {0-89791-987-4}, location = {Montreal, Quebec, Canada}, pages = {269--279}, numpages = {11}, url = {http://doi.acm.org/10.1145/277650.277738}, doi = {10.1145/277650.277738}, acmid = {277738}, publisher = {ACM}, address = {New York, NY, USA}, } From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Oliver Hunt Sent: Monday, April 01, 2013 4:37 PM To: Marius Gundersen Cc: es-discuss discussion Subject: Re: memory safety and weak references There are numerous problems with weak references and primitives, mostly revolving around the ability to regenerate a primitive, e.g. someWeakRef.set(foo) gc() var something = foo someWeakRef.get() // null or foo? vs. someWeakRef.set(foo) var something = foo gc() someWeakRef.get() // null or foo? vs. someWeakRef.set(foo) var something = fo something += o gc() someWeakRef.get() // null or foo? And of course all this just becomes worse for numeric primitives -- All existing engines use tagged values for some set of numeric values, and can also end up with the same value stored in different ways. V8 (at least in 32bit) gc allocates doubles, but not a subset of integers, this means that if you get the value 1 as a double then it might be gc'd and so the weak ref could go away, but if it were in the tagged int form it would not. JSC doesn't immediately intern strings, but over time duplicates do get merged, at which point weakness starts acquiring odd behaviour. Because off the implicitly shared heap in different pages this may even be exploitable as a way to find out information about other pages (essentially the weak reference to a primitive allows a side channel for determining content of other pages that you would not otherwise have access to) This means that any consistent semantic for primitives results in useless behaviour - either the weak ref has to be (essentially) strong on primitives, or be cleared on ever gc() regardless of liveness of other references. --Oliver On Apr 1, 2013, at 1:22 PM, Marius Gundersen gunder...@gmail.commailto:gunder...@gmail.com wrote: This seems to be more a problem with the garbage collector than with weak references. If I understood it correctly, any double value can look like a pointer, and the garbage collector will check what it is pointing at. To me this seems like a source for memory leaks. This problem exists even without weak references (or weak iterable maps/sets); the weak references just makes it observable. Does this mean the main reason weak references (or, again, weak iterable maps/sets) are not to be implemented is because of a bug in the garbage collector of popular JS enginges? As noted earlier, the implementation of the garbage collector is not specified in the ecmascript standard, so this is a problem with implementors, not with the specification. Again, I'm far from an expert on GC or JS implementations (and would love a simplified explanation if I have misunderstood the problem), but this seems less like a problem with weak references, and more like a problem with specific implementations of GCs. Marius Gundersen On Fri, Mar 29, 2013 at 3:47 AM, Oliver Hunt oli...@apple.commailto:oli...@apple.com wrote: On Mar 29, 2013, at 7:36 AM, David Herman dher...@mozilla.commailto:dher...@mozilla.com wrote: On Mar 27, 2013, at 4:52 AM, Sam Tobin-Hochstadt sa...@ccs.neu.edumailto:sa...@ccs.neu.edu wrote: On Tue, Mar 26, 2013 at 11:44 PM, Oliver Hunt oli...@apple.commailto:oli...@apple.com wrote: That said I believe that this does kill any dreams i may have had w.r.t primitive-keyed WeakMaps, kudos to MarkM. Wouldn't a primitive-keyed WeakMap just be a strong Map for those keys? And therefore immune to any GC attacks? Indeed, and also deeply misleading (a weak map with strongly held entries?), which is why I argued that WeakMap should disallow primitive keys. Oliver-- can you clarify what you were hoping for? I was dreaming of primitive keys, i was convinced in an earlier meeting of the problems that they would cause, but this security problem is a nail in the coffin :-/ Dave ___
RE: memory safety and weak references
If the compiler can prove x does not escape the block and it is not used again then it is dead and the compiler is free to reuse the stack slot holding the last reference. So I am arguing that x = null; is not required to kill x. If we agree on that then I think we agree that someWeakRef.get(); is allowed to return null. - Rick -Original Message- From: Brendan Eich [mailto:bren...@mozilla.com] Sent: Monday, April 01, 2013 5:56 PM To: Hudson, Rick Cc: Oliver Hunt; Marius Gundersen; es-discuss discussion Subject: Re: memory safety and weak references Hudson, Rick wrote: This brings up another interesting point. Do WeakRefs change a compiler's liveness analysis? Yes, of course. This could complicate some apparently useful optimizations. { var x = new Something(); someWeakRef.set(x); // Is x dead? (yes) Is x required to contribute to the root set? (I hope not.) You dind't kill x yet. Did you forget x = null; here? gc(); someWeakRef.get() // null or foo? If x = null; happened before gc() then null else the original ref. /be ... } ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: memory safety and weak references
Didn't mean to imply that one is required to use an optimization. I just wanted to make it clear that one could. -Rick From: Oliver Hunt [mailto:oli...@apple.com] Sent: Monday, April 01, 2013 6:18 PM To: Hudson, Rick Cc: Brendan Eich; Marius Gundersen; es-discuss discussion Subject: Re: memory safety and weak references On Apr 1, 2013, at 3:12 PM, Hudson, Rick rick.hud...@intel.commailto:rick.hud...@intel.com wrote: If the compiler can prove x does not escape the block and it is not used again then it is dead and the compiler is free to reuse the stack slot holding the last reference. So I am arguing that x = null; is not required to kill x. That semantic would mean that the interpreter would need to do escape analysis, and then the moment a variable became dead it would be required to clear it, even if it did not need that slot for anything else. The world is filled with papers on ways to reduce the conservatism of a GC, but you have to balance the cost of work required for that increased conservatism against the win you might get from reduced liveness. But all of this is kind of moot, as weak refs are by definition going to have some degree of non-determinism w.r.t liveness, and the initial discussion was of weak refs to primitives which have their own, completely separate problems (as was already covered) --Oliver ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: Observability of NaN distinctions — is this a concern?
jussi.kallioko...@gmail.com wrote: That's just because ES has had no notion of bits for floating points before. Other than that, ES NaN works like IEEE NaN, e.g. Some background about the latest GLS spec and IEEE NaNs from http://www.opengl.org/registry/doc/GLSLangSpec.4.20.11.clean.pdf Section 4.1.4 states As an input value to one of the processing units, a single-precision or double-precision floating-point variable is expected to match the corresponding IEEE 754 floating-point definition for precision and dynamic range. Floating-point variables within a shader are also encoded according to the IEEE 754 specification for single-precision floating-point values (logically, not necessarily physically). Section 4.7.1 goes on to provide a detailed list of reduced (from IEEE 754) precision requirements for single precision floats and then states the following: The precision of double-precision operations is at least that of single precision. 4.7.1 also sets up the requirements of operations to produce NaNs as follows: NaNs are not required to be generated. Support for signaling NaNs is not required and exceptions are never raised. Operations and built-in functions that operate on a NaN are not required to return a NaN as the result. So any statement that the GLS spec follows IEEE 754 treatment of double precision is only a statement about input values. - Rick -Original Message- From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Andreas Rossberg Sent: Tuesday, March 26, 2013 6:40 AM To: Oliver Hunt Cc: Mark S. Miller; Brendan Eich; es-discuss Subject: Re: Observability of NaN distinctions — is this a concern? I'm with Dave and Oliver. Worrying about the performance cost of NaN normalisation has a strong smell of premature micro optimisation. The one branch per float store, whose cost should be amortised by branch prediction when frequent, seems very unlikely to be measurable compared to everything else going on when executing JavaScript. As for the this is not a common problem argument, use cases should only trump principles if the cost is unbearable. /Andreas On 26 March 2013 09:29, Oliver Hunt oli...@apple.com wrote: On Mar 26, 2013, at 9:12 PM, Jussi Kalliokoski jussi.kallioko...@gmail.com wrote: That's just because ES has had no notion of bits for floating points before. Other than that, ES NaN works like IEEE NaN, e.g. 0/0 === NaN // false isNaN(0/0) // true That's true in any language - comparing to NaN is almost always defined explicitly as producing false. You're not looking at bit patterns, here so conflating NaN compares with bit values is kind of pointless. We need to stop raising this causes performance problems type issues without a concrete example of that problem. I remember having to work very hard to stop WebGL from being a gaping security hole in the first place and it's disappointing to see these same issues being re-raised in a different forum to try and get them bypassed here. Before saying security hole, please elaborate. Also, when it comes to standards, I think change should be justified with data, rather than the other way around. Done. You'll have to do better than that. ;) Ok, I'll try to go over this again, because for whatever reason it doesn't appear to stick: If you have a double-typed array, and access a member: typedArray[0] Then in ES it is a double that can be one of these values: +Infinitity, -Infinity, NaN, or a discrete value representable in IEEE double spec. There are no signaling NaNs, nor is there any exposure of what the underlying bit pattern of the NaN is. So the runtime loads this double, and then stores it somewhere, anywhere, it doesn't matter where, eg. var tmp = typedArray[0]; Now you store it: typedArray[whatever] = tmp; The specification must allow a bitwise comparison of typedArray[whatever] to typedArray[0] to return false, as it is not possible for any NaN-boxing engine to maintain the bit equality that you would otherwise desire, as that would be trivially exploitable. When I say security and correctness i mean it in the can't be remotely pwned sense. Given that we can't guarantee that the bit pattern will remain unchanged the spec should mandate normalizing to the non-signalling NaN. --Oliver Cheers, Jussi Cheers, Jussi --Oliver Allen /be On Mar 25, 2013, at 4:33 PM, Kenneth Russell k...@google.com wrote: On Mon, Mar 25, 2013 at 4:23 PM, Brendan Eich bren...@mozilla.com wrote: Allen Wirfs-Brock wrote: On Mar 25, 2013, at 4:05 PM, Brendan Eich wrote: Allen Wirfs-Brock wrote: BTW, isn't cannonicalization of endian-ness for both integers and floats a bigger interop issue than NaN cannonicalization? I know this was discussed in the past, but it doesn't seem to be covered in the latest Khronos spec. Was
RE: Pure functions in EcmaScript
Function purity, while an interesting concept, probably isn't as important as the function being associative. Our work with Parallel EcmaScript (aka River Trail) http://wiki.ecmascript.org/doku.php?id=strawman:data_parallelism has shown that for a useful set of kernel functions the compiler can conservatively determine that a function does not modify non-local variables. We have found no need for function annotation, instead if one passes a function to a ParallelArray method we trust but verify that it modifies only local variables. Beyond this check we do not attempt to prove that a function is associative. The results are guaranteed only to be the result of some ordering and never return an out of thin air value. Floating point anomalies aside, if the function is associative the result will be deterministic. - Rick -Original Message- From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Brendan Eich Sent: Wednesday, November 28, 2012 4:48 PM To: Axel Rauschmayer Cc: es-discuss Subject: Re: Pure functions in EcmaScript Axel Rauschmayer wrote: Would returning NaN be impure (apart from running the risk of it having been changed to something different, globally)? You can't say apart from..., that's exactly the risk. It could be replaced with a global getter that has effects. Isolating a pure function to a sandbox or prepared global environment saves this, but then the function's pure annotation can't be enough to express what's required. /be On Nov 28, 2012, at 21:35 , Oliver Hunt oli...@apple.com mailto:oli...@apple.com wrote: On Nov 28, 2012, at 12:25 PM, Waldemar Horwat walde...@google.com mailto:walde...@google.com wrote: On Wed, Nov 28, 2012 at 5:39 AM, Marius Gundersen gunder...@gmail.com mailto:gunder...@gmail.com wrote: On Wed, Nov 28, 2012 at 1:20 PM, Andreas Rossberg rossb...@google.com mailto:rossb...@google.com wrote: Second, due to the extremely impure nature of JavaScript, there aren't many useful pure functions you could even write. For example, your 'sum' function is not pure, because the implicit conversions required by + can cause arbitrary side effects. Functions passed to the array methods map, reduce, filter, etc would be good candidates for pure/side-effect-free functions. These functions shouldn't alter any state; they should only return a new value based on the parameter they were sent. You haven't addressed Andreas's point: Almost any function you write is nonpure, including your sum example. As a fun exercise, go ahead and write a pure version of your sum example. Waldemar Here you go: function sum(a, b) { var undefined; switch (typeof a) { case number: case string: break; default: return +undefined; } switch (typeof b) { case number: case string: break; default: return +undefined; } return a + b; } ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Dr. Axel Rauschmayer a...@rauschma.de mailto:a...@rauschma.de home: rauschma.de http://rauschma.de twitter: twitter.com/rauschma http://twitter.com/rauschma blog: 2ality.com http://2ality.com ___ 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: `free` operator
Another performance killing but valuable heap debugging tool, implementable if you have a GC write barrier that covers all pointer writes, is to have the write barrier trace any and all writes/overwrites of the pointer to the traced object. It isn't magic and the GC has to also trace the object as it is moved about but it is a step in the right direction and a tool I have used to debug GC implementations. This type of functionality should be part of the debugger / software development environment and not part of the language, performant runtime, or ES standard. - Rick -Original Message- From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Brendan Eich Sent: Sunday, October 28, 2012 4:49 PM To: David Bruant Cc: es-discuss Subject: Re: `free` operator Of course we are not going to add *unsafe* manual memory management to JS. No need to worry about that! Isaac proposed safe yet horribly inefficient memory management, whereby any unwanted strong refs are found (by a global scan) and then nulled or set to undefined. This is bad for the reasons given on the thread, but also because it requires a full GC in general. Safe and efficient manual memory management is a feature of Rust and other languages which range from Research to (at best) Advanced Technology, and which seem to require fancy type/ownership systems. As a debugging tool, something like Alex's assertFree (of course, you couldn't have a weak ref to pass in, so maybe assertSingleRef is a better name) could be done. Again, in some (many high performance) implementations, it would require a full mark/sweep GC. So it is a debug-build or debug-mode only tool, not to be used lightly. What I did years ago as a debugging tool in SpiderMonkey, which I believe survives in the JS_DumpHeap C API, is along these lines. Rather than null any leaky paths to cover up the bug, it dumps all paths by which the allegedly single-ref (or just mysteriously still-alive) GC-thing-to-find that you pass in as an optional parameter still is connected to the graph of rooted live things. The path names are formed by property names with unambiguous or sufficiently unlikely separators. Internal strong refs (e.g., roots in native data structures held as opaque or private parts of a JS object, e.g. a DOM object peering a C++ struct or class instance) may be given constant-string names when made strong (rooted). Usually when debugging a leak, getting the set of strong-ref paths leads quickly to progress in fixing the bug. /be David Bruant wrote: 2012/10/26 Isaac Schlueter i...@izs.me mailto:i...@izs.me (...) We've got some band-aids in place in the node http.js file to prevent parser leaks. A more forcible free() method would have made it much easier. The long-term solution is to rewrite the program (...) So you're suggesting that a language-level feature with abusive authority introducing use-after-free bugs (and maybe others) should be included to solve short-term problems? Yehuda's action at a distance complaint is definitely a valid concern. However, note that an object can't be freed unless you have a reference to the object. Everyone has a reference to built-ins so a bug or an attacker could free built-ins. Thus, any code that would set my reference to undefined could only do so if it was also capable of mutating the object in any other way (adding/removing properties, etc.) So, we already have this: function () { // acquire a ref from some external code // no way of knowing what else is sharing this object var x = func() x.foo = 'bar' // other code... doAnotherThing() // not guaranteed! assert(x.foo === 'bar') } With non-configurable properties and making objects non-extensible, you have a way to prevent this, a way to protect your objects from action at a distance. Even proxies are required to respect some invariants for the sake of application securability. The free operator you're proposing cannot be protected against. Anyone can release any object it has a reference to without the object creator (or the other object reference holder) having their word to say to prevent it. That's unbalanced. Whenever you have a reference to an object that is shared with some other code, there's the potential for action at a distance. The proposal here is to make that action a bit more powerful. I don't agree that it's necessarily a problem in production. We free objects in other languages all the time. I agree with you, C and C++ are absurdly unsafe languages. No wonder double free and use after-free bugs are so common! As the rumor goes, use-after-free bugs lead to security issues sometimes [1]. Really not an example to follow in my opinion. What do you think about the revokable proxy solution? I agree it's less sexy than a
RE: Function#fork
Besides web workers there are two straw man proposals that address adding parallelism and concurrency to JavaScript. http://wiki.ecmascript.org/doku.php?id=strawman:data_parallelism and http://wiki.ecmascript.org/doku.php?id=strawman:concurrency. The Parallel JavaScript (River Trail) proposal has a prototype implementation available at https://github.com/rivertrail/rivertrail/wiki. You should be able to implement your example's functionality using this API. The latest HotPar https://www.usenix.org/conference/hotpar12/tech-schedule/workshop-program had two interesting papers Parallel Programming for the Webhttps://www.usenix.org/conference/hotpar12/parallel-programming-web https://www.usenix.org/conference/hotpar12/parallel-programming-web and Parallel Closures: A New Twist on an Old Idea https://www.usenix.org/conference/hotpar12/parallel-closures-new-twist-old-idea These projects each address some important part of the general problem of adding parallelism and concurrency to JavaScript. Feedback is always appreciated. -Rick From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Jussi Kalliokoski Sent: Monday, September 24, 2012 8:44 AM To: es-discuss Subject: Function#fork Hello everyone, I've been thinking a lot about parallel processing in the context of JavaScript, and this is really a hard problem. I'm very curious to hear what everyone's opinions are about it's problems and so forth, but I don't think an open question like that will give very interesting results, so I have an example problem for discussion (while it seems like a bad idea to me, and unlikely to ever get to the language, what I want to know is everyone's reasoning behind their opinions whether it's for or against). What if we introduce Function#fork(), which would call the function in another thread that shares state with the current one (how much state it shares is an open question I'd like to hear ideas about, but one possibility is that only the function arguments are shared) using a similar signature to Function#call except that the first argument would be a callback, which would have error as its first argument (if the forked function throws with the given arguments, it can be controlled) and the return value of the forked function as the second argument. * What are the technical limitations of this? * What are the bad/good implications of this on the language users? * Better ideas? * etc. I have a detailed example of showing Function#fork in action [1] (I was supposed to make a simplified test, but got a bit carried away and made it do parallel fragment shading), it uses a simple fill-in for the Function#fork using setTimeout instead of an actual thread. Cheers, Jussi [1] https://gist.github.com/3775697 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: [[strawman:data_parallelism]] |this| and fat arrows
Hey Mark, You asked How/why might including index and the array itself distract the programmer from parallel thinking? If we present index as a location and not as the nth invocation of kernel function then we are fine. Array.map overloads index to serve both purposes. My concern is that if we are too close to Array then programmers will assume we are the same and the same sequential semantics will hold. There is nothing inherently non-parallel about a location. You are correct that we are talking more about programmer psychology, art, and pedagogy and there is no formal technical reason to go either way. While passing 3 arguments might be more expensive than passing one in today's implementations there are probably compiler optimizations that can ameliorate the effects. Let's look closely at the change you are suggesting on a very simple map invocation. function add1(element) {return element+1;} strawmanPA.map(add1); alternatePA.map(add1); OK, JavaScript's argument passing semantics mean no difference for the common case where the result is dependent upon just the element. The alternate is even upwardly compatible. Now let's consider a typical geometric decomposition function like a vector blur. function blurStrawman(index, array) { if (index 1) return array[index]; return (array[index]+array[index-1])/2; } function blurAlternate(element, index, array) { if (index 1) return element; return (element+array[index-1])/2; } strawmanPA.combine(blurStrawman); strawmanPA.map(blurAlternate); OK, blurAlternate again seems reasonable. I've played with other codes and I'm finding it increasingly hard to argue against your suggestions for arrays. Future proofing the cases where we might want to extend ParallelArray to objects seems fine since JavaScript blurs field names and indices allowing for index to have a reasonable meaning in the context of objects. Unless someone else speaks up I'll drop combine and change map and filter so the kernel function takes element, index, array. Cheers, - Rick -Original Message- From: Mark S. Miller [mailto:erig...@google.com] Sent: Friday, June 15, 2012 6:06 PM To: Hudson, Rick Cc: es-discuss Subject: Re: [[strawman:data_parallelism]] |this| and fat arrows On Fri, Jun 15, 2012 at 11:35 PM, Hudson, Rick rick.hud...@intel.com wrote: Hey Mark, ParallelArray and index are left out because of our desire to provide a few good methods that help/force programmers to think about parallel algorithms and not just speeding up sequential algorithms. Array map is really just syntactic sugar for for loops and invites thinking that depends on order. For ParallelArray map we felt that the value was the semantically important thing and the user should not be distracted by the index. Not having index available is one step towards thinking in more parallel ways. Hi Rick, the claim made in the paragraph above seems to be the core argument. I respect the kind of argument you're making -- programmer psychology is important, and it is our responsibility as language designers to take it into account, and to help steer programmers towards certain ways of thinking about the problem and away from others. Sometimes these psychological issues have no corresponding formal basis, but are still important nevertheless. Arguments by non-psychologists like us about psychology can often be fuzzy, but this does not relieve us of responsibility of taking these into account. However, I don't have any intuition that supports the specific claim. Let's take map specifically. How/why might including index and the array itself distract the programmer from parallel thinking? First, do we agree that there's no formal problem, and the issue is only psychology? If so, perhaps you could provide some examples that would help illustrate the psychological issue you have in mind? At this point, I just don't get it. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: [[strawman:data_parallelism]] |this| and fat arrows
Hey Mark, ParallelArray and index are left out because of our desire to provide a few good methods that help/force programmers to think about parallel algorithms and not just speeding up sequential algorithms. Array map is really just syntactic sugar for for loops and invites thinking that depends on order. For ParallelArray map we felt that the value was the semantically important thing and the user should not be distracted by the index. Not having index available is one step towards thinking in more parallel ways. In situations where index is more semantically important than the value we provide the method combine. Here we pass the ParallelArray and the index and not the value to the kernel function. A blur function that averages the values surrounding some location would naturally use combine. The documentation encourages the programmer to think of index as the _destination_ of the value the kernel function returns. Again the intent is to try and break away from sequential thinking. Filter is like combine, it gets the ParallelArray and the index and allows filtering based on location. If one accepts the above map/combine arguments then one could make a reasonable argument that there should be a filter based on value and a filter based on location. (Thanks you've forced me to think about this again.) The other methods have less use for index. Reduce) we agree that passing in the index doesn't make sense. Scan) has the same problems with index that reduce has. Scatter) takes an array of destination indices and a 2 arg conflict function. The index of both of the source elements isn't always available so it doesn't make sense here either. Not passing in the ParallelArray was a tougher decision. We really liked the way we had |this| bound to the ParallelArray since it made composition / nested parallelism straight forward and natural. With the exception of combine and filter the programmer has to arrange for the ParallelArray to be available in order to do composition. I think a clean break from high order Array methods is the way to go here, syntactically similar forms with semantically different meaning is worth avoiding. - Rick Guy Steele Language design is as much the art of what to leave out as what to put in. -Original Message- From: Mark S. Miller [mailto:erig...@google.com] Sent: Thursday, June 14, 2012 7:32 PM To: Hudson, Rick Cc: es-discuss Subject: Re: [[strawman:data_parallelism]] |this| and fat arrows Hi Rick, Even without =, I think this is an improvement to the API overall, as it makes it more similar to the corresponding array methods. However, I do not see the problem with making it much more similar. I agree regarding reduce and reduceRight, but fortunately, these already violate the general pattern for the other higher order array methods -- in that they call their callbackfn with this always bound to undefined. In retrospect, I wish we had called the existing function reduceLeft so yours could be called simply reduce and have the name difference suggest the lack of order. Regarding the others, the general pattern from the ho array methods is array.foo(callbackfn, possible-other-args, optional-this-arg) calls back callbackfn(value, index, array, this-arg-or-undefined) I wish that the optional-this-arg had been omitted from ES5, but for the sake of compat with the Prototype library and other implementations of these methods, I lost that argument. In retrospect I agree with that decision, even though I still believe that the this-arg has net negative value. By the same reasoning, I think you should follow this pattern as well except when there's a good argument not to. For reduce you make a good argument. Further comments inline below. On Fri, Jun 15, 2012 at 4:27 AM, Hudson, Rick rick.hud...@intel.com wrote: Proposed change to [[strawman:data_parallelism]] The ParallelArray methods map, combine, reduce, scan, scatter, and filter, each take a kernel function as an argument. Within this kernel function |this| is currently bound to the ParallelArray. This was natural and non-controversial I disagree that it was non-controversial -- I argued against it on compat grounds at the time. But I agree with your point that = makes that old design even less viable. as long as we used the function(){..} form which did not restrict how |this| was bound and explaining the semantics in terms of call or apply was perfectly reasonable. = is likely to change that. =, as proposed, enforces a lexical |this| and is semantically different than the function () {..} form. Going forward we expect folks to use the = form more than the function form. For the most part we will be leaving the kernel signatures as they are except that we will no longer bind |this| to the ParalleArray is inside a kernel function. Instead |this| will be bound in accordance to existing JavaScript specifications and [[strawman:data_parallelism
RE: Use cases for WeakMap
This is all a bit off topic but performance does matter and folks seem to be underestimating the wealth of community knowledge that exists in this area. Who underestimates? Sorry, this wasn't meant to slight anyone. I have spent a career standing on the shoulders of Allen and his colleagues. My respect should not be underestimated. Interesting pointer. -Rick From: Brendan Eich [mailto:bren...@mozilla.com] Sent: Monday, May 16, 2011 6:44 PM To: Hudson, Rick Cc: Allen Wirfs-Brock; Oliver Hunt; Andreas Gal; es-discuss Subject: Re: Use cases for WeakMap On May 16, 2011, at 2:46 PM, Hudson, Rick wrote: This is all a bit off topic but performance does matter and folks seem to be underestimating the wealth of community knowledge that exists in this area. Who underestimates? A bunch of us are aware of all this. Allen certainly knows all about it, and we've been talking shop with him for years, long before he joined Mozilla :-P. I recall a conversation like this one about sparse hashcode implementation with Allen, Lars Thomas Hansen (then of Opera), and Graydon Hoare from four or five years ago... http://wiki.ecmascript.org/doku.php?id=proposals:hashcodes (check the history) However, in this thread, the issue is not optimizing hashcode or other metadata sparsely associated with objects. That's a good thing, implementations should do it. Having the hashcode in the object wins, compared to having it (initially) in a side table, but who's counting? The issue under dispute was neither sparse hashcode nor sparse fish property association, where the property would be accessed by JS user code that referenced the containing object itself. Rather, it was whether a frozen object needed any hidden mutable state to be a key in a WeakMap. And since this state would be manipulated by the GC, it matters if it's in the object, since the GC would be touching more potentially randomly distributed memory, thrashing more cache. So far as I can tell, there's no demonstrated need for this hidden-mutable key-in-weakmap object state. And it does seem that touching key objects unnecessarily will hurt weakmap-aware GC performance. But I may be underestimating... :-/ /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Concerns about weak refs and weak maps.
I have concerns about weak refs and weak maps, one concern related to usability, one related to performance bugs, and another other related to changing the complexity of the GC algorithm. Usability Weak maps act as a GC API and in doing so violate GC's greatest strength: the user does not have to be concerned with memory management. Since the user can never observe that a key/value pair has been deleted, weak maps are much better than weak refs but they still seem capable of causing hard to diagnose and fix performance bugs related to memory pressure and the particular GC implementation. GC implementation Software stacks on multicores will need GCs to become increasingly concurrent and latency free. Weak maps cause concurrent GCs and additional mutator synchronizations. While a concurrent GC already has to do some synchronization, each additional synchronization point impedes scalability. My concern is that the number of synchronization points might be proportional to the number of k, v pairs in the weak maps (see below). GC Complexity Another potential performance bug is that the complexity of the Abstract GC Algorithm at http://wiki.ecmascript.org/doku.php?id=harmony:weak_maps appears to be O(n**2), since each loop may only discover a single retained key k from (k,v) whose walk of the related value v discovers only a single unretained k. This would then be repeated and require rescanning all the weak maps in the each of the following iterations. Concurrent GCs would probable require one or more mutator synchronizations at each iteration. My sense is that the value of a simple efficient concurrent GC and reduced latency is higher than the value of weak maps so weak maps should not be part of the standard. - Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: Concerns about weak refs and weak maps.
Hi Brendan, I think we all agree that EcmaScript, the language, should not contain threads with shared memory constructs such as locks or transactions. We seem to disagree as to whether EcmaScript, the implementation, should be multithreaded. If bridge builders, compiler writers, GC implementations, need better (non-application visible) tools then running their tools concurrently seems the way forward. Web workers that share immutable heap object behind a message passing façade could provide reasonable performance without changing the (HTML5) standard. Optimizers running in a separate thread also seem like a good idea. Moving the scans of weak maps into a stop the world GC only makes the GC more intrusive while removing the application writers ability to optimize their applications. In the GC literature 50 milliseconds latency is considered the upper bound if one wishes to provide an acceptable client experience. 10 milliseconds is what one wants for a game experience. This is increasingly hard to achieve with a stop the world collector as the memory foot print grows while CPU speed does not. In the long run I believe that EcmaScript will not be able to compete with other languages in providing highly responsive client side applications without a concurrent GC. But to answer your direct question: If you remove the concurrent GC concern, then what is your sense? GC latency will increase as memory footprint and use of weak maps increases. Large application using weak maps will have performance bugs that will end up on the GC implementer's desk where they will be hard to diagnose and fix. Perhaps if folks talk privately to the top half dozen Java GC implementers EcmaScipt might be able to avoid some of their pain. - Rick From: Brendan Eich [mailto:bren...@mozilla.com] Sent: Thursday, October 28, 2010 2:39 PM To: Hudson, Rick Cc: es-discuss; Andreas Gal Subject: Re: Concerns about weak refs and weak maps. On Oct 28, 2010, at 2:10 PM, Hudson, Rick wrote: I have concerns about weak refs and weak maps, one concern related to usability, one related to performance bugs, and another other related to changing the complexity of the GC algorithm. Hi Rick, your comments are on target, but I'll differ on some fine points below. Thanks for writing. Usability Weak maps act as a GC API and in doing so violate GC's greatest strength: the user does not have to be concerned with memory management. Since the user can never observe that a key/value pair has been deleted, weak maps are much better than weak refs but they still seem capable of causing hard to diagnose and fix performance bugs related to memory pressure and the particular GC implementation. This is all true, but developers are already concerned with memory management. GC is good, I like it, but it is not and never will be perfect (enough). Even V8 is facing criticism in its nodejs.orghttp://nodejs.org embedding, for among other things having too-small heap limits. Node users are retracing the JVM user footprints and asking for an explicit library call, gc(), to force collection. So weakmaps can't be the breaking point that throws concern over memeory management via GC into users' faces. It's an issue on the client side too, already (and for many years, mostly due to cycles crossing through the DOM, which is under separate, often ref-counted, management, back to JS via the global object containing a closure capturing its environment, including document). Plus, weakmaps give JS bridge-builders and compiler/runtime writers a needed tool, without which the only options are too costly (linear search of an array matching object reference identity) and leak-prone (strong references only). GC implementation Software stacks on multicores will need GCs to become increasingly concurrent and latency free. Weak maps cause concurrent GCs and additional mutator synchronizations. While a concurrent GC already has to do some synchronization, each additional synchronization point impedes scalability. My concern is that the number of synchronization points might be proportional to the number of k, v pairs in the weak maps (see below). Browsers do not multithread JS, the language has no such execution model. More, it won't get one. Nodejs uses a single thread for all requests, requiring continuation passing style coding. There are alternatives, along Erlang lines, but they do not involve shared mutable state. So no global, concurrent GC is in the cards, on client or server -- my best projection (and strong advice!). GC Complexity Another potential performance bug is that the complexity of the Abstract GC Algorithm at http://wiki.ecmascript.org/doku.php?id=harmony:weak_maps appears to be O(n**2), since each loop may only discover a single retained key k from (k,v) whose walk of the related value v discovers only a single unretained k. This would then be repeated and require rescanning all