|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
JS API change: remove JS_SetBranchCallback, change JS_*OperationCallback*Hi,
We plan on changing the branch and operation callback APIs in SpiderMonkey. The long-standing branch callback, and the recently added (Firefox 3) operation callback API, will be removed and replaced with the following entry points: extern JS_PUBLIC_API(JSOperationCallback) JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback); extern JS_PUBLIC_API(JSOperationCallback) JS_GetOperationCallback(JSContext *cx); extern JS_PUBLIC_API(void) JS_TriggerOperationCallback(JSContext *cx); Please note that this new API does not allow specifying any operation limits. An operation callback is now merely a function associated with a context that will be called some time after JS_TriggerOperationCallback() is invoked on that context. The operation callback is always invoked from the thread associated with the context, and execution on that context pauses until the callback returns. As previously, the callback can return false to abort code execution (for example when the callback decides that too much time has elapsed executing code on this context). The JS engine now automatically yields active requests on the context immediately prior to invoking the callback. It is no longer necessary to manually yield the request from within the callback in multithreaded embeddings. Callbacks may be triggered from any thread, or even from inside signal and interrupt handlers, as they merely update a flag in memory. Multithreaded embeddings are advised to use a timer thread to implement a watchdog. The timer thread can use JS_TriggerOperationCallback to ensure that the operation callback is invoked on a regular basis, permitting the callback to abort execution if appropriate. For single-threaded embeddings that cannot use signals or interrupts to trigger operation callbacks on a regular basis we have added the following API of last-resort. Its use is discouraged (use signals or a watchdog thread if you can); this API is not available to multithreaded embeddings: extern JS_PUBLIC_API(JSHeartbeatCallback) JS_SetHeartbeatCallback(JSRuntime *rt, JSHeartbeatCallback hbCallback); extern JS_PUBLIC_API(JSHeartbeatCallback) JS_GetHeartbeatCallback(JSRuntime *rt); This API installs a heartbeat callback that will be called from the JS engine on a regular basis. The invocation frequency is machine dependent and varies depending on whether code is run by the interpreter or is executed as machine code compiled by the tracing JIT. The heartbeat callback may trigger an operation callback. Removing the old branch and operation callback APIs speeds up the execution of JIT-compiled tight loops by up to 25%. Over a set of mixed benchmark programs we have observed an average speedup of 2%. We SpiderMonkey hackers take JS API compatibility seriously, preserving it by default and adding new entry points while almost never removing old ones. This has been an element of SpiderMonkey's success for over ten years in Mozilla open source, even longer counting Netscape-licensed versions. But with the TraceMonkey work to add a JIT to SpiderMonkey, some APIs have to go. We hope embedders will agree that the branch callback was always too blunt an instrument, and that the performance and flexibility gained by the new operation callback proposed here and implemented in https://bugzilla.mozilla.org/show_bug.cgi?id=477187 are worth the compatibility break. If you have any comments or questions please let us know. Andreas Gal Brendan Eich Igor Bukanov _______________________________________________ dev-tech-js-engine mailing list dev-tech-js-engine@... https://lists.mozilla.org/listinfo/dev-tech-js-engine |
|
|
Re: JS API change: remove JS_SetBranchCallback, change JS_*OperationCallback*> For single-threaded embeddings that cannot use signals or interrupts
> to trigger operation callbacks on a regular basis we have added the > following API of last-resort. Its use is discouraged (use signals or a > watchdog thread if you can); this API is not available to > multithreaded embeddings: > > extern JS_PUBLIC_API(JSHeartbeatCallback) > JS_SetHeartbeatCallback(JSRuntime *rt, JSHeartbeatCallback > hbCallback); > > extern JS_PUBLIC_API(JSHeartbeatCallback) > JS_GetHeartbeatCallback(JSRuntime *rt); > > This API installs a heartbeat callback that will be called from the JS > engine on a regular basis. The invocation frequency is machine > dependent and varies depending on whether code is run by the > interpreter or is executed as machine code compiled by the tracing > JIT. The heartbeat callback may trigger an operation callback. Igor pointed out in https://bugzilla.mozilla.org/show_bug.cgi?id=477187 how this API is not close enough to substitute for the branch callback or old (as in, Firefox 3 era, not yet shipped in a standalone SpiderMonkey) operation callback, and it won't stop nearly-infinite loops in native code. The best way forward is signals if not threads, so we are withdrawing the heartbeat API. /be _______________________________________________ dev-tech-js-engine mailing list dev-tech-js-engine@... https://lists.mozilla.org/listinfo/dev-tech-js-engine |
|
|
Re: JS API change: remove JS_SetBranchCallback, change JS_*OperationCallback*Team MozJS,
I was a bit surprised by the API change, but I swapped out the old operation count branching mechanism (I never understood exactly what the SetOperationLimit mapped to anyways) to use signals in 10minutes. It works great! I wrote up some notes on a single-thread+signals mechanism: http://wiki.client9.com/wiki.pl/SpiderMonkeyRunaways and some sample code to test it out here http://svn.client9.com/client9code/spidermonkey/micro_opt.cc $ # 1 second timeout $ ./a.out ---- WITH JIT Array(1<<27).sort() : 1010861 while (1) {} : 1017258 for (var i= 0; i < 10000000; ++i) {} : 366390 for (var i= 0; i < 10000000; i++) {} : 366423 for (var i= 0; i < 10000000; i += 1) {} : 570077 for (var i= 0; i < 10000000; i = i + 1) {} : 564697 var i = 0; while (i < 10000000) { ++i; } : 369668 function f() { f(); } f(); : 2848 ---- WITHOUT JIT Array(1<<27).sort() : 1011369 while (1) {} : 1008704 for (var i= 0; i < 10000000; ++i) {} : 360710 for (var i= 0; i < 10000000; i++) {} : 369606 for (var i= 0; i < 10000000; i += 1) {} : 562706 for (var i= 0; i < 10000000; i = i + 1) {} : 562393 var i = 0; while (i < 10000000) { ++i; } : 365057 function f() { f(); } f(); : 2394 (ok the for loops complete before the 1s time out) (FYI -- looks like the JIT isn't being triggered by trivial for loops anymore -- it was yesterday) thanks again, --nickg _______________________________________________ dev-tech-js-engine mailing list dev-tech-js-engine@... https://lists.mozilla.org/listinfo/dev-tech-js-engine |
|
|
Re: JS API change: remove JS_SetBranchCallback, change JS_*OperationCallback*Brendan:
As long as you are changing the API, would you consider adding some small promises? - JS_(Get|Set|Trigger)OperationCallback() are safe to run inside a signal handler - JS_(Get|Set|Trigger)OperationCallback() are safe to run from a thread which is NOT the JS_SetContextThread() thread These routines currently look safe to run and do not even have the normal CHECK_REQUEST(cx) guards in them, so I think the promises I'm asking for are already implemented, just not future-proofed from a documentation point of view. So, to be clear, I'd like to be able to safely write int mySignalHandler(sig) { gOldCB = JS_GetOperationCallback(someCX); JS_SetOperationCallback(someCX, myCB); JS_TriggerOperationCallback(someCX); } JSBool myCB(JSContext *cx) { JS_SetOperationCallback(cx, gOldCB); return JS_CallFunction(cx, ....); } in an environment with multiple threads of JavaScript executing, and have the thread executing someCX's JS code run myCB shortly after mySignalHandler() runs. It is not guaranteed that the thread catching the signal will be the same thread that owns someCX (in all likelihood, signals will be caught with a totally separate thread running sigwait(3C)); Notes - I don't expect signal safety inside JS_ASSERT, that would be silly - JS(Get|Set|Trigger) thread synchronization is a problem left for the API-user and as such omitted from my example Wes -- Wesley W. Garland Director, Product Development PageMail, Inc. +1 613 542 2787 x 102 _______________________________________________ dev-tech-js-engine mailing list dev-tech-js-engine@... https://lists.mozilla.org/listinfo/dev-tech-js-engine |
|
|
Re: JS API change: remove JS_SetBranchCallback, change JS_*OperationCallback*On 2/7/09 11:33 PM, Brendan Eich wrote:
> extern JS_PUBLIC_API(JSOperationCallback) > JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback); > > extern JS_PUBLIC_API(void) > JS_TriggerOperationCallback(JSContext *cx); This is a much nicer API, but I wonder why it's still called "operation callback". How would a patch to rename this to "async callback" be received? Also, it seems funny that the callback is sometimes called even when the application didn't trigger it. It seems like we could easily make it speak only when spoken to. Why not? -j _______________________________________________ dev-tech-js-engine mailing list dev-tech-js-engine@... https://lists.mozilla.org/listinfo/dev-tech-js-engine |
| Free embeddable forum powered by Nabble | Forum Help |