Open
Bug 1222086
Opened 9 years ago
Updated 2 years ago
Block JavaScript parser thread when source code characters are not available
Categories
(Core :: JavaScript Engine, defect)
Core
JavaScript Engine
Tracking
()
NEW
Performance Impact | low |
People
(Reporter: yury, Unassigned)
References
(Blocks 1 open bug)
Details
(Keywords: perf)
Attachments
(4 files, 16 obsolete files)
175 bytes,
application/x-javascript
|
Details | |
30.82 KB,
patch
|
djvj
:
review+
|
Details | Diff | Splinter Review |
12.47 KB,
patch
|
djvj
:
review+
|
Details | Diff | Splinter Review |
42.60 KB,
patch
|
djvj
:
review+
|
Details | Diff | Splinter Review |
So the idea is to block parsing thread when end of available source code stream is found. Currently the Parser logic depends on a JavaScript source code to be a continuous char16 buffer -- we either need to replace the initial buffer or pre-allocate enough characters to fit at the beginning. Problem with the latter is that nsIChannel cannot guarantee or does not know total length (hints like Content-Length do not work since they are reflect the encoded content length -- zipped or charset). Pros: - Minimal change in the Parser code base - Practically no impact on the parsing speed - No intermediate state to save Cons: - Available single Parser thread will be blocked - Hence more than one Parsing thread must be created (bad due to thread memory overheads) and use additional heuristic needed to detect which files will be processed using this mode
Reporter | ||
Comment 1•9 years ago
|
||
Reporter | ||
Updated•9 years ago
|
Attachment #8683948 -
Attachment description: Pass JS source as CharsStream object. → [WIP] 1. Pass JS source as CharsStream object.
Reporter | ||
Comment 2•9 years ago
|
||
Reporter | ||
Comment 3•9 years ago
|
||
Reporter | ||
Comment 4•9 years ago
|
||
Reporter | ||
Comment 5•9 years ago
|
||
Attachment #8683948 -
Attachment is obsolete: true
Reporter | ||
Comment 6•9 years ago
|
||
Attachment #8683949 -
Attachment is obsolete: true
Reporter | ||
Comment 7•9 years ago
|
||
Attachment #8683951 -
Attachment is obsolete: true
Reporter | ||
Comment 8•9 years ago
|
||
Attachment #8688180 -
Attachment is obsolete: true
Reporter | ||
Comment 9•9 years ago
|
||
Attachment #8688181 -
Attachment is obsolete: true
Reporter | ||
Comment 10•9 years ago
|
||
Attachment #8688182 -
Attachment is obsolete: true
Reporter | ||
Comment 11•9 years ago
|
||
https://treeherder.mozilla.org/#/jobs?repo=try&revision=1033608147f9 I run Parsemark to see if there is a side effect from the TokenStream redesign -- there was no regression, "Meh." on all files.
Reporter | ||
Updated•9 years ago
|
Attachment #8689048 -
Flags: review?(kvijayan)
Reporter | ||
Updated•9 years ago
|
Attachment #8689049 -
Flags: review?(kvijayan)
Reporter | ||
Updated•9 years ago
|
Attachment #8689052 -
Flags: review?(kvijayan)
Comment 12•9 years ago
|
||
Ah! Just saw these review requests. Will do them next week. Sorry for lateness.
Comment 13•9 years ago
|
||
Comment on attachment 8689048 [details] [diff] [review] 1. Pass JS source as CharsStream object. Review of attachment 8689048 [details] [diff] [review]: ----------------------------------------------------------------- Nice. Very clean and easy to understand. ::: js/src/builtin/RegExp.cpp @@ +172,5 @@ > } > > /* Steps 9-10. */ > CompileOptions options(cx); > + frontend::TokenStream dummyTokenStream(cx, options, &frontend::NullCharsStream::null(), nullptr); It seems slightly more readable here to have the NullCharsStream usage reflect the same syntactic structure as the usage of StaticCharsStream: namely, it gets stack-allocated and a pointer gets passed to the stack-allocated item. ::: js/src/frontend/TokenStream.h @@ +309,5 @@ > + *start = *end = nullptr; > + *final = true; > + } > + > + static NullCharsStream& null() { I'd remove this method and use the same calling convention for NullCharsStream as users of StaticCharsStream do: stack-allocate-and-pass-pointer, instead of having a single statically allocated instance. Minor nit, though. I don't feel strongly about it. @@ +926,5 @@ > + if (MOZ_LIKELY(ptr < limit_)) > + return true; > + if (final_) > + return false; > + requestMoreChars(); |requestMoreChars| is guaranteed to grow the buffer, right? Might be good to assert that after the call, just to make sure that implementors of |CharsStream| are fulfilling that contract.
Attachment #8689048 -
Flags: review?(kvijayan) → review+
Comment 14•9 years ago
|
||
Comment on attachment 8689048 [details] [diff] [review] 1. Pass JS source as CharsStream object. Review of attachment 8689048 [details] [diff] [review]: ----------------------------------------------------------------- One additional note: The |final| parameter/field might better be named something like |streamComplete|.
Comment 15•9 years ago
|
||
Comment on attachment 8689049 [details] [diff] [review] 2. Allows OffThreadCompileCallback handle chars in chunks Review of attachment 8689049 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/jsapi.h @@ +746,5 @@ > length_(dataLength), > + requestChars_(requestChars), > + requestCharsData_(requestCharsData), > + ownsChars_(ownership == GiveOwnership), > + final_(!requestChars) Nit: |final_| might be better named |streamComplete_|. @@ +796,5 @@ > ownsChars_ = false; > return const_cast<char16_t*>(data_); > } > > + bool final() const { see above comment about naming (streamComplete()).
Attachment #8689049 -
Flags: review?(kvijayan) → review+
Comment 16•9 years ago
|
||
Comment on attachment 8689052 [details] [diff] [review] 3. jsshell integration Review of attachment 8689052 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/jit-test/tests/basic/offThreadCompileScript-03.js @@ +12,5 @@ > + > +if (helperThreadCount() === 0) > + quit(0); > + > +offThreadCompileScript('Math.sin(M', {}, false); This test case would be clearer if the entire "subscript" being compiled was a single string, and there was an array that listed the indexes at which the script should be split up into pieces, and the repeated calls to |appendOffThreadScript| and |waitSome| were instead a loop over that index array, using substring() to pick off pieces of the script to submit in parts. ::: js/src/shell/js.cpp @@ +5090,5 @@ > " Wait for off-thread compilation to complete. If an error occurred,\n" > " throw the appropriate exception; otherwise, run the script and return\n" > " its value."), > > +JS_FN_HELP("appendOffThreadScript", appendOffThreadScript, 0, 0, Nice. This is very clever.
Attachment #8689052 -
Flags: review?(kvijayan) → review+
Reporter | ||
Comment 17•9 years ago
|
||
Attachment #8689048 -
Attachment is obsolete: true
Reporter | ||
Comment 18•9 years ago
|
||
(In reply to Kannan Vijayan [:djvj] from comment #14) > Comment on attachment 8689048 [details] [diff] [review] > 1. Pass JS source as CharsStream object. > > Review of attachment 8689048 [details] [diff] [review]: > ----------------------------------------------------------------- > > One additional note: The |final| parameter/field might better be named > something like |streamComplete|. Fixed. (In reply to Kannan Vijayan [:djvj] from comment #13) > Comment on attachment 8689048 [details] [diff] [review] > 1. Pass JS source as CharsStream object. > > Review of attachment 8689048 [details] [diff] [review]: > ----------------------------------------------------------------- > > Nice. Very clean and easy to understand. > > ::: js/src/builtin/RegExp.cpp > @@ +172,5 @@ > > } > > > > /* Steps 9-10. */ > > CompileOptions options(cx); > > + frontend::TokenStream dummyTokenStream(cx, options, &frontend::NullCharsStream::null(), nullptr); > > It seems slightly more readable here to have the NullCharsStream usage > reflect the same syntactic structure as the usage of StaticCharsStream: > namely, it gets stack-allocated and a pointer gets passed to the > stack-allocated item. > > ::: js/src/frontend/TokenStream.h > @@ +309,5 @@ > > + *start = *end = nullptr; > > + *final = true; > > + } > > + > > + static NullCharsStream& null() { > > I'd remove this method and use the same calling convention for > NullCharsStream as users of StaticCharsStream do: > stack-allocate-and-pass-pointer, instead of having a single statically > allocated instance. > > Minor nit, though. I don't feel strongly about it. Fixed. > > @@ +926,5 @@ > > + if (MOZ_LIKELY(ptr < limit_)) > > + return true; > > + if (final_) > > + return false; > > + requestMoreChars(); > > |requestMoreChars| is guaranteed to grow the buffer, right? Might be good > to assert that after the call, just to make sure that implementors of > |CharsStream| are fulfilling that contract. requestMoreChars is non-virtual, so it's safe to add this check at the requestMoreChars method body. And the described check is already present there. Is it what you had in mind?
Flags: needinfo?(kvijayan)
Reporter | ||
Comment 19•9 years ago
|
||
(In reply to Kannan Vijayan [:djvj] from comment #15) > Comment on attachment 8689049 [details] [diff] [review] > 2. Allows OffThreadCompileCallback handle chars in chunks > > Review of attachment 8689049 [details] [diff] [review]: > ----------------------------------------------------------------- > > ::: js/src/jsapi.h > @@ +746,5 @@ > > length_(dataLength), > > + requestChars_(requestChars), > > + requestCharsData_(requestCharsData), > > + ownsChars_(ownership == GiveOwnership), > > + final_(!requestChars) > > Nit: |final_| might be better named |streamComplete_|. > > @@ +796,5 @@ > > ownsChars_ = false; > > return const_cast<char16_t*>(data_); > > } > > > > + bool final() const { > > see above comment about naming (streamComplete()). Fixed.
Attachment #8689049 -
Attachment is obsolete: true
Reporter | ||
Comment 20•9 years ago
|
||
(In reply to Kannan Vijayan [:djvj] from comment #16) > Comment on attachment 8689052 [details] [diff] [review] > 3. jsshell integration > > Review of attachment 8689052 [details] [diff] [review]: > ----------------------------------------------------------------- > > ::: js/src/jit-test/tests/basic/offThreadCompileScript-03.js > @@ +12,5 @@ > > + > > +if (helperThreadCount() === 0) > > + quit(0); > > + > > +offThreadCompileScript('Math.sin(M', {}, false); > > This test case would be clearer if the entire "subscript" being compiled was > a single string, and there was an array that listed the indexes at which the > script should be split up into pieces, and the repeated calls to > |appendOffThreadScript| and |waitSome| were instead a loop over that index > array, using substring() to pick off pieces of the script to submit in parts. > Fixed. Last try https://treeherder.mozilla.org/#/jobs?repo=try&revision=4228eb759fbd
Attachment #8689052 -
Attachment is obsolete: true
Reporter | ||
Comment 21•9 years ago
|
||
Fixed "js/src/frontend/BytecodeCompiler.cpp:49:5: error: bad implicit conversion constructor for 'SourceBufferCharsStream'" (https://treeherder.mozilla.org/#/jobs?repo=try&revision=9d2607159a52)
Attachment #8693845 -
Attachment is obsolete: true
Reporter | ||
Comment 22•9 years ago
|
||
The hazards test was failing (https://treeherder.mozilla.org/#/jobs?repo=try&revision=4228eb759fbd&selectedJob=14272132): Function '_ZN2js8frontend6ParserINS0_16FullParseHandlerEEC1EPNS_16ExclusiveContextEPNS_9LifoAllocERKN2JS22ReadOnlyCompileOptionsEPNS0_11CharsStreamEbPNS1_INS0_18SyntaxParseHandlerEEEPNS_10LazyScriptE *INTERNAL* |js::frontend::Parser<ParseHandler>::Parser(js::ExclusiveContext*, js::LifoAlloc*, const JS::ReadOnlyCompileOptions&, js::frontend::CharsStream*, bool, js::frontend::Parser<js::frontend::SyntaxParseHandler>*, js::LazyScript*) [with ParseHandler = js::frontend::FullParseHandler]' has unrooted 'lazyOuterFunction' of type 'js::LazyScript*' live across GC call '_ZN2js8frontend11TokenStreamC1EPNS_16ExclusiveContextERKN2JS22ReadOnlyCompileOptionsEPNS0_11CharsStreamEPNS0_16StrictModeGetterE|void js::frontend::TokenStream::TokenStream(js::ExclusiveContext*, JS::ReadOnlyCompileOptions*, js::frontend::CharsStream*, js::frontend::StrictModeGetter*)' at js/src/frontend/Parser.cpp:662 ... js/src/frontend/Parser.cpp:662: Call(6,7, this*.tokenStream.TokenStream(cx*,options*,chars*,__temp_1*.field:0)) [[GC call]] .... js/src/frontend/Parser.cpp:662: Call(22,23, this*.handler.FullParseHandler(cx*,alloc*,this*.tokenStream,syntaxParser*,lazyOuterFunction*)) I changed the lazyOuterFunction type from LazyScript* to Handle<LazyScript*> for the ParseHandler (Please also find requestMoreChars body for contract verification of CharsStream.request implementation)
Attachment #8693804 -
Attachment is obsolete: true
Flags: needinfo?(kvijayan)
Attachment #8694406 -
Flags: review?(kvijayan)
Reporter | ||
Comment 24•9 years ago
|
||
rebased, new try https://treeherder.mozilla.org/#/jobs?repo=try&revision=39643287908a
Attachment #8693848 -
Attachment is obsolete: true
Updated•9 years ago
|
Attachment #8694406 -
Flags: review?(kvijayan) → review+
Reporter | ||
Comment 25•9 years ago
|
||
Found an issue with lazy function parsing: ScriptSource::setSourceCopy was getting initial/incomplete portion of the source and it was never updated. Fixing that by calling setSourceCopy after entire source is loaded.
Attachment #8694407 -
Attachment is obsolete: true
Attachment #8700597 -
Flags: review?(kvijayan)
Reporter | ||
Comment 26•9 years ago
|
||
Updated/added a test cases for the finding above. https://treeherder.mozilla.org/#/jobs?repo=try&revision=a4f9bb47eb0c
Attachment #8694408 -
Attachment is obsolete: true
Attachment #8700599 -
Flags: review?(kvijayan)
Updated•8 years ago
|
Attachment #8700597 -
Flags: review?(kvijayan) → review+
Updated•8 years ago
|
Attachment #8700599 -
Flags: review?(kvijayan) → review+
Reporter | ||
Comment 27•8 years ago
|
||
Found yesterday that the similar lazy function parsing issue happens when TokenStream's seek/tell are used. The TokenBuf.setOffsetOfNextRawChar (and requestMoreChars) is modified to sync chars buffer. https://treeherder.mozilla.org/#/jobs?repo=try&revision=4b98db5f463d
Attachment #8694406 -
Attachment is obsolete: true
Attachment #8702607 -
Flags: review?(kvijayan)
Comment 28•8 years ago
|
||
Comment on attachment 8702607 [details] [diff] [review] 1-bug1222086-charsstream.patch Review of attachment 8702607 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/frontend/BytecodeCompiler.cpp @@ +233,2 @@ > /* foldConstants = */ false, (Parser<SyntaxParseHandler>*) nullptr, > + Handle<LazyScript*>(nullptr)); Just a question. There are many places where you convert lazyscript from being a raw pointer to rooted behaviour (using Rooted and Handle<LazyScript*>). Why is this necessary now when it wasn't before?
Attachment #8702607 -
Flags: review?(kvijayan) → review+
Updated•7 years ago
|
Whiteboard: [qf]
Updated•7 years ago
|
Whiteboard: [qf] → [qf-]
Updated•7 years ago
|
Whiteboard: [qf-] → [qf:p1]
Updated•7 years ago
|
Whiteboard: [qf:p1] → [qf:p3]
Updated•2 years ago
|
Performance Impact: --- → P3
Whiteboard: [qf:p3]
Reporter | ||
Updated•2 years ago
|
Assignee: ydelendik → nobody
Updated•2 years ago
|
Severity: normal → S3
You need to log in
before you can comment on or make changes to this bug.
Description
•