// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This module contains the platform-specific code. This make the rest of the
// code less dependent on operating system, compilers and runtime libraries.
// This module does specifically not deal with differences between different
// processor architecture.
// The platform classes have the same definition for all platforms. The
// implementation for a particular platform is put in platform_<os>.cc.
// The build system then uses the implementation for the target platform.
//
// This design has been chosen because it is simple and fast. Alternatively,
// the platform dependent classes could have been implemented using abstract
// superclasses with virtual methods and having specializations for each
// platform. This design was rejected because it was more complicated and
// slower. It would require factory methods for selecting the right
// implementation and the overhead of virtual methods for performance
// sensitive like mutex locking/unlocking.

#ifndef V8_BASE_PLATFORM_PLATFORM_H_
#define V8_BASE_PLATFORM_PLATFORM_H_

#include <cstdarg>
#include <cstdint>
#include <string>
#include <vector>

#include "src/base/base-export.h"
#include "src/base/build_config.h"
#include "src/base/compiler-specific.h"
#include "src/base/platform/mutex.h"
#include "src/base/platform/semaphore.h"

#if V8_OS_QNX
#include "src/base/qnx-math.h"
#endif

#ifdef V8_USE_ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif  // V8_USE_ADDRESS_SANITIZER

namespace v8 {

namespace base {

// ----------------------------------------------------------------------------
// Fast TLS support

#ifndef V8_NO_FAST_TLS

#if V8_CC_MSVC && V8_HOST_ARCH_IA32

#define V8_FAST_TLS_SUPPORTED 1

V8_INLINE intptr_t InternalGetExistingThreadLocal(intptr_t index);

inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
  const intptr_t kTibInlineTlsOffset = 0xE10;
  const intptr_t kTibExtraTlsOffset = 0xF94;
  const intptr_t kMaxInlineSlots = 64;
  const intptr_t kMaxSlots = kMaxInlineSlots + 1024;
  const intptr_t kSystemPointerSize = sizeof(void*);
  DCHECK(0 <= index && index < kMaxSlots);
  USE(kMaxSlots);
  if (index < kMaxInlineSlots) {
    return static_cast<intptr_t>(
        __readfsdword(kTibInlineTlsOffset + kSystemPointerSize * index));
  }
  intptr_t extra = static_cast<intptr_t>(__readfsdword(kTibExtraTlsOffset));
  DCHECK_NE(extra, 0);
  return *reinterpret_cast<intptr_t*>(extra + kSystemPointerSize *
                                                  (index - kMaxInlineSlots));
}

#elif defined(__APPLE__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)

// tvOS simulator does not use intptr_t as TLS key.
#if !defined(V8_OS_STARBOARD) || !defined(TARGET_OS_SIMULATOR)

#define V8_FAST_TLS_SUPPORTED 1

extern V8_BASE_EXPORT intptr_t kMacTlsBaseOffset;

V8_INLINE intptr_t InternalGetExistingThreadLocal(intptr_t index);

inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
  intptr_t result;
#if V8_HOST_ARCH_IA32
  asm("movl %%gs:(%1,%2,4), %0;"
      :"=r"(result)  // Output must be a writable register.
      :"r"(kMacTlsBaseOffset), "r"(index));
#else
  asm("movq %%gs:(%1,%2,8), %0;"
      :"=r"(result)
      :"r"(kMacTlsBaseOffset), "r"(index));
#endif
  return result;
}

#endif  // !defined(V8_OS_STARBOARD) || !defined(TARGET_OS_SIMULATOR)

#endif

#endif  // V8_NO_FAST_TLS

class PageAllocator;
class TimezoneCache;

// ----------------------------------------------------------------------------
// OS
//
// This class has static methods for the different platform specific
// functions. Add methods here to cope with differences between the
// supported platforms.

class V8_BASE_EXPORT OS {
 public:
  // Initialize the OS class.
  // - hard_abort: If true, OS::Abort() will crash instead of aborting.
  // - gc_fake_mmap: Name of the file for fake gc mmap used in ll_prof.
  static void Initialize(bool hard_abort, const char* const gc_fake_mmap);

