Index: src/background-parser-thread.cc |
diff --git a/src/background-parser-thread.cc b/src/background-parser-thread.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..86b8e7fcc7a9bd27ceda752ce2778719d5cf6162 |
--- /dev/null |
+++ b/src/background-parser-thread.cc |
@@ -0,0 +1,106 @@ |
+// Copyright 2014 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "src/background-parser-thread.h" |
+ |
+#include "src/parser.h" |
+ |
+namespace v8 { |
+namespace internal { |
+ |
+static const int kBackgroundParserThreadStackSize = 64 * KB; |
+ |
+// To be called on the main thread. |
+class FinalizeParsingTask : public v8::Task { |
+ public: |
+ FinalizeParsingTask(ScriptCompiler::StreamedSource* source, Isolate* isolate, |
+ ScriptCompiler::StreamingCompleteCallback callback, |
+ void* callback_data) |
+ : source_(source), |
+ isolate_(isolate), |
+ callback_(callback), |
+ callback_data_(callback_data) {} |
+ |
+ virtual void Run() V8_OVERRIDE { |
+ // The source is now ready for compilation. For that, we need to pass the |
+ // control back to the embedder, to get Context etc. set up correctly. |
+ callback_(source_, callback_data_); |
+ } |
+ |
+ private: |
+ ScriptCompiler::StreamedSource* source_; |
+ Isolate* isolate_; |
+ ScriptCompiler::StreamingCompleteCallback callback_; |
+ void* callback_data_; |
+}; |
+ |
+ |
+void BackgroundParsingTask::Run() { |
+ uintptr_t limit = |
+ reinterpret_cast<uintptr_t>(&limit) - kBackgroundParserThreadStackSize; |
+ Parser parser(source_->info, limit, hash_seed_); |
+ parser.set_allow_lazy(allow_lazy_); |
+ parser.ParseOnBackground(); |
+ |
+ if (script_data_ != NULL) { |
+ source_->cached_data = new ScriptCompiler::CachedData( |
+ script_data_->data(), script_data_->length(), |
+ ScriptCompiler::CachedData::BufferOwned); |
+ script_data_->ReleaseDataOwnership(); |
+ delete script_data_; |
+ script_data_ = NULL; |
+ } |
+ |
+ // The task is destroyed automatically. |
+ V8::GetCurrentPlatform()->CallOnForegroundThread( |
+ reinterpret_cast<v8::Isolate*>(isolate_), |
+ new FinalizeParsingTask(source_, isolate_, callback_, callback_data_)); |
+} |
+ |
+ |
+BackgroundParserThread::BackgroundParserThread() |
+ : Thread(Thread::Options("v8::BackgroundParserThread", |
+ kBackgroundParserThreadStackSize)), |
+ task_(NULL), |
+ have_work_(0), |
+ should_stop_(false) {} |
+ |
+ |
+void BackgroundParserThread::Run() { |
+ DisallowHeapAllocation no_allocation; |
+ DisallowHandleAllocation no_handles; |
+ DisallowHandleDereference no_deref; |
+ |
+ while (true) { |
+ have_work_.Wait(); |
+ if (should_stop_) { |
+ break; |
+ } |
+ DCHECK(task_ != NULL); |
+ task_->Run(); |
+ delete task_; |
+ task_ = NULL; |
+ } |
+} |
+ |
+ |
+void BackgroundParserThread::Stop() { |
+ should_stop_ = true; |
+ have_work_.Signal(); |
+ Join(); |
+} |
+ |
+ |
+void BackgroundParserThread::SetTask(BackgroundParsingTask* task) { |
+ // This can only be called when the thread is not already running a task. The |
+ // upper layer will take care of not tryng to add a task before the previous |
+ // one is done. TODO(marja): In the future we'll we want to parse multiple |
+ // scripts on the background. We might need several background threads to |
+ // distribute the tasks to. |
+ DCHECK(task_ == NULL); |
+ task_ = task; |
+ have_work_.Signal(); |
+} |
+} |
+} // namespace v8::internal |