// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/thread.h"

#include "vm/growable_array.h"
#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/log.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/os_thread.h"
#include "vm/profiler.h"
#include "vm/runtime_entry.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
#include "vm/thread_interrupter.h"
#include "vm/thread_registry.h"

namespace dart {

// The single thread local key which stores all the thread local data
// for a thread.
ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey;
Thread* Thread::thread_list_head_ = NULL;
Mutex* Thread::thread_list_lock_ = NULL;

// Remove |thread| from each isolate's thread registry.
class ThreadPruner : public IsolateVisitor {
 public:
  explicit ThreadPruner(Thread* thread)
      : thread_(thread) {
    ASSERT(thread_ != NULL);
  }

  void VisitIsolate(Isolate* isolate) {
    ThreadRegistry* registry = isolate->thread_registry();
    ASSERT(registry != NULL);
    registry->PruneThread(thread_);
  }
 private:
  Thread* thread_;
};


void Thread::AddThreadToList(Thread* thread) {
  ASSERT(thread != NULL);
  ASSERT(thread->isolate() == NULL);
  ASSERT(thread_list_lock_ != NULL);
  MutexLocker ml(thread_list_lock_);

  ASSERT(thread->thread_list_next_ == NULL);

#if defined(DEBUG)
  {
    // Ensure that we aren't already in the list.
    Thread* current = thread_list_head_;
    while (current != NULL) {
      ASSERT(current != thread);
      current = current->thread_list_next_;
    }
  }
#endif

  // Insert at head of list.
  thread->thread_list_next_ = thread_list_head_;
  thread_list_head_ = thread;
}


void Thread::RemoveThreadFromList(Thread* thread) {
  ASSERT(thread != NULL);
  ASSERT(thread->isolate() == NULL);
  ASSERT(thread_list_lock_ != NULL);
  MutexLocker ml(thread_list_lock_);

  // Handle case where |thread| is head of list.
  if (thread_list_head_ == thread) {
    thread_list_head_ = thread->thread_list_next_;
    thread->thread_list_next_ = NULL;
    return;
  }

  Thread* current = thread_list_head_;
  Thread* previous = NULL;

  // Scan across list and remove |thread|.
  while (current != NULL) {
    previous = current;
    current = current->thread_list_next_;
    if (current == thread) {
      // We found |thread|, remove from list.
      previous->thread_list_next_ = current->thread_list_next_;
      thread->thread_list_next_ = NULL;
      return;
    }
  }

  UNREACHABLE();
}


static void DeleteThread(void* thread) {
  delete reinterpret_cast<Thread*>(thread);
}


void Thread::Shutdown() {
  if (thread_list_lock_ != NULL) {
    delete thread_list_lock_;
    thread_list_lock_ = NULL;
  }
}


Thread::~Thread() {
  // We should cleanly exit any isolate before destruction.
  ASSERT(isolate_ == NULL);
  // Clear |this| from all isolate's thread registry.
  ThreadPruner pruner(this);
  Isolate::VisitIsolates(&pruner);
  delete log_;
  log_ = NULL;
  RemoveThreadFromList(this);
}


void Thread::InitOnceBeforeIsolate() {
  ASSERT(thread_list_lock_ == NULL);
  thread_list_lock_ = new Mutex();
  ASSERT(thread_list_lock_ != NULL);
  ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey);
  thread_key_ = OSThread::CreateThreadLocal(DeleteThread);
  ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey);
  ASSERT(Thread::Current() == NULL);
  // Allocate a new Thread and postpone initialization of VM constants for
  // this first thread.
  Thread* thread = new Thread(false);
  // Verify that current thread was set.
  ASSERT(Thread::Current() == thread);
}


void Thread::InitOnceAfterObjectAndStubCode() {
  Thread* thread = Thread::Current();
  ASSERT(thread != NULL);
  ASSERT(thread->isolate() == Dart::vm_isolate());
  thread->InitVMConstants();
}


void Thread::SetCurrent(Thread* current) {
  OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current));
}


void Thread::EnsureInit() {
  if (Thread::Current() == NULL) {
    // Allocate a new Thread.
    Thread* thread = new Thread();
    // Verify that current thread was set.
    ASSERT(Thread::Current() == thread);
  }
}


