Re: Weak callbacks?

2013-11-08 Thread Jason Orendorff
On Thu, Nov 7, 2013 at 6:40 PM, K. Gadd k...@luminance.org wrote:
 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.

But if you were to rely on weak references for a use case like this,
you'd nondeterministically get strange behavior. Entity A will be
chasing something that is not in the simulation, until GC happens and
it fixes itself.

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

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.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Weak callbacks?

2013-11-08 Thread David Bruant

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?

2013-11-08 Thread Mark S. Miller
Please try -- such experiments are interesting. But even if this experiment
is successful, I hope and expect that we'll have weakrefs and post-mortem
finalization in ES7. They are needed for many other things, such as
distributed acyclic garbage collection (as in adapting the CapTP ideas to
distributed JS).


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




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Rev21 ES6 Draft now available

2013-11-08 Thread Allen Wirfs-Brock
PDFs and .doc file available at
http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#november_8_2013_draft_rev_21
 

New in this revision:
• Updated Module Syntax and static semantics
• Scripts no longer may contain import statements
• Specified how to determine if a call is in tail position
• The call and apply functions now internally do tail calls to the 
target function
• Tweaked the new operator so it will work in tail position
• Eliminated the [[Invoke]] MOP operation
• Calling the next method of an completed generator returns a “done” 
result instead of throwing
• The length property of bound functions is now 
configurable/non-writable
• Clarified requirements of String localeCompare when no language 
sensitive comparison support is available.
• Tweaked the ordering of a few steps in Array.from to enable 
self-hosting using for-of
• Added ToInt8 and similar abstract operation
• Defined name property of %TypedArray% and the individual typed array 
constructors
• Significant fixed to yield * evaluation semantics
• Fixed handling of identifier ‘yield’ in generator function parameter 
lists
• A little static semantic cleanup making sure that 
FunctionDeclarations and GeneratorDeclarations have the same top level scoping 
rules


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Weak callbacks?

2013-11-08 Thread K. Gadd
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?

2013-11-08 Thread Allen Wirfs-Brock

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


Specification of use before declaration errors

2013-11-08 Thread Ian Halliday
Hello es-discuss,

I'm having difficulty figuring out where the ES6 draft spec specifies that a 
use before declaration error should be thrown.  My last understanding of the 
temporal dead zone was that ECMAScript would always issue a use before 
declaration error at runtime, regardless whether it can be statically 
determined or not.  However it seems like the evaluation semantics of var 
declarations, for example, do not lead to any line that throws a ReferenceError.

That is, consider this code:

function f() {
{
var x = 5;
let x;
}
}

f();
I think the var declaration creates a binding for x in the function's lexical 
environment, but then binds to the x in the block's environment for the 
initialization.  As such, the initialization should throw a use before 
declaration error.  But this is what I cannot find in the spec.  Maybe I am 
wrong about the semantics here?

If I am not wrong then this raises the question of order of operations.  Is the 
RHS evaluated first, then the error is thrown?  Or is the LHS name evaluated 
first, throwing if it is a binding that is currently in its TDZ?

E.g. is g() called here before throwing?

function g() {
console.log('hello');
return 0;
}

function f() {
{
var x = g();
let x;
}
}

f();


How about for-in/of loops?  Is g() called here?
function g() {
console.log('hello');
return { a: 1, b: 2, c: 3 };
}

function f() {
{
for (var x in g()) {
console.log('unreachable');
}
let x;
}
}

Ian Halliday

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Specification of use before declaration errors

2013-11-08 Thread Allen Wirfs-Brock

On Nov 8, 2013, at 3:35 PM, Ian Halliday wrote:

 Hello es-discuss,
  
 I’m having difficulty figuring out where the ES6 draft spec specifies that a 
 “use before declaration” error should be thrown.  My last understanding of 
 the temporal dead zone was that ECMAScript would always issue a “use before 
 declaration” error at runtime, regardless whether it can be statically 
 determined or not.  However it seems like the evaluation semantics of var 
 declarations, for example, do not lead to any line that throws a 
 ReferenceError.


  
 That is, consider this code:
  
 function f() {
 {
 var x = 5;
 let x;
declaring the same name using a let and a var is an early error: 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-block-static-semantics-early-errors
  
or for the function level 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-function-definitions-static-semantics-early-errors
 


 }
 }
 
 f();
 
 I think the var declaration creates a binding for x in the function’s lexical 
 environment, but then binds to the x in the block’s environment for the 
 initialization.  As such, the initialization should throw a “use before 
 declaration” error.  But this is what I cannot find in the spec.  Maybe I am 
 wrong about the semantics here?

because an early error exists, the surround script or module is never evaluated.

Allen___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Weak callbacks?

2013-11-08 Thread K. Gadd
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?

2013-11-08 Thread David Bruant

