Chromium Code Reviews| Index: src/parser-thread.cc |
| diff --git a/src/parser-thread.cc b/src/parser-thread.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..27b7af26b4f3bf7b863b90f8b0bc4dbf15ef7bdb |
| --- /dev/null |
| +++ b/src/parser-thread.cc |
| @@ -0,0 +1,218 @@ |
| +// Copyright 2014 the V8 project authors. All rights reserved. |
| +// Redistribution and use in source and binary forms, with or without |
| +// modification, are permitted provided that the following conditions are |
| +// met: |
| +// |
| +// * Redistributions of source code must retain the above copyright |
| +// notice, this list of conditions and the following disclaimer. |
| +// * Redistributions in binary form must reproduce the above |
| +// copyright notice, this list of conditions and the following |
| +// disclaimer in the documentation and/or other materials provided |
| +// with the distribution. |
| +// * Neither the name of Google Inc. nor the names of its |
| +// contributors may be used to endorse or promote products derived |
| +// from this software without specific prior written permission. |
| +// |
| +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| + |
| +#include "parser-thread.h" |
| + |
| +#include "api.h" |
| +#include "platform/condition-variable.h" |
| +#include "preparse-data.h" |
| +#include "scanner-character-streams.h" |
| +#include "unbound-queue.h" |
| + |
| +namespace v8 { |
| +namespace internal { |
| + |
| +static const int kFastParserThreadStackSize = 64 * KB; |
| + |
| +class BackgroundParsingTask { |
| + public: |
| + BackgroundParsingTask(Utf16CharacterStream* stream, |
| + bool allow_harmony_scoping, |
| + bool allow_modules, |
| + bool allow_natives_syntax, |
| + bool allow_generators, |
| + bool allow_for_of, |
| + bool allow_harmony_numeric_literals) |
| + : stream_(stream), |
| + result_(PreParser::kPreParseSuccess), |
| + allow_harmony_scoping_(allow_harmony_scoping), |
| + allow_modules_(allow_modules), |
| + allow_natives_syntax_(allow_natives_syntax), |
| + allow_generators_(allow_generators), |
| + allow_for_of_(allow_for_of), |
| + allow_harmony_numeric_literals_(allow_harmony_numeric_literals) {} |
| + |
| + |
| + void Produce(int start, int end, int literals, |
| + int properties, StrictMode strict_mode) { |
| + LockGuard<Mutex> lock_guard(&mutex_); |
| + LazyFunction function(start, end, literals, properties, strict_mode); |
| + data_.Enqueue(function); |
| + have_data_.NotifyOne(); |
| + } |
| + |
| + |
| + void Consume(int* start, int* end, int* literals, |
| + int* properties, StrictMode* strict_mode) { |
| + LockGuard<Mutex> lock_guard(&mutex_); |
| + if (data_.IsEmpty()) |
| + have_data_.Wait(&mutex_); // Implicitly unlocks and locks the mutex. |
| + ASSERT(!data_.IsEmpty()); |
| + LazyFunction function; |
| + data_.Dequeue(&function); |
| + *start = function.start; |
| + *end = function.end; |
| + *literals = function.literals; |
| + *properties = function.properties; |
| + *strict_mode = function.strict_mode; |
| + } |
| + |
| + |
| + void Run(FastParserThread* thread) { |
| + DisallowHeapAllocation no_allocation; |
| + DisallowHandleAllocation no_handles; |
| + DisallowHandleDereference no_deref; |
| + UnicodeCache unicode_cache; |
| + Scanner scanner(&unicode_cache); |
| + uintptr_t limit = |
| + reinterpret_cast<uintptr_t>(&limit) - kFastParserThreadStackSize; |
| + PreParser preparser(&scanner, &recorder_, limit, thread); |
| + preparser.set_allow_lazy(true); |
|
ulan
2014/04/23 10:18:20
Would it be worthwhile to put these flags into a s
Sven Panne
2014/04/23 10:36:29
+1 for this proposal, see http://refactoring.com/c
|
| + preparser.set_allow_harmony_scoping(allow_harmony_scoping_); |
| + preparser.set_allow_modules(allow_modules_); |
| + preparser.set_allow_natives_syntax(allow_natives_syntax_); |
| + preparser.set_allow_generators(allow_generators_); |
| + preparser.set_allow_for_of(allow_for_of_); |
| + preparser.set_allow_harmony_numeric_literals( |
| + allow_harmony_numeric_literals_); |
| + scanner.Initialize(stream_); |
| + result_ = preparser.PreParseProgram(); |
| + |
| + // Queue a dummy data element, so that the Parser doesn't wait forever if it |
| + // expects the thread to produce more data than it will. (For example, when |
| + // the thread parses a function and encounters an error.) |
| + Produce(-1, -1, -1, -1, SLOPPY); |
| + } |
| + |
| + private: |
| + friend class FastParserThread; |
| + struct LazyFunction { |
| + int start; |
| + int end; |
| + int literals; |
| + int properties; |
| + StrictMode strict_mode; |
| + LazyFunction(int s, int e, int l, int p, StrictMode st) |
| + : start(s), end(e), literals(l), properties(p), strict_mode(st) {} |
| + LazyFunction() |
| + : start(-1), |
| + end(-1), |
| + literals(-1), |
| + properties(-1), |
| + strict_mode(SLOPPY) {} |
| + }; |
| + |
| + Utf16CharacterStream* stream_; |
| + SingletonLogger recorder_; |
| + Mutex mutex_; |
| + ConditionVariable have_data_; |
| + UnboundQueue<LazyFunction> data_; |
| + PreParser::PreParseResult result_; |
| + bool allow_harmony_scoping_; |
| + bool allow_modules_; |
| + bool allow_natives_syntax_; |
| + bool allow_generators_; |
| + bool allow_for_of_; |
| + bool allow_harmony_numeric_literals_; |
| +}; |
| + |
| + |
| +FastParserThread::FastParserThread() |
| + : Thread( |
| + Thread::Options("v8::FastParserThread", kFastParserThreadStackSize)), |
| + current_task_(NULL), |
| + have_work_(0), |
| + work_done_(0), |
| + should_stop_(false) {} |
| + |
| + |
| +void FastParserThread::StartBackgroundParsing( |
| + Utf16CharacterStream* stream, bool allow_harmony_scoping, |
| + bool allow_modules, bool allow_natives_syntax, bool allow_generators, |
| + bool allow_for_of, bool allow_harmony_numeric_literals) { |
| + ASSERT(current_task_ == NULL); |
| + current_task_ = new BackgroundParsingTask( |
| + stream, allow_harmony_scoping, allow_modules, allow_natives_syntax, |
| + allow_generators, allow_for_of, allow_harmony_numeric_literals); |
| + have_work_.Signal(); |
| +} |
| + |
| + |
| +void FastParserThread::FinishBackgroundParsing() { |
| + work_done_.Wait(); |
| + delete current_task_; |
|
Michael Starzinger
2014/04/23 09:07:10
This deletes the background parsing task, but I ca
|
| + current_task_ = NULL; |
| +} |
| + |
| + |
| +void FastParserThread::Run() { |
| + while (true) { |
| + have_work_.Wait(); |
| + if (should_stop_) { |
| + break; |
| + } |
| + ASSERT(current_task_ != NULL); |
| + current_task_->Run(this); |
| + work_done_.Signal(); |
| + } |
| +} |
| + |
| + |
| +void FastParserThread::Stop() { |
| + should_stop_ = true; |
| + have_work_.Signal(); |
| + Join(); |
| +} |
| + |
| + |
| +void FastParserThread::Produce(int start, int end, int literals, int properties, |
| + StrictMode strict_mode) { |
| + ASSERT(current_task_); |
| + current_task_->Produce(start, end, literals, properties, strict_mode); |
| +} |
| + |
| + |
| +void FastParserThread::Consume(int* start, int* end, int* literals, |
| + int* properties, StrictMode* strict_mode) { |
| + ASSERT(current_task_); |
| + current_task_->Consume(start, end, literals, properties, strict_mode); |
| +} |
| + |
| + |
| +PreParser::PreParseResult FastParserThread::result() const { |
| + ASSERT(current_task_); |
| + return current_task_->result_; |
| +} |
| + |
| + |
| +const SingletonLogger* FastParserThread::recorder() const { |
| + ASSERT(current_task_); |
| + return &(current_task_->recorder_); |
| +} |
| + |
| + |
| +} } // namespace v8::internal |