#if defined(TARGET_OS_WINDOWS)
void Thread::CleanUp() {
  Thread* current = Current();
  if (current != NULL) {
    SetCurrent(NULL);
    delete current;
  }
}
#endif

#if defined(DEBUG)
#define REUSABLE_HANDLE_SCOPE_INIT(object)                                     \
  reusable_##object##_handle_scope_active_(false),
#else
#define REUSABLE_HANDLE_SCOPE_INIT(object)
#endif  // defined(DEBUG)

#define REUSABLE_HANDLE_INITIALIZERS(object)                                   \
  object##_handle_(NULL),


Thread::Thread(bool init_vm_constants)
    : id_(OSThread::GetCurrentThreadId()),
      thread_interrupt_callback_(NULL),
      thread_interrupt_data_(NULL),
      isolate_(NULL),
      heap_(NULL),
      store_buffer_block_(NULL),
      log_(new class Log()),
      deopt_id_(0),
      vm_tag_(0),
      REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
      REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT)
      reusable_handles_(),
      cha_(NULL),
      no_callback_scope_depth_(0),
      thread_list_next_(NULL) {
  ClearState();

#define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value)    \
  member_name = default_init_value;
CACHED_CONSTANTS_LIST(DEFAULT_INIT)
#undef DEFAULT_INIT

#define DEFAULT_INIT(name)                                                     \
  name##_entry_point_ = 0;
RUNTIME_ENTRY_LIST(DEFAULT_INIT)
#undef DEFAULT_INIT

#define DEFAULT_INIT(returntype, name, ...)                                    \
  name##_entry_point_ = 0;
LEAF_RUNTIME_ENTRY_LIST(DEFAULT_INIT)
#undef DEFAULT_INIT

  if (init_vm_constants) {
    InitVMConstants();
  }
  SetCurrent(this);
  AddThreadToList(this);
}


void Thread::InitVMConstants() {
#define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value)  \
  ASSERT((init_expr)->IsOldObject());
CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP)
#undef ASSERT_VM_HEAP

#define INIT_VALUE(type_name, member_name, init_expr, default_init_value)      \
  ASSERT(member_name == default_init_value);                                   \
  member_name = (init_expr);
CACHED_CONSTANTS_LIST(INIT_VALUE)
#undef INIT_VALUE

#define INIT_VALUE(name)                                                       \
  ASSERT(name##_entry_point_ == 0);                                            \
  name##_entry_point_ = k##name##RuntimeEntry.GetEntryPoint();
RUNTIME_ENTRY_LIST(INIT_VALUE)
#undef INIT_VALUE

#define INIT_VALUE(returntype, name, ...)                                      \
  ASSERT(name##_entry_point_ == 0);                                            \
  name##_entry_point_ = k##name##RuntimeEntry.GetEntryPoint();
LEAF_RUNTIME_ENTRY_LIST(INIT_VALUE)
#undef INIT_VALUE

  // Setup the thread specific reusable handles.
#define REUSABLE_HANDLE_ALLOCATION(object)                                     \
  this->object##_handle_ = this->AllocateReusableHandle<object>();
  REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_ALLOCATION)
#undef REUSABLE_HANDLE_ALLOCATION
}


void Thread::Schedule(Isolate* isolate, bool bypass_safepoint) {
  State st;
  if (isolate->thread_registry()->RestoreStateTo(this, &st, bypass_safepoint)) {
    ASSERT(isolate->thread_registry()->Contains(this));
    state_ = st;
  }
}


void Thread::Unschedule(bool bypass_safepoint) {
  ThreadRegistry* reg = isolate_->thread_registry();
  ASSERT(reg->Contains(this));
  reg->SaveStateFrom(this, state_, bypass_safepoint);
  ClearState();
}


void Thread::EnterIsolate(Isolate* isolate) {
  Thread* thread = Thread::Current();
  ASSERT(thread != NULL);
  ASSERT(thread->isolate() == NULL);
  ASSERT(!isolate->HasMutatorThread());
  thread->isolate_ = isolate;
  isolate->MakeCurrentThreadMutator(thread);
  thread->set_vm_tag(VMTag::kVMTagId);
  ASSERT(thread->store_buffer_block_ == NULL);
  thread->StoreBufferAcquire();
  ASSERT(isolate->heap() != NULL);
  thread->heap_ = isolate->heap();
  thread->Schedule(isolate);
  // TODO(koda): Migrate profiler interface to use Thread.
  Profiler::BeginExecution(isolate);
}


