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