1304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
5304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org#ifndef V8_OPTIMIZING_COMPILER_THREAD_H_
6304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org#define V8_OPTIMIZING_COMPILER_THREAD_H_
7304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
81e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/atomicops.h"
95de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/mutex.h"
105de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/platform.h"
115de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/time.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/flags.h"
13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/list.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/unbound-queue-inl.h"
15304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
16304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.orgnamespace v8 {
17304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.orgnamespace internal {
18304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
19a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgclass HOptimizedGraphBuilder;
204954674151afa960af66efb4831df06bde727333yangguo@chromium.orgclass OptimizedCompileJob;
21fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgclass SharedFunctionInfo;
22304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
235de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.orgclass OptimizingCompilerThread : public base::Thread {
24304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org public:
255e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  explicit OptimizingCompilerThread(Isolate* isolate)
265e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      : Thread(Options("OptimizingCompilerThread")),
271f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org#ifdef DEBUG
285e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        thread_id_(0),
291f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org#endif
305e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        isolate_(isolate),
315e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        stop_semaphore_(0),
325e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        input_queue_semaphore_(0),
335e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        input_queue_capacity_(FLAG_concurrent_recompilation_queue_length),
345e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        input_queue_length_(0),
355e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        input_queue_shift_(0),
365e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        osr_buffer_capacity_(FLAG_concurrent_recompilation_queue_length + 4),
375e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        osr_buffer_cursor_(0),
385e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        osr_hits_(0),
395e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        osr_attempts_(0),
405e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        blocked_jobs_(0) {
411e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org    base::NoBarrier_Store(&stop_thread_,
421e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org                          static_cast<base::AtomicWord>(CONTINUE));
434954674151afa960af66efb4831df06bde727333yangguo@chromium.org    input_queue_ = NewArray<OptimizedCompileJob*>(input_queue_capacity_);
448e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    if (FLAG_concurrent_osr) {
452ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org      // Allocate and mark OSR buffer slots as empty.
464954674151afa960af66efb4831df06bde727333yangguo@chromium.org      osr_buffer_ = NewArray<OptimizedCompileJob*>(osr_buffer_capacity_);
472ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org      for (int i = 0; i < osr_buffer_capacity_; i++) osr_buffer_[i] = NULL;
488e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    }
498e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  }
508e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
512ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org  ~OptimizingCompilerThread();
52304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
53304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  void Run();
54304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  void Stop();
55594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void Flush();
564954674151afa960af66efb4831df06bde727333yangguo@chromium.org  void QueueForOptimization(OptimizedCompileJob* optimizing_compiler);
57a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  void Unblock();
58304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  void InstallOptimizedFunctions();
594954674151afa960af66efb4831df06bde727333yangguo@chromium.org  OptimizedCompileJob* FindReadyOSRCandidate(Handle<JSFunction> function,
604954674151afa960af66efb4831df06bde727333yangguo@chromium.org                                             BailoutId osr_ast_id);
614954674151afa960af66efb4831df06bde727333yangguo@chromium.org  bool IsQueuedForOSR(Handle<JSFunction> function, BailoutId osr_ast_id);
623d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org
63e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org  bool IsQueuedForOSR(JSFunction* function);
64304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
65304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  inline bool IsQueueAvailable() {
665de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org    base::LockGuard<base::Mutex> access_input_queue(&input_queue_mutex_);
672ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org    return input_queue_length_ < input_queue_capacity_;
682ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org  }
692ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org
702ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org  inline void AgeBufferedOsrJobs() {
712ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org    // Advance cursor of the cyclic buffer to next empty slot or stale OSR job.
722ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org    // Dispose said OSR job in the latter case.  Calling this on every GC
732ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org    // should make sure that we do not hold onto stale jobs indefinitely.
742ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org    AddToOsrBuffer(NULL);
75304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  }
76304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
779af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  static bool Enabled(int max_available) {
789af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    return (FLAG_concurrent_recompilation && max_available > 1);
799af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  }
809af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
81304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org#ifdef DEBUG
829af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  static bool IsOptimizerThread(Isolate* isolate);
83304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  bool IsOptimizerThread();
84304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org#endif
85304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
86304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org private:
87594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  enum StopFlag { CONTINUE, STOP, FLUSH };
88594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org
89594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void FlushInputQueue(bool restore_function_code);
90594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void FlushOutputQueue(bool restore_function_code);
918e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  void FlushOsrBuffer(bool restore_function_code);
92594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  void CompileNext();
934954674151afa960af66efb4831df06bde727333yangguo@chromium.org  OptimizedCompileJob* NextInput();
94594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org
958e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  // Add a recompilation task for OSR to the cyclic buffer, awaiting OSR entry.
968e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  // Tasks evicted from the cyclic buffer are discarded.
974954674151afa960af66efb4831df06bde727333yangguo@chromium.org  void AddToOsrBuffer(OptimizedCompileJob* compiler);
982ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org
992ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org  inline int InputQueueIndex(int i) {
1002ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org    int result = (i + input_queue_shift_) % input_queue_capacity_;
101e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_LE(0, result);
102e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_LT(result, input_queue_capacity_);
1032ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org    return result;
1048e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  }
1058e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
1061f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org#ifdef DEBUG
1071f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  int thread_id_;
1085de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::Mutex thread_id_mutex_;
1091f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org#endif
1101f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
111304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  Isolate* isolate_;
1125de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::Semaphore stop_semaphore_;
1135de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::Semaphore input_queue_semaphore_;
1143d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org
1152ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org  // Circular queue of incoming recompilation tasks (including OSR).
1164954674151afa960af66efb4831df06bde727333yangguo@chromium.org  OptimizedCompileJob** input_queue_;
1172ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org  int input_queue_capacity_;
1182ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org  int input_queue_length_;
1192ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org  int input_queue_shift_;
1205de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::Mutex input_queue_mutex_;
1212ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org
1223d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  // Queue of recompilation tasks ready to be installed (excluding OSR).
1234954674151afa960af66efb4831df06bde727333yangguo@chromium.org  UnboundQueue<OptimizedCompileJob*> output_queue_;
1242ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org
1258e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  // Cyclic buffer of recompilation tasks for OSR.
1264954674151afa960af66efb4831df06bde727333yangguo@chromium.org  OptimizedCompileJob** osr_buffer_;
1272ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org  int osr_buffer_capacity_;
1282ed0d029906d9c6f0ae06fe8eb7f1180077ae2b0mstarzinger@chromium.org  int osr_buffer_cursor_;
1293d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org
1301e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org  volatile base::AtomicWord stop_thread_;
1315de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::TimeDelta time_spent_compiling_;
1325de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::TimeDelta time_spent_total_;
1333d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org
1343d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  int osr_hits_;
1353d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  int osr_attempts_;
136a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org
137a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int blocked_jobs_;
138304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org};
139304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
140304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org} }  // namespace v8::internal
141304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
142304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org#endif  // V8_OPTIMIZING_COMPILER_THREAD_H_
143