void Thread::ExitIsolate() {
  Thread* thread = Thread::Current();
  // TODO(koda): Audit callers; they should know whether they're in an isolate.
  if (thread == NULL || thread->isolate() == NULL) return;
#if defined(DEBUG)
  ASSERT(!thread->IsAnyReusableHandleScopeActive());
#endif  // DEBUG
  // Clear since GC will not visit the thread once it is unscheduled.
  thread->ClearReusableHandles();
  Isolate* isolate = thread->isolate();
  Profiler::EndExecution(isolate);
  thread->Unschedule();
  // TODO(koda): Move store_buffer_block_ into State.
  thread->StoreBufferRelease();
  if (isolate->is_runnable()) {
    thread->set_vm_tag(VMTag::kIdleTagId);
  } else {
    thread->set_vm_tag(VMTag::kLoadWaitTagId);
  }
  isolate->ClearMutatorThread();
  thread->isolate_ = NULL;
  ASSERT(Isolate::Current() == NULL);
  thread->heap_ = NULL;
}


void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
  Thread* thread = Thread::Current();
  ASSERT(thread != NULL);
  ASSERT(thread->isolate() == NULL);
  thread->isolate_ = isolate;
  ASSERT(thread->store_buffer_block_ == NULL);
  // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge.
  thread->store_buffer_block_ =
      thread->isolate()->store_buffer()->PopEmptyBlock();
  ASSERT(isolate->heap() != NULL);
  thread->heap_ = isolate->heap();
  ASSERT(thread->thread_interrupt_callback_ == NULL);
  ASSERT(thread->thread_interrupt_data_ == NULL);
  // Do not update isolate->mutator_thread, but perform sanity check:
  // this thread should not be both the main mutator and helper.
  ASSERT(!isolate->MutatorThreadIsCurrentThread());
  thread->Schedule(isolate, bypass_safepoint);
}


void Thread::ExitIsolateAsHelper(bool bypass_safepoint) {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  ASSERT(isolate != NULL);
  thread->Unschedule(bypass_safepoint);
  // TODO(koda): Move store_buffer_block_ into State.
  thread->StoreBufferRelease();
  thread->isolate_ = NULL;
  thread->heap_ = NULL;
  ASSERT(!isolate->MutatorThreadIsCurrentThread());
}


// TODO(koda): Make non-static and invoke in SafepointThreads.
void Thread::PrepareForGC() {
  Thread* thread = Thread::Current();
  // Prevent scheduling another GC.
  thread->StoreBufferRelease(StoreBuffer::kIgnoreThreshold);
  // Make sure to get an *empty* block; the isolate needs all entries
  // at GC time.
  // TODO(koda): Replace with an epilogue (PrepareAfterGC) that acquires.
  thread->store_buffer_block_ =
      thread->isolate()->store_buffer()->PopEmptyBlock();
}


void Thread::StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy) {
  StoreBufferRelease(policy);
  StoreBufferAcquire();
}


void Thread::StoreBufferAddObject(RawObject* obj) {
  store_buffer_block_->Push(obj);
  if (store_buffer_block_->IsFull()) {
    StoreBufferBlockProcess(StoreBuffer::kCheckThreshold);
  }
}


void Thread::StoreBufferAddObjectGC(RawObject* obj) {
  store_buffer_block_->Push(obj);
  if (store_buffer_block_->IsFull()) {
    StoreBufferBlockProcess(StoreBuffer::kIgnoreThreshold);
  }
}


void Thread::StoreBufferRelease(StoreBuffer::ThresholdPolicy policy) {
  StoreBufferBlock* block = store_buffer_block_;
  store_buffer_block_ = NULL;
  isolate_->store_buffer()->PushBlock(block, policy);
}


void Thread::StoreBufferAcquire() {
  store_buffer_block_ = isolate()->store_buffer()->PopNonFullBlock();
}


