aboutsummaryrefslogtreecommitdiff
path: root/src/compiler-dispatcher/compiler-dispatcher.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler-dispatcher/compiler-dispatcher.h')
-rw-r--r--src/compiler-dispatcher/compiler-dispatcher.h201
1 files changed, 201 insertions, 0 deletions
diff --git a/src/compiler-dispatcher/compiler-dispatcher.h b/src/compiler-dispatcher/compiler-dispatcher.h
new file mode 100644
index 00000000..6347aa89
--- /dev/null
+++ b/src/compiler-dispatcher/compiler-dispatcher.h
@@ -0,0 +1,201 @@
+// Copyright 2016 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.
+
+#ifndef V8_COMPILER_DISPATCHER_COMPILER_DISPATCHER_H_
+#define V8_COMPILER_DISPATCHER_COMPILER_DISPATCHER_H_
+
+#include <map>
+#include <memory>
+#include <unordered_set>
+#include <utility>
+
+#include "src/base/atomic-utils.h"
+#include "src/base/macros.h"
+#include "src/base/platform/condition-variable.h"
+#include "src/base/platform/mutex.h"
+#include "src/base/platform/semaphore.h"
+#include "src/globals.h"
+#include "testing/gtest/include/gtest/gtest_prod.h"
+
+namespace v8 {
+
+class Platform;
+enum class MemoryPressureLevel;
+
+namespace internal {
+
+class CancelableTaskManager;
+class CompilerDispatcherJob;
+class CompilerDispatcherTracer;
+class DeferredHandles;
+class FunctionLiteral;
+class Isolate;
+class SharedFunctionInfo;
+class Zone;
+
+template <typename T>
+class Handle;
+
+// The CompilerDispatcher uses a combination of idle tasks and background tasks
+// to parse and compile lazily parsed functions.
+//
+// As both parsing and compilation currently requires a preparation and
+// finalization step that happens on the main thread, every task has to be
+// advanced during idle time first. Depending on the properties of the task, it
+// can then be parsed or compiled on either background threads, or during idle
+// time. Last, it has to be finalized during idle time again.
+//
+// CompilerDispatcher::jobs_ maintains the list of all CompilerDispatcherJobs
+// the CompilerDispatcher knows about.
+//
+// CompilerDispatcher::pending_background_jobs_ contains the set of
+// CompilerDispatcherJobs that can be processed on a background thread.
+//
+// CompilerDispatcher::running_background_jobs_ contains the set of
+// CompilerDispatcherJobs that are currently being processed on a background
+// thread.
+//
+// CompilerDispatcher::DoIdleWork tries to advance as many jobs out of jobs_ as
+// possible during idle time. If a job can't be advanced, but is suitable for
+// background processing, it fires off background threads.
+//
+// CompilerDispatcher::DoBackgroundWork advances one of the pending jobs, and
+// then spins of another idle task to potentially do the final step on the main
+// thread.
+class V8_EXPORT_PRIVATE CompilerDispatcher {
+ public:
+ enum class BlockingBehavior { kBlock, kDontBlock };
+
+ CompilerDispatcher(Isolate* isolate, Platform* platform,
+ size_t max_stack_size);
+ ~CompilerDispatcher();
+
+ // Returns true if the compiler dispatcher is enabled.
+ bool IsEnabled() const;
+
+ // Enqueue a job for parse and compile. Returns true if a job was enqueued.
+ bool Enqueue(Handle<SharedFunctionInfo> function);
+
+ // Like Enqueue, but also advances the job so that it can potentially
+ // continue running on a background thread (if at all possible). Returns
+ // true if the job was enqueued.
+ bool EnqueueAndStep(Handle<SharedFunctionInfo> function);
+
+ // Enqueue a job for compilation. Function must have already been parsed and
+ // analyzed and be ready for compilation. Returns true if a job was enqueued.
+ bool Enqueue(Handle<Script> script, Handle<SharedFunctionInfo> function,
+ FunctionLiteral* literal, std::shared_ptr<Zone> parse_zone,
+ std::shared_ptr<DeferredHandles> parse_handles,
+ std::shared_ptr<DeferredHandles> compile_handles);
+
+ // Like Enqueue, but also advances the job so that it can potentially
+ // continue running on a background thread (if at all possible). Returns
+ // true if the job was enqueued.
+ bool EnqueueAndStep(Handle<Script> script,
+ Handle<SharedFunctionInfo> function,
+ FunctionLiteral* literal,
+ std::shared_ptr<Zone> parse_zone,
+ std::shared_ptr<DeferredHandles> parse_handles,
+ std::shared_ptr<DeferredHandles> compile_handles);
+
+ // Returns true if there is a pending job for the given function.
+ bool IsEnqueued(Handle<SharedFunctionInfo> function) const;
+
+ // Blocks until the given function is compiled (and does so as fast as
+ // possible). Returns true if the compile job was successful.
+ bool FinishNow(Handle<SharedFunctionInfo> function);
+
+ // Aborts a given job. Blocks if requested.
+ void Abort(Handle<SharedFunctionInfo> function, BlockingBehavior blocking);
+
+ // Aborts all jobs. Blocks if requested.
+ void AbortAll(BlockingBehavior blocking);
+
+ // Memory pressure notifications from the embedder.
+ void MemoryPressureNotification(v8::MemoryPressureLevel level,
+ bool is_isolate_locked);
+
+ private:
+ FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStep);
+ FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStepTwice);
+ FRIEND_TEST(CompilerDispatcherTest, EnqueueParsed);
+ FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStepParsed);
+ FRIEND_TEST(CompilerDispatcherTest, IdleTaskSmallIdleTime);
+ FRIEND_TEST(CompilerDispatcherTest, CompileOnBackgroundThread);
+ FRIEND_TEST(CompilerDispatcherTest, FinishNowWithBackgroundTask);
+ FRIEND_TEST(CompilerDispatcherTest, AsyncAbortAllPendingBackgroundTask);
+ FRIEND_TEST(CompilerDispatcherTest, AsyncAbortAllRunningBackgroundTask);
+ FRIEND_TEST(CompilerDispatcherTest, FinishNowDuringAbortAll);
+
+ typedef std::multimap<std::pair<int, int>,
+ std::unique_ptr<CompilerDispatcherJob>>
+ JobMap;
+ class AbortTask;
+ class BackgroundTask;
+ class IdleTask;
+
+ void WaitForJobIfRunningOnBackground(CompilerDispatcherJob* job);
+ void AbortInactiveJobs();
+ bool CanEnqueue(Handle<SharedFunctionInfo> function);
+ JobMap::const_iterator GetJobFor(Handle<SharedFunctionInfo> shared) const;
+ void ConsiderJobForBackgroundProcessing(CompilerDispatcherJob* job);
+ void ScheduleMoreBackgroundTasksIfNeeded();
+ void ScheduleIdleTaskFromAnyThread();
+ void ScheduleIdleTaskIfNeeded();
+ void ScheduleAbortTask();
+ void DoBackgroundWork();
+ void DoIdleWork(double deadline_in_seconds);
+
+ Isolate* isolate_;
+ Platform* platform_;
+ size_t max_stack_size_;
+
+ // Copy of FLAG_trace_compiler_dispatcher to allow for access from any thread.
+ bool trace_compiler_dispatcher_;
+
+ std::unique_ptr<CompilerDispatcherTracer> tracer_;
+
+ std::unique_ptr<CancelableTaskManager> task_manager_;
+
+ // Mapping from (script id, function literal id) to job. We use a multimap,
+ // as script id is not necessarily unique.
+ JobMap jobs_;
+
+ base::AtomicValue<v8::MemoryPressureLevel> memory_pressure_level_;
+
+ // The following members can be accessed from any thread. Methods need to hold
+ // the mutex |mutex_| while accessing them.
+ base::Mutex mutex_;
+
+ // True if the dispatcher is in the process of aborting running tasks.
+ bool abort_;
+
+ bool idle_task_scheduled_;
+
+ // Number of currently scheduled BackgroundTask objects.
+ size_t num_scheduled_background_tasks_;
+
+ // The set of CompilerDispatcherJobs that can be advanced on any thread.
+ std::unordered_set<CompilerDispatcherJob*> pending_background_jobs_;
+
+ // The set of CompilerDispatcherJobs currently processed on background
+ // threads.
+ std::unordered_set<CompilerDispatcherJob*> running_background_jobs_;
+
+ // If not nullptr, then the main thread waits for the task processing
+ // this job, and blocks on the ConditionVariable main_thread_blocking_signal_.
+ CompilerDispatcherJob* main_thread_blocking_on_job_;
+ base::ConditionVariable main_thread_blocking_signal_;
+
+ // Test support.
+ base::AtomicValue<bool> block_for_testing_;
+ base::Semaphore semaphore_for_testing_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompilerDispatcher);
+};
+
+} // namespace internal
+} // namespace v8
+
+#endif // V8_COMPILER_DISPATCHER_COMPILER_DISPATCHER_H_