  // Returns the accumulated user time for thread. This routine
  // can be used for profiling. The implementation should
  // strive for high-precision timer resolution, preferable
  // micro-second resolution.
  static int GetUserTime(uint32_t* secs,  uint32_t* usecs);

  // Returns current time as the number of milliseconds since
  // 00:00:00 UTC, January 1, 1970.
  static double TimeCurrentMillis();

  static TimezoneCache* CreateTimezoneCache();

  // Returns last OS error.
  static int GetLastError();

  static FILE* FOpen(const char* path, const char* mode);
  static bool Remove(const char* path);

  static char DirectorySeparator();
  static bool isDirectorySeparator(const char ch);

  // Opens a temporary file, the file is auto removed on close.
  static FILE* OpenTemporaryFile();

  // Log file open mode is platform-dependent due to line ends issues.
  static const char* const LogFileOpenMode;

  // Print output to console. This is mostly used for debugging output.
  // On platforms that has standard terminal output, the output
  // should go to stdout.
  static PRINTF_FORMAT(1, 2) void Print(const char* format, ...);
  static PRINTF_FORMAT(1, 0) void VPrint(const char* format, va_list args);

  // Print output to a file. This is mostly used for debugging output.
  static PRINTF_FORMAT(2, 3) void FPrint(FILE* out, const char* format, ...);
  static PRINTF_FORMAT(2, 0) void VFPrint(FILE* out, const char* format,
                                          va_list args);

  // Print error output to console. This is mostly used for error message
  // output. On platforms that has standard terminal output, the output
  // should go to stderr.
  static PRINTF_FORMAT(1, 2) void PrintError(const char* format, ...);
  static PRINTF_FORMAT(1, 0) void VPrintError(const char* format, va_list args);

  // Memory permissions. These should be kept in sync with the ones in
  // v8::PageAllocator.
  enum class MemoryPermission {
    kNoAccess,
    kRead,
    kReadWrite,
    // TODO(hpayer): Remove this flag. Memory should never be rwx.
    kReadWriteExecute,
    kReadExecute,
    // TODO(jkummerow): Remove this when Wasm has a platform-independent
    // w^x implementation.
    kNoAccessWillJitLater
  };

  static bool HasLazyCommits();

  // Sleep for a specified time interval.
  static void Sleep(TimeDelta interval);

  // Abort the current process.
  [[noreturn]] static void Abort();

  // Debug break.
  static void DebugBreak();

  // Walk the stack.
  static const int kStackWalkError = -1;
  static const int kStackWalkMaxNameLen = 256;
  static const int kStackWalkMaxTextLen = 256;
  struct StackFrame {
    void* address;
    char text[kStackWalkMaxTextLen];
  };

  class V8_BASE_EXPORT MemoryMappedFile {
   public:
    enum class FileMode { kReadOnly, kReadWrite };

    virtual ~MemoryMappedFile() = default;
    virtual void* memory() const = 0;
    virtual size_t size() const = 0;

    static MemoryMappedFile* open(const char* name,
                                  FileMode mode = FileMode::kReadWrite);
    static MemoryMappedFile* create(const char* name, size_t size,
                                    void* initial);
  };

  // Safe formatting print. Ensures that str is always null-terminated.
  // Returns the number of chars written, or -1 if output was truncated.
  static PRINTF_FORMAT(3, 4) int SNPrintF(char* str, int length,
                                          const char* format, ...);
  static PRINTF_FORMAT(3, 0) int VSNPrintF(char* str, int length,
                                           const char* format, va_list args);

  static void StrNCpy(char* dest, int length, const char* src, size_t n);

  // Support for the profiler.  Can do nothing, in which case ticks
  // occurring in shared libraries will not be properly accounted for.
  struct SharedLibraryAddress {
    SharedLibraryAddress(const std::string& library_path, uintptr_t start,
                         uintptr_t end)
        : library_path(library_path), start(start), end(end), aslr_slide(0) {}
    SharedLibraryAddress(const std::string& library_path, uintptr_t start,
                         uintptr_t end, intptr_t aslr_slide)
        : library_path(library_path),
          start(start),
          end(end),
          aslr_slide(aslr_slide) {}