CHA* Thread::cha() const {
  ASSERT(isolate_ != NULL);
  return cha_;
}


void Thread::set_cha(CHA* value) {
  ASSERT(isolate_ != NULL);
  cha_ = value;
}


Log* Thread::log() const {
  return log_;
}


template<class C>
C* Thread::AllocateReusableHandle() {
  C* handle = reinterpret_cast<C*>(reusable_handles_.AllocateScopedHandle());
  C::initializeHandle(handle, C::null());
  return handle;
}


void Thread::ClearReusableHandles() {
#define CLEAR_REUSABLE_HANDLE(object)                                          \
  *object##_handle_ = object::null();
  REUSABLE_HANDLE_LIST(CLEAR_REUSABLE_HANDLE)
#undef CLEAR_REUSABLE_HANDLE
}


void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  ASSERT(visitor != NULL);

  // Visit objects in thread specific handles area.
  reusable_handles_.VisitObjectPointers(visitor);
}


void Thread::SetThreadInterrupter(ThreadInterruptCallback callback,
                                  void* data) {
  ASSERT(Thread::Current() == this);
  thread_interrupt_callback_ = callback;
  thread_interrupt_data_ = data;
}


bool Thread::IsThreadInterrupterEnabled(ThreadInterruptCallback* callback,
                                        void** data) const {
#if defined(TARGET_OS_WINDOWS)
  // On Windows we expect this to be called from the thread interrupter thread.
  ASSERT(id() != OSThread::GetCurrentThreadId());
#else
  // On posix platforms, we expect this to be called from signal handler.
  ASSERT(id() == OSThread::GetCurrentThreadId());
#endif
  ASSERT(callback != NULL);
  ASSERT(data != NULL);
  *callback = thread_interrupt_callback_;
  *data = thread_interrupt_data_;
  return (*callback != NULL) &&
         (*data != NULL);
}


bool Thread::CanLoadFromThread(const Object& object) {
#define CHECK_OBJECT(type_name, member_name, expr, default_init_value)         \
  if (object.raw() == expr) return true;
CACHED_VM_OBJECTS_LIST(CHECK_OBJECT)
#undef CHECK_OBJECT
  return false;
}


intptr_t Thread::OffsetFromThread(const Object& object) {
#define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value)       \
  ASSERT((expr)->IsVMHeapObject());                                            \
  if (object.raw() == expr) return Thread::member_name##offset();
CACHED_VM_OBJECTS_LIST(COMPUTE_OFFSET)
#undef COMPUTE_OFFSET
  UNREACHABLE();
  return -1;
}


intptr_t Thread::OffsetFromThread(const RuntimeEntry* runtime_entry) {
#define COMPUTE_OFFSET(name)                                                   \
  if (runtime_entry->function() == k##name##RuntimeEntry.function())         { \
    return Thread::name##_entry_point_offset();                                \
  }
RUNTIME_ENTRY_LIST(COMPUTE_OFFSET)
#undef COMPUTE_OFFSET

#define COMPUTE_OFFSET(returntype, name, ...)                                  \
  if (runtime_entry->function() == k##name##RuntimeEntry.function())         { \
    return Thread::name##_entry_point_offset();                                \
  }
LEAF_RUNTIME_ENTRY_LIST(COMPUTE_OFFSET)
#undef COMPUTE_OFFSET

  UNREACHABLE();
  return -1;
}


ThreadIterator::ThreadIterator() {
  ASSERT(Thread::thread_list_lock_ != NULL);
  // Lock the thread list while iterating.
  Thread::thread_list_lock_->Lock();
  next_ = Thread::thread_list_head_;
}


ThreadIterator::~ThreadIterator() {
  ASSERT(Thread::thread_list_lock_ != NULL);
  // Unlock the thread list when done.
  Thread::thread_list_lock_->Unlock();
}


bool ThreadIterator::HasNext() const {
  ASSERT(Thread::thread_list_lock_ != NULL);
  ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread());
  return next_ != NULL;
}


Thread* ThreadIterator::Next() {
  ASSERT(Thread::thread_list_lock_ != NULL);
  ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread());
  Thread* current = next_;
  next_ = next_->thread_list_next_;
  return current;
}


}  // namespace dart
