1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_DISPATCHER_OPTIMIZING_COMPILE_DISPATCHER_H_
6 #define V8_COMPILER_DISPATCHER_OPTIMIZING_COMPILE_DISPATCHER_H_
7 
8 #include <atomic>
9 #include <queue>
10 
11 #include "src/base/platform/condition-variable.h"
12 #include "src/base/platform/mutex.h"
13 #include "src/base/platform/platform.h"
14 #include "src/common/globals.h"
15 #include "src/flags/flags.h"
16 #include "src/utils/allocation.h"
17 
18 namespace v8 {
19 namespace internal {
20 
21 class LocalHeap;
22 class OptimizedCompilationJob;
23 class RuntimeCallStats;
24 class SharedFunctionInfo;
25 
26 class V8_EXPORT_PRIVATE OptimizingCompileDispatcher {
27  public:
OptimizingCompileDispatcher(Isolate * isolate)28   explicit OptimizingCompileDispatcher(Isolate* isolate)
29       : isolate_(isolate),
30         input_queue_capacity_(FLAG_concurrent_recompilation_queue_length),
31         input_queue_length_(0),
32         input_queue_shift_(0),
33         mode_(COMPILE),
34         blocked_jobs_(0),
35         ref_count_(0),
36         recompilation_delay_(FLAG_concurrent_recompilation_delay) {
37     input_queue_ = NewArray<OptimizedCompilationJob*>(input_queue_capacity_);
38   }
39 
40   ~OptimizingCompileDispatcher();
41 
42   void Stop();
43   void Flush(BlockingBehavior blocking_behavior);
44   // Takes ownership of |job|.
45   void QueueForOptimization(OptimizedCompilationJob* job);
46   void Unblock();
47   void InstallOptimizedFunctions();
48 
IsQueueAvailable()49   inline bool IsQueueAvailable() {
50     base::MutexGuard access_input_queue(&input_queue_mutex_);
51     return input_queue_length_ < input_queue_capacity_;
52   }
53 
Enabled()54   static bool Enabled() { return FLAG_concurrent_recompilation; }
55 
56  private:
57   class CompileTask;
58 
59   enum ModeFlag { COMPILE, FLUSH };
60 
61   void FlushOutputQueue(bool restore_function_code);
62   void CompileNext(OptimizedCompilationJob* job, RuntimeCallStats* stats,
63                    LocalIsolate* local_isolate);
64   OptimizedCompilationJob* NextInput(LocalIsolate* local_isolate,
65                                      bool check_if_flushing = false);
66 
InputQueueIndex(int i)67   inline int InputQueueIndex(int i) {
68     int result = (i + input_queue_shift_) % input_queue_capacity_;
69     DCHECK_LE(0, result);
70     DCHECK_LT(result, input_queue_capacity_);
71     return result;
72   }
73 
74   Isolate* isolate_;
75 
76   // Circular queue of incoming recompilation tasks (including OSR).
77   OptimizedCompilationJob** input_queue_;
78   int input_queue_capacity_;
79   int input_queue_length_;
80   int input_queue_shift_;
81   base::Mutex input_queue_mutex_;
82 
83   // Queue of recompilation tasks ready to be installed (excluding OSR).
84   std::queue<OptimizedCompilationJob*> output_queue_;
85   // Used for job based recompilation which has multiple producers on
86   // different threads.
87   base::Mutex output_queue_mutex_;
88 
89   std::atomic<ModeFlag> mode_;
90 
91   int blocked_jobs_;
92 
93   int ref_count_;
94   base::Mutex ref_count_mutex_;
95   base::ConditionVariable ref_count_zero_;
96 
97   // Copy of FLAG_concurrent_recompilation_delay that will be used from the
98   // background thread.
99   //
100   // Since flags might get modified while the background thread is running, it
101   // is not safe to access them directly.
102   int recompilation_delay_;
103 };
104 }  // namespace internal
105 }  // namespace v8
106 
107 #endif  // V8_COMPILER_DISPATCHER_OPTIMIZING_COMPILE_DISPATCHER_H_
108