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_OPTIMIZING_COMPILER_THREAD_H_
6#define V8_OPTIMIZING_COMPILER_THREAD_H_
7
8#include "src/base/atomicops.h"
9#include "src/base/platform/mutex.h"
10#include "src/base/platform/platform.h"
11#include "src/base/platform/time.h"
12#include "src/flags.h"
13#include "src/list.h"
14#include "src/unbound-queue-inl.h"
15
16namespace v8 {
17namespace internal {
18
19class HOptimizedGraphBuilder;
20class OptimizedCompileJob;
21class SharedFunctionInfo;
22
23class OptimizingCompilerThread : public base::Thread {
24 public:
25  explicit OptimizingCompilerThread(Isolate* isolate)
26      : Thread(Options("OptimizingCompilerThread")),
27#ifdef DEBUG
28        thread_id_(0),
29#endif
30        isolate_(isolate),
31        stop_semaphore_(0),
32        input_queue_semaphore_(0),
33        input_queue_capacity_(FLAG_concurrent_recompilation_queue_length),
34        input_queue_length_(0),
35        input_queue_shift_(0),
36        osr_buffer_capacity_(FLAG_concurrent_recompilation_queue_length + 4),
37        osr_buffer_cursor_(0),
38        osr_hits_(0),
39        osr_attempts_(0),
40        blocked_jobs_(0) {
41    base::NoBarrier_Store(&stop_thread_,
42                          static_cast<base::AtomicWord>(CONTINUE));
43    input_queue_ = NewArray<OptimizedCompileJob*>(input_queue_capacity_);
44    if (FLAG_concurrent_osr) {
45      // Allocate and mark OSR buffer slots as empty.
46      osr_buffer_ = NewArray<OptimizedCompileJob*>(osr_buffer_capacity_);
47      for (int i = 0; i < osr_buffer_capacity_; i++) osr_buffer_[i] = NULL;
48    }
49  }
50
51  ~OptimizingCompilerThread();
52
53  void Run();
54  void Stop();
55  void Flush();
56  void QueueForOptimization(OptimizedCompileJob* optimizing_compiler);
57  void Unblock();
58  void InstallOptimizedFunctions();
59  OptimizedCompileJob* FindReadyOSRCandidate(Handle<JSFunction> function,
60                                             BailoutId osr_ast_id);
61  bool IsQueuedForOSR(Handle<JSFunction> function, BailoutId osr_ast_id);
62
63  bool IsQueuedForOSR(JSFunction* function);
64
65  inline bool IsQueueAvailable() {
66    base::LockGuard<base::Mutex> access_input_queue(&input_queue_mutex_);
67    return input_queue_length_ < input_queue_capacity_;
68  }
69
70  inline void AgeBufferedOsrJobs() {
71    // Advance cursor of the cyclic buffer to next empty slot or stale OSR job.
72    // Dispose said OSR job in the latter case.  Calling this on every GC
73    // should make sure that we do not hold onto stale jobs indefinitely.
74    AddToOsrBuffer(NULL);
75  }
76
77  static bool Enabled(int max_available) {
78    return (FLAG_concurrent_recompilation && max_available > 1);
79  }
80
81#ifdef DEBUG
82  static bool IsOptimizerThread(Isolate* isolate);
83  bool IsOptimizerThread();
84#endif
85
86 private:
87  enum StopFlag { CONTINUE, STOP, FLUSH };
88
89  void FlushInputQueue(bool restore_function_code);
90  void FlushOutputQueue(bool restore_function_code);
91  void FlushOsrBuffer(bool restore_function_code);
92  void CompileNext();
93  OptimizedCompileJob* NextInput();
94
95  // Add a recompilation task for OSR to the cyclic buffer, awaiting OSR entry.
96  // Tasks evicted from the cyclic buffer are discarded.
97  void AddToOsrBuffer(OptimizedCompileJob* compiler);
98
99  inline int InputQueueIndex(int i) {
100    int result = (i + input_queue_shift_) % input_queue_capacity_;
101    DCHECK_LE(0, result);
102    DCHECK_LT(result, input_queue_capacity_);
103    return result;
104  }
105
106#ifdef DEBUG
107  int thread_id_;
108  base::Mutex thread_id_mutex_;
109#endif
110
111  Isolate* isolate_;
112  base::Semaphore stop_semaphore_;
113  base::Semaphore input_queue_semaphore_;
114
115  // Circular queue of incoming recompilation tasks (including OSR).
116  OptimizedCompileJob** input_queue_;
117  int input_queue_capacity_;
118  int input_queue_length_;
119  int input_queue_shift_;
120  base::Mutex input_queue_mutex_;
121
122  // Queue of recompilation tasks ready to be installed (excluding OSR).
123  UnboundQueue<OptimizedCompileJob*> output_queue_;
124
125  // Cyclic buffer of recompilation tasks for OSR.
126  OptimizedCompileJob** osr_buffer_;
127  int osr_buffer_capacity_;
128  int osr_buffer_cursor_;
129
130  volatile base::AtomicWord stop_thread_;
131  base::TimeDelta time_spent_compiling_;
132  base::TimeDelta time_spent_total_;
133
134  int osr_hits_;
135  int osr_attempts_;
136
137  int blocked_jobs_;
138};
139
140} }  // namespace v8::internal
141
142#endif  // V8_OPTIMIZING_COMPILER_THREAD_H_
143