    std::string library_path;
    uintptr_t start;
    uintptr_t end;
    intptr_t aslr_slide;
  };

  static std::vector<SharedLibraryAddress> GetSharedLibraryAddresses();

  // Support for the profiler.  Notifies the external profiling
  // process that a code moving garbage collection starts.  Can do
  // nothing, in which case the code objects must not move (e.g., by
  // using --never-compact) if accurate profiling is desired.
  static void SignalCodeMovingGC();

  // Support runtime detection of whether the hard float option of the
  // EABI is used.
  static bool ArmUsingHardFloat();

  // Returns the activation frame alignment constraint or zero if
  // the platform doesn't care. Guaranteed to be a power of two.
  static int ActivationFrameAlignment();

  static int GetCurrentProcessId();

  static int GetCurrentThreadId();

  static void AdjustSchedulingParams();

  static void ExitProcess(int exit_code);

 private:
  // These classes use the private memory management API below.
  friend class MemoryMappedFile;
  friend class PosixMemoryMappedFile;
  friend class v8::base::PageAllocator;

  static size_t AllocatePageSize();

  static size_t CommitPageSize();

  static void SetRandomMmapSeed(int64_t seed);

  static void* GetRandomMmapAddr();

  V8_WARN_UNUSED_RESULT static void* Allocate(void* address, size_t size,
                                              size_t alignment,
                                              MemoryPermission access);

  V8_WARN_UNUSED_RESULT static void* AllocateShared(size_t size,
                                                    MemoryPermission access);

  V8_WARN_UNUSED_RESULT static void* RemapShared(void* old_address,
                                                 void* new_address,
                                                 size_t size);

  V8_WARN_UNUSED_RESULT static bool Free(void* address, const size_t size);

  V8_WARN_UNUSED_RESULT static bool Release(void* address, size_t size);

  V8_WARN_UNUSED_RESULT static bool SetPermissions(void* address, size_t size,
                                                   MemoryPermission access);

  V8_WARN_UNUSED_RESULT static bool DiscardSystemPages(void* address,
                                                       size_t size);

  static const int msPerSecond = 1000;

#if V8_OS_POSIX
  static const char* GetGCFakeMMapFile();
#endif

  DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
};

#if (defined(_WIN32) || defined(_WIN64))
V8_BASE_EXPORT void EnsureConsoleOutputWin32();
#endif  // (defined(_WIN32) || defined(_WIN64))

inline void EnsureConsoleOutput() {
#if (defined(_WIN32) || defined(_WIN64))
  // Windows requires extra calls to send assert output to the console
  // rather than a dialog box.
  EnsureConsoleOutputWin32();
#endif  // (defined(_WIN32) || defined(_WIN64))
}

// ----------------------------------------------------------------------------
// Thread
//
// Thread objects are used for creating and running threads. When the start()
// method is called the new thread starts running the run() method in the new
// thread. The Thread object should not be deallocated before the thread has
// terminated.

class V8_BASE_EXPORT Thread {
 public:
  // Opaque data type for thread-local storage keys.
#if V8_OS_STARBOARD
  using LocalStorageKey = SbThreadLocalKey;
#else
  using LocalStorageKey = int32_t;
#endif

  class Options {
   public:
    Options() : name_("v8:<unknown>"), stack_size_(0) {}
    explicit Options(const char* name, int stack_size = 0)
        : name_(name), stack_size_(stack_size) {}

    const char* name() const { return name_; }
    int stack_size() const { return stack_size_; }

   private:
    const char* name_;
    int stack_size_;
  };

  // Create new thread.
  explicit Thread(const Options& options);
  Thread(const Thread&) = delete;
  Thread& operator=(const Thread&) = delete;
  virtual ~Thread();

  // Start new thread by calling the Run() method on the new thread.
  V8_WARN_UNUSED_RESULT bool Start();

