1// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_OPTIMIZING_COMPILER_THREAD_H_
29#define V8_OPTIMIZING_COMPILER_THREAD_H_
30
31#include "atomicops.h"
32#include "flags.h"
33#include "list.h"
34#include "platform.h"
35#include "platform/mutex.h"
36#include "platform/time.h"
37#include "unbound-queue-inl.h"
38
39namespace v8 {
40namespace internal {
41
42class HOptimizedGraphBuilder;
43class RecompileJob;
44class SharedFunctionInfo;
45
46class OptimizingCompilerThread : public Thread {
47 public:
48  explicit OptimizingCompilerThread(Isolate *isolate) :
49      Thread("OptimizingCompilerThread"),
50#ifdef DEBUG
51      thread_id_(0),
52#endif
53      isolate_(isolate),
54      stop_semaphore_(0),
55      input_queue_semaphore_(0),
56      input_queue_capacity_(FLAG_concurrent_recompilation_queue_length),
57      input_queue_length_(0),
58      input_queue_shift_(0),
59      osr_buffer_capacity_(FLAG_concurrent_recompilation_queue_length + 4),
60      osr_buffer_cursor_(0),
61      osr_hits_(0),
62      osr_attempts_(0),
63      blocked_jobs_(0) {
64    NoBarrier_Store(&stop_thread_, static_cast<AtomicWord>(CONTINUE));
65    input_queue_ = NewArray<RecompileJob*>(input_queue_capacity_);
66    if (FLAG_concurrent_osr) {
67      // Allocate and mark OSR buffer slots as empty.
68      osr_buffer_ = NewArray<RecompileJob*>(osr_buffer_capacity_);
69      for (int i = 0; i < osr_buffer_capacity_; i++) osr_buffer_[i] = NULL;
70    }
71  }
72
73  ~OptimizingCompilerThread();
74
75  void Run();
76  void Stop();
77  void Flush();
78  void QueueForOptimization(RecompileJob* optimizing_compiler);
79  void Unblock();
80  void InstallOptimizedFunctions();
81  RecompileJob* FindReadyOSRCandidate(Handle<JSFunction> function,
82                                      uint32_t osr_pc_offset);
83  bool IsQueuedForOSR(Handle<JSFunction> function, uint32_t osr_pc_offset);
84
85  bool IsQueuedForOSR(JSFunction* function);
86
87  inline bool IsQueueAvailable() {
88    LockGuard<Mutex> access_input_queue(&input_queue_mutex_);
89    return input_queue_length_ < input_queue_capacity_;
90  }
91
92  inline void AgeBufferedOsrJobs() {
93    // Advance cursor of the cyclic buffer to next empty slot or stale OSR job.
94    // Dispose said OSR job in the latter case.  Calling this on every GC
95    // should make sure that we do not hold onto stale jobs indefinitely.
96    AddToOsrBuffer(NULL);
97  }
98
99  static bool Enabled(int max_available) {
100    return (FLAG_concurrent_recompilation && max_available > 1);
101  }
102
103#ifdef DEBUG
104  static bool IsOptimizerThread(Isolate* isolate);
105  bool IsOptimizerThread();
106#endif
107
108 private:
109  enum StopFlag { CONTINUE, STOP, FLUSH };
110
111  void FlushInputQueue(bool restore_function_code);
112  void FlushOutputQueue(bool restore_function_code);
113  void FlushOsrBuffer(bool restore_function_code);
114  void CompileNext();
115  RecompileJob* NextInput();
116
117  // Add a recompilation task for OSR to the cyclic buffer, awaiting OSR entry.
118  // Tasks evicted from the cyclic buffer are discarded.
119  void AddToOsrBuffer(RecompileJob* compiler);
120
121  inline int InputQueueIndex(int i) {
122    int result = (i + input_queue_shift_) % input_queue_capacity_;
123    ASSERT_LE(0, result);
124    ASSERT_LT(result, input_queue_capacity_);
125    return result;
126  }
127
128#ifdef DEBUG
129  int thread_id_;
130  Mutex thread_id_mutex_;
131#endif
132
133  Isolate* isolate_;
134  Semaphore stop_semaphore_;
135  Semaphore input_queue_semaphore_;
136
137  // Circular queue of incoming recompilation tasks (including OSR).
138  RecompileJob** input_queue_;
139  int input_queue_capacity_;
140  int input_queue_length_;
141  int input_queue_shift_;
142  Mutex input_queue_mutex_;
143
144  // Queue of recompilation tasks ready to be installed (excluding OSR).
145  UnboundQueue<RecompileJob*> output_queue_;
146
147  // Cyclic buffer of recompilation tasks for OSR.
148  RecompileJob** osr_buffer_;
149  int osr_buffer_capacity_;
150  int osr_buffer_cursor_;
151
152  volatile AtomicWord stop_thread_;
153  TimeDelta time_spent_compiling_;
154  TimeDelta time_spent_total_;
155
156  int osr_hits_;
157  int osr_attempts_;
158
159  int blocked_jobs_;
160};
161
162} }  // namespace v8::internal
163
164#endif  // V8_OPTIMIZING_COMPILER_THREAD_H_
165