|
|
Description[testing] Add the notion of a wait count to allow tests to robustly wait on asynchronous tasks.
Note that this also modifies mjsunit.js to allow the {failWithMessage} method to be monkey-patched by a test. This is necessary because assertions which fail in a promise's then-clause would normally only throw an exception, which is swallowed by the promise, causing the test to silently pass. Instead, patching this {failWithMessage} functionality allows then clauses to use the full assertion machinery of mjsunit.js.
R=ulan@chromium.org, gsathya@chromium.org
BUG=
Review-Url: https://codereview.chromium.org/2752043002
Cr-Commit-Position: refs/heads/master@{#43875}
Committed: https://chromium.googlesource.com/v8/v8/+/3bbd81afbc7383956a7894e4dd791ff88dba4c8a
Patch Set 1 #Patch Set 2 : Strip it down to %IncrementWaitCount and %DecrementWaitCount #
Total comments: 1
Patch Set 3 : Add ForTesting #
Total comments: 2
Patch Set 4 : Move functions to runtime-test.cc #Patch Set 5 : Don't touch runtime-promise.cc #
Messages
Total messages: 39 (22 generated)
The CQ bit was checked by titzer@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
On 2017/03/15 17:52:16, titzer wrote: A little more background on this CL: In testing WASM asynchronous compilation which is triggered by "WebAssembly.compile(buffer)", the returned promise may in fact be the only link that the foreground script has to the compilation running in the background. The very first task created for the compilation is a background task that, when complete, posts foreground tasks that are executed as part of PumpMessageLoop(). Problem is, that the entire script can finish before the background task ever gets started, and thus none of the promise handler code ever runs. This CL instead allows certain promises to be waited-for, which causes d8 to wait until all promises are resolved (continually pumping the message queue until that is so).
Description was changed from ========== [promises] Add %WaitForPromise runtime call to allow tests to reliably wait for promises to be finished before executing. Note that this also modifies mjsunit.js to allow the {failWithMessage} method to be monkey-patched by a test. This is necessary because assertions which fail in a then-clause would normally only throw an exception, which is swallowed by the promise, causing the test to silently pass. Instead, patching this {failWithMessage} functionality allows then clauses to use the full assertion machinery of mjsunit.js. R=ulan@chromium.org, gsathya@chromium.org BUG= ========== to ========== [promises] Add %WaitForPromise runtime call to allow tests to reliably wait for promises to be finished before executing. Note that this also modifies mjsunit.js to allow the {failWithMessage} method to be monkey-patched by a test. This is necessary because assertions which fail in a then-clause would normally only throw an exception, which is swallowed by the promise, causing the test to silently pass. Instead, patching this {failWithMessage} functionality allows then clauses to use the full assertion machinery of mjsunit.js. R=ulan@chromium.org, gsathya@chromium.org BUG= ==========
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
On 2017/03/15 17:55:05, titzer wrote: > On 2017/03/15 17:52:16, titzer wrote: > > A little more background on this CL: > > In testing WASM asynchronous compilation which is triggered by > "WebAssembly.compile(buffer)", the returned promise may in fact be the only link > that the foreground script has to the compilation running in the background. The > very first task created for the compilation is a background task that, when > complete, posts foreground tasks that are executed as part of PumpMessageLoop(). > Problem is, that the entire script can finish before the background task ever > gets started, and thus none of the promise handler code ever runs. > > This CL instead allows certain promises to be waited-for, which causes d8 to > wait until all promises are resolved (continually pumping the message queue > until that is so). How about something like this -- async function testCompile() { %IncrementCounter(); var module = await Compile(..) %DecrementCounter(); assert(module ..); } Runtime_IncrementCounter { isolate->IncrementPromiseWaitCount(); } Runtime_DecrementCounter{ isolate->DecrementPromiseWaitCount(); } There's no need to change the promise internals.
On 2017/03/16 00:32:16, gsathya wrote: > On 2017/03/15 17:55:05, titzer wrote: > > On 2017/03/15 17:52:16, titzer wrote: > > > > A little more background on this CL: > > > > In testing WASM asynchronous compilation which is triggered by > > "WebAssembly.compile(buffer)", the returned promise may in fact be the only > link > > that the foreground script has to the compilation running in the background. > The > > very first task created for the compilation is a background task that, when > > complete, posts foreground tasks that are executed as part of > PumpMessageLoop(). > > Problem is, that the entire script can finish before the background task ever > > gets started, and thus none of the promise handler code ever runs. > > > > This CL instead allows certain promises to be waited-for, which causes d8 to > > wait until all promises are resolved (continually pumping the message queue > > until that is so). > > How about something like this -- > > async function testCompile() { > %IncrementCounter(); > var module = await Compile(..) > %DecrementCounter(); > assert(module ..); > } > > Runtime_IncrementCounter { > isolate->IncrementPromiseWaitCount(); > } > > Runtime_DecrementCounter{ > isolate->DecrementPromiseWaitCount(); > } > > There's no need to change the promise internals. That's a good idea. I'll give it a shot! (funny enough, I had something like what you suggest, but implemented in JS. The problem is AFAICT that we can only create microtasks in our JS tests and not foreground tasks. The background compilation needs to run foreground tasks to complete--especially, resolving the promise--and the waiting needs to therefore to loop until these foreground tasks are completed).
The CQ bit was checked by titzer@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
Description was changed from ========== [promises] Add %WaitForPromise runtime call to allow tests to reliably wait for promises to be finished before executing. Note that this also modifies mjsunit.js to allow the {failWithMessage} method to be monkey-patched by a test. This is necessary because assertions which fail in a then-clause would normally only throw an exception, which is swallowed by the promise, causing the test to silently pass. Instead, patching this {failWithMessage} functionality allows then clauses to use the full assertion machinery of mjsunit.js. R=ulan@chromium.org, gsathya@chromium.org BUG= ========== to ========== [testing] Add the notion of a wait count to allow tests to robustly wait on asynchronous tasks. Note that this also modifies mjsunit.js to allow the {failWithMessage} method to be monkey-patched by a test. This is necessary because assertions which fail in a promise's then-clause would normally only throw an exception, which is swallowed by the promise, causing the test to silently pass. Instead, patching this {failWithMessage} functionality allows then clauses to use the full assertion machinery of mjsunit.js. R=ulan@chromium.org, gsathya@chromium.org BUG= ==========
On 2017/03/16 06:29:51, titzer wrote: > On 2017/03/16 00:32:16, gsathya wrote: > > On 2017/03/15 17:55:05, titzer wrote: > > > On 2017/03/15 17:52:16, titzer wrote: > > > > > > A little more background on this CL: > > > > > > In testing WASM asynchronous compilation which is triggered by > > > "WebAssembly.compile(buffer)", the returned promise may in fact be the only > > link > > > that the foreground script has to the compilation running in the background. > > The > > > very first task created for the compilation is a background task that, when > > > complete, posts foreground tasks that are executed as part of > > PumpMessageLoop(). > > > Problem is, that the entire script can finish before the background task > ever > > > gets started, and thus none of the promise handler code ever runs. > > > > > > This CL instead allows certain promises to be waited-for, which causes d8 to > > > wait until all promises are resolved (continually pumping the message queue > > > until that is so). > > > > How about something like this -- > > > > async function testCompile() { > > %IncrementCounter(); > > var module = await Compile(..) > > %DecrementCounter(); > > assert(module ..); > > } > > > > Runtime_IncrementCounter { > > isolate->IncrementPromiseWaitCount(); > > } > > > > Runtime_DecrementCounter{ > > isolate->DecrementPromiseWaitCount(); > > } > > > > There's no need to change the promise internals. > > That's a good idea. I'll give it a shot! > > (funny enough, I had something like what you suggest, but implemented in JS. The > problem is AFAICT that we can only create microtasks in our JS tests and not > foreground tasks. The background compilation needs to run foreground tasks to > complete--especially, resolving the promise--and the waiting needs to therefore > to loop until these foreground tasks are completed). PTAL, I've updated this CL based on Sathya's suggestion.
https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc File src/d8.cc (right): https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc#newcode1583 src/d8.cc:1583: return global_template; How about adding "increment", "decrement" functions to d8 specific global object instead of isolate?
On 2017/03/16 11:50:14, ulan wrote: > https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc > File src/d8.cc (right): > > https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc#newcode1583 > src/d8.cc:1583: return global_template; > How about adding "increment", "decrement" functions to d8 specific global object > instead of isolate? We could do that, but the more common way we do this is to introduce natives. Are you concerned about the extra counter on the isolate?
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
On 2017/03/16 11:52:52, titzer wrote: > On 2017/03/16 11:50:14, ulan wrote: > > https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc > > File src/d8.cc (right): > > > > https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc#newcode1583 > > src/d8.cc:1583: return global_template; > > How about adding "increment", "decrement" functions to d8 specific global > object > > instead of isolate? > > We could do that, but the more common way we do this is to introduce natives. > Are you concerned about the extra counter on the isolate? Yeah, it is a d8 specific counter, not used in chrome and other embedders.
On 2017/03/16 12:47:34, ulan wrote: > On 2017/03/16 11:52:52, titzer wrote: > > On 2017/03/16 11:50:14, ulan wrote: > > > https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc > > > File src/d8.cc (right): > > > > > > https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc#newcode1583 > > > src/d8.cc:1583: return global_template; > > > How about adding "increment", "decrement" functions to d8 specific global > > object > > > instead of isolate? > > > > We could do that, but the more common way we do this is to introduce natives. > > Are you concerned about the extra counter on the isolate? > > Yeah, it is a d8 specific counter, not used in chrome and other embedders. I see it more as a testing thing, for which we have lots of natives calls. Besides, Maybe we want to expose to other embedders in the future?
On 2017/03/16 12:55:33, titzer wrote: > On 2017/03/16 12:47:34, ulan wrote: > > On 2017/03/16 11:52:52, titzer wrote: > > > On 2017/03/16 11:50:14, ulan wrote: > > > > https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc > > > > File src/d8.cc (right): > > > > > > > > > https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc#newcode1583 > > > > src/d8.cc:1583: return global_template; > > > > How about adding "increment", "decrement" functions to d8 specific global > > > object > > > > instead of isolate? > > > > > > We could do that, but the more common way we do this is to introduce > natives. > > > Are you concerned about the extra counter on the isolate? > > > > Yeah, it is a d8 specific counter, not used in chrome and other embedders. > > I see it more as a testing thing, for which we have lots of natives calls. > Besides, Maybe we want to expose to other embedders in the future? lgtm if you add "for_testing"/"ForTesting" to the field and runtime functions to make it clear that these are not used in production. I don't see how we would expose this as public API. Happy to discuss offline :)
The CQ bit was checked by titzer@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
On 2017/03/16 13:27:42, ulan wrote: > On 2017/03/16 12:55:33, titzer wrote: > > On 2017/03/16 12:47:34, ulan wrote: > > > On 2017/03/16 11:52:52, titzer wrote: > > > > On 2017/03/16 11:50:14, ulan wrote: > > > > > https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc > > > > > File src/d8.cc (right): > > > > > > > > > > > > https://codereview.chromium.org/2752043002/diff/20001/src/d8.cc#newcode1583 > > > > > src/d8.cc:1583: return global_template; > > > > > How about adding "increment", "decrement" functions to d8 specific > global > > > > object > > > > > instead of isolate? > > > > > > > > We could do that, but the more common way we do this is to introduce > > natives. > > > > Are you concerned about the extra counter on the isolate? > > > > > > Yeah, it is a d8 specific counter, not used in chrome and other embedders. > > > > I see it more as a testing thing, for which we have lots of natives calls. > > Besides, Maybe we want to expose to other embedders in the future? > lgtm if you add "for_testing"/"ForTesting" to the field and runtime functions to > make it clear that these are not used in production. > > I don't see how we would expose this as public API. Happy to discuss offline :) Added ForTesting suffix to the methods on isolate.
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
On 2017/03/16 06:29:51, titzer wrote: > On 2017/03/16 00:32:16, gsathya wrote: > > On 2017/03/15 17:55:05, titzer wrote: > > > On 2017/03/15 17:52:16, titzer wrote: > > > > > > A little more background on this CL: > > > > > > In testing WASM asynchronous compilation which is triggered by > > > "WebAssembly.compile(buffer)", the returned promise may in fact be the only > > link > > > that the foreground script has to the compilation running in the background. > > The > > > very first task created for the compilation is a background task that, when > > > complete, posts foreground tasks that are executed as part of > > PumpMessageLoop(). > > > Problem is, that the entire script can finish before the background task > ever > > > gets started, and thus none of the promise handler code ever runs. > > > > > > This CL instead allows certain promises to be waited-for, which causes d8 to > > > wait until all promises are resolved (continually pumping the message queue > > > until that is so). > > > > How about something like this -- > > > > async function testCompile() { > > %IncrementCounter(); > > var module = await Compile(..) > > %DecrementCounter(); > > assert(module ..); > > } > > > > Runtime_IncrementCounter { > > isolate->IncrementPromiseWaitCount(); > > } > > > > Runtime_DecrementCounter{ > > isolate->DecrementPromiseWaitCount(); > > } > > > > There's no need to change the promise internals. > > That's a good idea. I'll give it a shot! > > (funny enough, I had something like what you suggest, but implemented in JS. The > problem is AFAICT that we can only create microtasks in our JS tests and not > foreground tasks. The background compilation needs to run foreground tasks to > complete--especially, resolving the promise--and the waiting needs to therefore > to loop until these foreground tasks are completed). You could busy wait in JS with something like this right? -- var run = false; var module; async function compile() { module = await Compile(..); ran = true; } compile(); while(!ran) { %RunMicrotasks(); } assert(module ..); I'm not sure if this is strictly better than what you already have. It would mean not having extra runtime functions/vars on isolate, though. I'll leave it to you. LGTM % nits.
https://codereview.chromium.org/2752043002/diff/40001/src/d8.cc File src/d8.cc (right): https://codereview.chromium.org/2752043002/diff/40001/src/d8.cc#newcode2600 src/d8.cc:2600: if (reinterpret_cast<i::Isolate*>(isolate)->GetWaitCountForTesting() > 0) { Should we time out here? https://codereview.chromium.org/2752043002/diff/40001/src/runtime/runtime-pro... File src/runtime/runtime-promise.cc (right): https://codereview.chromium.org/2752043002/diff/40001/src/runtime/runtime-pro... src/runtime/runtime-promise.cc:174: RUNTIME_FUNCTION(Runtime_IncrementWaitCount) { Can you move these to runtime-test.cc?
On 2017/03/16 17:38:53, gsathya wrote: > On 2017/03/16 06:29:51, titzer wrote: > > On 2017/03/16 00:32:16, gsathya wrote: > > > On 2017/03/15 17:55:05, titzer wrote: > > > > On 2017/03/15 17:52:16, titzer wrote: > > > > > > > > A little more background on this CL: > > > > > > > > In testing WASM asynchronous compilation which is triggered by > > > > "WebAssembly.compile(buffer)", the returned promise may in fact be the > only > > > link > > > > that the foreground script has to the compilation running in the > background. > > > The > > > > very first task created for the compilation is a background task that, > when > > > > complete, posts foreground tasks that are executed as part of > > > PumpMessageLoop(). > > > > Problem is, that the entire script can finish before the background task > > ever > > > > gets started, and thus none of the promise handler code ever runs. > > > > > > > > This CL instead allows certain promises to be waited-for, which causes d8 > to > > > > wait until all promises are resolved (continually pumping the message > queue > > > > until that is so). > > > > > > How about something like this -- > > > > > > async function testCompile() { > > > %IncrementCounter(); > > > var module = await Compile(..) > > > %DecrementCounter(); > > > assert(module ..); > > > } > > > > > > Runtime_IncrementCounter { > > > isolate->IncrementPromiseWaitCount(); > > > } > > > > > > Runtime_DecrementCounter{ > > > isolate->DecrementPromiseWaitCount(); > > > } > > > > > > There's no need to change the promise internals. > > > > That's a good idea. I'll give it a shot! > > > > (funny enough, I had something like what you suggest, but implemented in JS. > The > > problem is AFAICT that we can only create microtasks in our JS tests and not > > foreground tasks. The background compilation needs to run foreground tasks to > > complete--especially, resolving the promise--and the waiting needs to > therefore > > to loop until these foreground tasks are completed). > > You could busy wait in JS with something like this right? -- > > var run = false; > var module; > async function compile() { > module = await Compile(..); > ran = true; > } > > compile(); > > while(!ran) { > %RunMicrotasks(); > } > > assert(module ..); > > I'm not sure if this is strictly better than what you already have. It would > mean not having extra runtime functions/vars on isolate, though. I'll leave it > to you. > That was the first step on the road that led me here :) Unfortunately that is not enough, because in order for the base::platform to run foreground tasks, the script must return to the main event loop (i.e. the PumpMessageLoop() in d8.cc). > LGTM % nits.
On 2017/03/16 17:42:26, titzer wrote: > On 2017/03/16 17:38:53, gsathya wrote: > > On 2017/03/16 06:29:51, titzer wrote: > > > On 2017/03/16 00:32:16, gsathya wrote: > > > > On 2017/03/15 17:55:05, titzer wrote: > > > > > On 2017/03/15 17:52:16, titzer wrote: > > > > > > > > > > A little more background on this CL: > > > > > > > > > > In testing WASM asynchronous compilation which is triggered by > > > > > "WebAssembly.compile(buffer)", the returned promise may in fact be the > > only > > > > link > > > > > that the foreground script has to the compilation running in the > > background. > > > > The > > > > > very first task created for the compilation is a background task that, > > when > > > > > complete, posts foreground tasks that are executed as part of > > > > PumpMessageLoop(). > > > > > Problem is, that the entire script can finish before the background task > > > ever > > > > > gets started, and thus none of the promise handler code ever runs. > > > > > > > > > > This CL instead allows certain promises to be waited-for, which causes > d8 > > to > > > > > wait until all promises are resolved (continually pumping the message > > queue > > > > > until that is so). > > > > > > > > How about something like this -- > > > > > > > > async function testCompile() { > > > > %IncrementCounter(); > > > > var module = await Compile(..) > > > > %DecrementCounter(); > > > > assert(module ..); > > > > } > > > > > > > > Runtime_IncrementCounter { > > > > isolate->IncrementPromiseWaitCount(); > > > > } > > > > > > > > Runtime_DecrementCounter{ > > > > isolate->DecrementPromiseWaitCount(); > > > > } > > > > > > > > There's no need to change the promise internals. > > > > > > That's a good idea. I'll give it a shot! > > > > > > (funny enough, I had something like what you suggest, but implemented in JS. > > The > > > problem is AFAICT that we can only create microtasks in our JS tests and not > > > foreground tasks. The background compilation needs to run foreground tasks > to > > > complete--especially, resolving the promise--and the waiting needs to > > therefore > > > to loop until these foreground tasks are completed). > > > > You could busy wait in JS with something like this right? -- > > > > var run = false; > > var module; > > async function compile() { > > module = await Compile(..); > > ran = true; > > } > > > > compile(); > > > > while(!ran) { > > %RunMicrotasks(); > > } > > > > assert(module ..); > > > > I'm not sure if this is strictly better than what you already have. It would > > mean not having extra runtime functions/vars on isolate, though. I'll leave it > > to you. > > > > That was the first step on the road that led me here :) > > Unfortunately that is not enough, because in order for the base::platform to run > foreground tasks, the script must return to the main event loop (i.e. the > PumpMessageLoop() in d8.cc). > > > LGTM % nits. Ah, I see. LGTM. Thanks for making the changes!
The CQ bit was checked by titzer@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was checked by titzer@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was checked by titzer@chromium.org
The patchset sent to the CQ was uploaded after l-g-t-m from ulan@chromium.org, gsathya@chromium.org Link to the patchset: https://codereview.chromium.org/2752043002/#ps80001 (title: "Don't touch runtime-promise.cc")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
CQ is committing da patch. Bot data: {"patchset_id": 80001, "attempt_start_ts": 1489687076670380, "parent_rev": "4c3217e13292a3aab056b5800678754c8dac8bfe", "commit_rev": "3bbd81afbc7383956a7894e4dd791ff88dba4c8a"}
Message was sent while issue was closed.
Description was changed from ========== [testing] Add the notion of a wait count to allow tests to robustly wait on asynchronous tasks. Note that this also modifies mjsunit.js to allow the {failWithMessage} method to be monkey-patched by a test. This is necessary because assertions which fail in a promise's then-clause would normally only throw an exception, which is swallowed by the promise, causing the test to silently pass. Instead, patching this {failWithMessage} functionality allows then clauses to use the full assertion machinery of mjsunit.js. R=ulan@chromium.org, gsathya@chromium.org BUG= ========== to ========== [testing] Add the notion of a wait count to allow tests to robustly wait on asynchronous tasks. Note that this also modifies mjsunit.js to allow the {failWithMessage} method to be monkey-patched by a test. This is necessary because assertions which fail in a promise's then-clause would normally only throw an exception, which is swallowed by the promise, causing the test to silently pass. Instead, patching this {failWithMessage} functionality allows then clauses to use the full assertion machinery of mjsunit.js. R=ulan@chromium.org, gsathya@chromium.org BUG= Review-Url: https://codereview.chromium.org/2752043002 Cr-Commit-Position: refs/heads/master@{#43875} Committed: https://chromium.googlesource.com/v8/v8/+/3bbd81afbc7383956a7894e4dd791ff88db... ==========
Message was sent while issue was closed.
Committed patchset #5 (id:80001) as https://chromium.googlesource.com/v8/v8/+/3bbd81afbc7383956a7894e4dd791ff88db... |