  // Start new thread and wait until Run() method is called on the new thread.
  bool StartSynchronously() {
    start_semaphore_ = new Semaphore(0);
    if (!Start()) return false;
    start_semaphore_->Wait();
    delete start_semaphore_;
    start_semaphore_ = nullptr;
    return true;
  }

  // Wait until thread terminates.
  void Join();

  inline const char* name() const {
    return name_;
  }

  // Abstract method for run handler.
  virtual void Run() = 0;

  // Thread-local storage.
  static LocalStorageKey CreateThreadLocalKey();
  static void DeleteThreadLocalKey(LocalStorageKey key);
  static void* GetThreadLocal(LocalStorageKey key);
  static int GetThreadLocalInt(LocalStorageKey key) {
    return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
  }
  static void SetThreadLocal(LocalStorageKey key, void* value);
  static void SetThreadLocalInt(LocalStorageKey key, int value) {
    SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
  }
  static bool HasThreadLocal(LocalStorageKey key) {
    return GetThreadLocal(key) != nullptr;
  }

#ifdef V8_FAST_TLS_SUPPORTED
  static inline void* GetExistingThreadLocal(LocalStorageKey key) {
    void* result = reinterpret_cast<void*>(
        InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
    DCHECK(result == GetThreadLocal(key));
    return result;
  }
#else
  static inline void* GetExistingThreadLocal(LocalStorageKey key) {
    return GetThreadLocal(key);
  }
#endif

  // The thread name length is limited to 16 based on Linux's implementation of
  // prctl().
  static const int kMaxThreadNameLength = 16;

  class PlatformData;
  PlatformData* data() { return data_; }

  void NotifyStartedAndRun() {
    if (start_semaphore_) start_semaphore_->Signal();
    Run();
  }

 private:
  void set_name(const char* name);

  PlatformData* data_;

  char name_[kMaxThreadNameLength];
  int stack_size_;
  Semaphore* start_semaphore_;
};

// TODO(v8:10354): Make use of the stack utilities here in V8.
class V8_BASE_EXPORT Stack {
 public:
  // Convenience wrapper to use stack slots as unsigned values or void*
  // pointers.
  struct StackSlot {
    // NOLINTNEXTLINE
    StackSlot(void* value) : value(reinterpret_cast<uintptr_t>(value)) {}
    StackSlot(uintptr_t value) : value(value) {}  // NOLINT

    // NOLINTNEXTLINE
    operator void*() const { return reinterpret_cast<void*>(value); }
    operator uintptr_t() const { return value; }  // NOLINT

    uintptr_t value;
  };

  // Gets the start of the stack of the current thread.
  static StackSlot GetStackStart();

  // Returns the current stack top. Works correctly with ASAN and SafeStack.
  // GetCurrentStackPosition() should not be inlined, because it works on stack
  // frames if it were inlined into a function with a huge stack frame it would
  // return an address significantly above the actual current stack position.
  static V8_NOINLINE StackSlot GetCurrentStackPosition();

  // Returns the real stack frame if slot is part of a fake frame, and slot
  // otherwise.
  static StackSlot GetRealStackAddressForSlot(StackSlot slot) {
#ifdef V8_USE_ADDRESS_SANITIZER
    // ASAN fetches the real stack deeper in the __asan_addr_is_in_fake_stack()
    // call (precisely, deeper in __asan_stack_malloc_()), which results in a
    // real frame that could be outside of stack bounds. Adjust for this
    // impreciseness here.
    constexpr size_t kAsanRealFrameOffsetBytes = 32;
    void* real_frame = __asan_addr_is_in_fake_stack(
        __asan_get_current_fake_stack(), slot, nullptr, nullptr);
    return real_frame
               ? (static_cast<char*>(real_frame) + kAsanRealFrameOffsetBytes)
               : slot;
#endif  // V8_USE_ADDRESS_SANITIZER
    return slot;
  }
};

}  // namespace base
}  // namespace v8

#endif  // V8_BASE_PLATFORM_PLATFORM_H_