Le 08/11/2013 20:35, Mark S. Miller a écrit :

Please try -- such experiments are interesting.

I am :-)

But even if this experiment is successful, I hope and expect that 
we'll have weakrefs and post-mortem finalization in ES7. They are 
needed for many other things, such as distributed acyclic garbage 
collection (as in adapting the CapTP ideas to distributed JS).

yes...
Speaking of which, could you explain the use of proxyRef.get from the 
related example? [1]
At least in the executor function, I don't understand how the object 
could be still alive and why the call is needed.


David

[1] 
http://wiki.ecmascript.org/doku.php?id=strawman:weak_references#distributed_acyclic_garbage_collection

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Weak callbacks?

2013-11-08 Thread Mark S. Miller
Hi David, there's a distributed race condition that's fixed by the use of
importCount. Fixing it using post-mortem finalization creates a local race
condition which is fixed by this test, not if the proxy is *still* alive,
but if a new proxy has been installed as its reincarnation.

For background, see http://www.erights.org/elib/distrib/captp/dagc.html
and http://www.erights.org/elib/distrib/captp/DeliverOp.html. Kenton
Varda is implementing a high performance adaptation of CapTP 
https://github.com/kentonv/capnproto/blob/master/c++/src/capnp/rpc.capnp as
part of Cap'n Proto http://kentonv.github.io/capnproto/. (Kenton did
Google's protobufs 2 and open sourced them before leaving Google to do this
successor.) This CapTP-in-Cap'n Proto has essentially the same distributed
gc logic for coping with the distributed race conditions, but in its C++
bindings, relies on local manual collection rather than observation of
local GC, so it doesn't have the same local race condition.

The distributed race condition is that VatA notices (by finalization of the
proxy)  that it has dropped all local references to its bobProxy for VatB's
Bob object. So VatA sends a GCExportOp(i, importCount) (in original CapTP
terminology) to VatB. However, in the meantime, a message from VatB to VatA
contains a reference to VatB's Bob. When it serializes the references to
Bob, it sees that Bob is already registered in its VatB-to-VatA exports
table at index i, so it serializes the reference as an ImportDesc(i). (When
it sends Bob the first time it sends a NewFarDesc instead.)

The GCExportOp(i, importCount) from VatA-to-VatB might cross on the wire
with the ImportDesc(i) from VatB to VatA, which is the distributed race
condition issue. The solution is that every time VatB sends an
ImportDesc(i) to VatA, it increments exportCount[i] in its VatB to VatA
export table. Everytime VatA unserializes an ImportDesc(i), it calls the
Import(i) function at 
http://wiki.ecmascript.org/doku.php?id=strawman:weak_references#distributed_acyclic_garbage_collection,
which increments importCount[i] and returns a valid proxy registered in is
VatA-from-VatB imports table at i. If the existing proxy still exists, it
uses that one. Otherwise it creates a new one.

When VatB receiver the GCExportOp(i, importCount) from VatA, it decrements
its exportCount by that amount. If its exportCount reaches 0, then it knows
it can null out entry i in its exports table, enabling local collection of
Bob if there are no other local uses. Otherwise, it knows that it needs to
keep Bob registered as exports[i].

The local race condition is that VatA's local GC might have collected
bobProxy, therefore nulling out the proxyRef, and scheduled a notification
of the handler that would send the GCExportOp. However, already queued on
VatA ahead of the notification of the handler is the processing of the
ImportDesc from VatB, so that gets processed first, creating a successor
proxy at imports[i]. Finally, when the handler does get notified, it needs
to check if such a successor has already been installed and is still alive.

I know this is complex, but after many years of looking at it, I don't know
how to make it any simpler. Consider this a challenge ;). (OTOH, after many
years of use, I've come to have high confidence in it.)

The Dec Src Network Object system has similar solutions to many of these
distributed race condition problems. But they had a very different model of
local concurrency (shared state concurrency with Tony Hoare monitors IIRC),
so they had different local race condition problems.




On Fri, Nov 8, 2013 at 4:49 PM, David Bruant bruan...@gmail.com wrote:

 Le 08/11/2013 20:35, Mark S. Miller a écrit :

  Please try -- such experiments are interesting.

 I am :-)


  But even if this experiment is successful, I hope and expect that we'll
 have weakrefs and post-mortem finalization in ES7. They are needed for many
 other things, such as distributed acyclic garbage collection (as in
 adapting the CapTP ideas to distributed JS).

 yes...
 Speaking of which, could you explain the use of proxyRef.get from the
 related example? [1]
 At least in the executor function, I don't understand how the object could
 be still alive and why the call is needed.

 David

 [1] http://wiki.ecmascript.org/doku.php?id=strawman:weak_
 references#distributed_acyclic_garbage_collection




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss