Merge V8 5.2.361.47  DO NOT MERGE

https://chromium.googlesource.com/v8/v8/+/5.2.361.47

FPIIM-449

Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/src/base/atomic-utils.h b/src/base/atomic-utils.h
new file mode 100644
index 0000000..ac90fd9
--- /dev/null
+++ b/src/base/atomic-utils.h
@@ -0,0 +1,175 @@
+// Copyright 2015 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.
+
+#ifndef V8_ATOMIC_UTILS_H_
+#define V8_ATOMIC_UTILS_H_
+
+#include <limits.h>
+
+#include "src/base/atomicops.h"
+#include "src/base/macros.h"
+
+namespace v8 {
+namespace base {
+
+template <class T>
+class AtomicNumber {
+ public:
+  AtomicNumber() : value_(0) {}
+  explicit AtomicNumber(T initial) : value_(initial) {}
+
+  // Returns the newly set value.
+  V8_INLINE T Increment(T increment) {
+    return static_cast<T>(base::Barrier_AtomicIncrement(
+        &value_, static_cast<base::AtomicWord>(increment)));
+  }
+
+  V8_INLINE T Value() { return static_cast<T>(base::Acquire_Load(&value_)); }
+
+  V8_INLINE void SetValue(T new_value) {
+    base::Release_Store(&value_, static_cast<base::AtomicWord>(new_value));
+  }
+
+  V8_INLINE T operator=(T value) {
+    SetValue(value);
+    return value;
+  }
+
+ private:
+  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
+
+  base::AtomicWord value_;
+};
+
+
+// Flag using T atomically. Also accepts void* as T.
+template <typename T>
+class AtomicValue {
+ public:
+  AtomicValue() : value_(0) {}
+
+  explicit AtomicValue(T initial)
+      : value_(cast_helper<T>::to_storage_type(initial)) {}
+
+  V8_INLINE T Value() {
+    return cast_helper<T>::to_return_type(base::Acquire_Load(&value_));
+  }
+
+  V8_INLINE bool TrySetValue(T old_value, T new_value) {
+    return base::Release_CompareAndSwap(
+               &value_, cast_helper<T>::to_storage_type(old_value),
+               cast_helper<T>::to_storage_type(new_value)) ==
+           cast_helper<T>::to_storage_type(old_value);
+  }
+
+  V8_INLINE void SetValue(T new_value) {
+    base::Release_Store(&value_, cast_helper<T>::to_storage_type(new_value));
+  }
+
+ private:
+  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
+
+  template <typename S>
+  struct cast_helper {
+    static base::AtomicWord to_storage_type(S value) {
+      return static_cast<base::AtomicWord>(value);
+    }
+    static S to_return_type(base::AtomicWord value) {
+      return static_cast<S>(value);
+    }
+  };
+
+  template <typename S>
+  struct cast_helper<S*> {
+    static base::AtomicWord to_storage_type(S* value) {
+      return reinterpret_cast<base::AtomicWord>(value);
+    }
+    static S* to_return_type(base::AtomicWord value) {
+      return reinterpret_cast<S*>(value);
+    }
+  };
+
+  base::AtomicWord value_;
+};
+
+
+// See utils.h for EnumSet. Storage is always base::AtomicWord.
+// Requirements on E:
+// - No explicit values.
+// - E::kLastValue defined to be the last actually used value.
+//
+// Example:
+// enum E { kA, kB, kC, kLastValue = kC };
+template <class E>
+class AtomicEnumSet {
+ public:
+  explicit AtomicEnumSet(base::AtomicWord bits = 0) : bits_(bits) {}
+
+  bool IsEmpty() const { return ToIntegral() == 0; }
+
+  bool Contains(E element) const { return (ToIntegral() & Mask(element)) != 0; }
+  bool ContainsAnyOf(const AtomicEnumSet& set) const {
+    return (ToIntegral() & set.ToIntegral()) != 0;
+  }
+
+  void RemoveAll() { base::Release_Store(&bits_, 0); }
+
+  bool operator==(const AtomicEnumSet& set) const {
+    return ToIntegral() == set.ToIntegral();
+  }
+
+  bool operator!=(const AtomicEnumSet& set) const {
+    return ToIntegral() != set.ToIntegral();
+  }
+
+  AtomicEnumSet<E> operator|(const AtomicEnumSet& set) const {
+    return AtomicEnumSet<E>(ToIntegral() | set.ToIntegral());
+  }
+
+// The following operations modify the underlying storage.
+
+#define ATOMIC_SET_WRITE(OP, NEW_VAL)                                     \
+  do {                                                                    \
+    base::AtomicWord old;                                                 \
+    do {                                                                  \
+      old = base::Acquire_Load(&bits_);                                   \
+    } while (base::Release_CompareAndSwap(&bits_, old, old OP NEW_VAL) != \
+             old);                                                        \
+  } while (false)
+
+  void Add(E element) { ATOMIC_SET_WRITE(|, Mask(element)); }
+
+  void Add(const AtomicEnumSet& set) { ATOMIC_SET_WRITE(|, set.ToIntegral()); }
+
+  void Remove(E element) { ATOMIC_SET_WRITE(&, ~Mask(element)); }
+
+  void Remove(const AtomicEnumSet& set) {
+    ATOMIC_SET_WRITE(&, ~set.ToIntegral());
+  }
+
+  void Intersect(const AtomicEnumSet& set) {
+    ATOMIC_SET_WRITE(&, set.ToIntegral());
+  }
+
+#undef ATOMIC_SET_OP
+
+ private:
+  // Check whether there's enough storage to hold E.
+  STATIC_ASSERT(E::kLastValue < (sizeof(base::AtomicWord) * CHAR_BIT));
+
+  V8_INLINE base::AtomicWord ToIntegral() const {
+    return base::Acquire_Load(&bits_);
+  }
+
+  V8_INLINE base::AtomicWord Mask(E element) const {
+    return static_cast<base::AtomicWord>(1) << element;
+  }
+
+  base::AtomicWord bits_;
+};
+
+}  // namespace base
+}  // namespace v8
+
+#endif  // #define V8_ATOMIC_UTILS_H_
diff --git a/src/base/bits.cc b/src/base/bits.cc
index 74d747f..9b949cc 100644
--- a/src/base/bits.cc
+++ b/src/base/bits.cc
@@ -7,6 +7,7 @@
 #include <limits>
 
 #include "src/base/logging.h"
+#include "src/base/safe_math.h"
 
 namespace v8 {
 namespace base {
@@ -48,6 +49,35 @@
   return lhs % rhs;
 }
 
+
+int64_t FromCheckedNumeric(const internal::CheckedNumeric<int64_t> value) {
+  if (value.IsValid())
+    return value.ValueUnsafe();
+
+  // We could return max/min but we don't really expose what the maximum delta
+  // is. Instead, return max/(-max), which is something that clients can reason
+  // about.
+  // TODO(rvargas) crbug.com/332611: don't use internal values.
+  int64_t limit = std::numeric_limits<int64_t>::max();
+  if (value.validity() == internal::RANGE_UNDERFLOW)
+    limit = -limit;
+  return value.ValueOrDefault(limit);
+}
+
+
+int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs) {
+  internal::CheckedNumeric<int64_t> rv(lhs);
+  rv += rhs;
+  return FromCheckedNumeric(rv);
+}
+
+
+int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs) {
+  internal::CheckedNumeric<int64_t> rv(lhs);
+  rv -= rhs;
+  return FromCheckedNumeric(rv);
+}
+
 }  // namespace bits
 }  // namespace base
 }  // namespace v8
diff --git a/src/base/bits.h b/src/base/bits.h
index 0e76624..2e6527b 100644
--- a/src/base/bits.h
+++ b/src/base/bits.h
@@ -16,6 +16,12 @@
 
 namespace v8 {
 namespace base {
+
+namespace internal {
+template <typename T>
+class CheckedNumeric;
+}
+
 namespace bits {
 
 // CountPopulation32(value) returns the number of bits set in |value|.
@@ -296,6 +302,21 @@
   return rhs ? lhs % rhs : 0u;
 }
 
+
+// Clamp |value| on overflow and underflow conditions.
+int64_t FromCheckedNumeric(const internal::CheckedNumeric<int64_t> value);
+
+
+// SignedSaturatedAdd64(lhs, rhs) adds |lhs| and |rhs|,
+// checks and returns the result.
+int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs);
+
+
+// SignedSaturatedSub64(lhs, rhs) substracts |lhs| by |rhs|,
+// checks and returns the result.
+int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs);
+
+
 }  // namespace bits
 }  // namespace base
 }  // namespace v8
diff --git a/src/base/compiler-specific.h b/src/base/compiler-specific.h
index ffd5a44..822893f 100644
--- a/src/base/compiler-specific.h
+++ b/src/base/compiler-specific.h
@@ -26,6 +26,17 @@
 #define WARN_UNUSED_RESULT /* NOT SUPPORTED */
 #endif
 
+// Tell the compiler a function is using a printf-style format string.
+// |format_param| is the one-based index of the format string parameter;
+// |dots_param| is the one-based index of the "..." parameter.
+// For v*printf functions (which take a va_list), pass 0 for dots_param.
+// (This is undocumented but matches what the system C headers do.)
+#if defined(__GNUC__)
+#define PRINTF_FORMAT(format_param, dots_param) \
+  __attribute__((format(printf, format_param, dots_param)))
+#else
+#define PRINTF_FORMAT(format_param, dots_param)
+#endif
 
 // The C++ standard requires that static const members have an out-of-class
 // definition (in a single compilation unit), but MSVC chokes on this (when
diff --git a/src/base/format-macros.h b/src/base/format-macros.h
new file mode 100644
index 0000000..5f5fe5d
--- /dev/null
+++ b/src/base/format-macros.h
@@ -0,0 +1,97 @@
+// Copyright 2016 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.
+
+#ifndef BASE_FORMAT_MACROS_H_
+#define BASE_FORMAT_MACROS_H_
+
+// This file defines the format macros for some integer types.
+
+// To print a 64-bit value in a portable way:
+//   int64_t value;
+//   printf("xyz:%" PRId64, value);
+// The "d" in the macro corresponds to %d; you can also use PRIu64 etc.
+//
+// For wide strings, prepend "Wide" to the macro:
+//   int64_t value;
+//   StringPrintf(L"xyz: %" WidePRId64, value);
+//
+// To print a size_t value in a portable way:
+//   size_t size;
+//   printf("xyz: %" PRIuS, size);
+// The "u" in the macro corresponds to %u, and S is for "size".
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "src/base/build_config.h"
+
+#if defined(V8_OS_POSIX) && (defined(_INTTYPES_H) || defined(_INTTYPES_H_)) && \
+    !defined(PRId64)
+#error "inttypes.h has already been included before this header file, but "
+#error "without __STDC_FORMAT_MACROS defined."
+#endif
+
+#if defined(V8_OS_POSIX) && !defined(__STDC_FORMAT_MACROS)
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <inttypes.h>
+
+#if defined(V8_OS_POSIX)
+
+// GCC will concatenate wide and narrow strings correctly, so nothing needs to
+// be done here.
+#define WidePRId64 PRId64
+#define WidePRIu64 PRIu64
+#define WidePRIx64 PRIx64
+
+#if !defined(PRIuS)
+#define PRIuS "zu"
+#endif
+
+// The size of NSInteger and NSUInteger varies between 32-bit and 64-bit
+// architectures and Apple does not provides standard format macros and
+// recommends casting. This has many drawbacks, so instead define macros
+// for formatting those types.
+#if defined(V8_OS_MACOSX)
+#if defined(V8_HOST_ARCH_64_BIT)
+#if !defined(PRIdNS)
+#define PRIdNS "ld"
+#endif
+#if !defined(PRIuNS)
+#define PRIuNS "lu"
+#endif
+#if !defined(PRIxNS)
+#define PRIxNS "lx"
+#endif
+#else  // defined(V8_HOST_ARCH_64_BIT)
+#if !defined(PRIdNS)
+#define PRIdNS "d"
+#endif
+#if !defined(PRIuNS)
+#define PRIuNS "u"
+#endif
+#if !defined(PRIxNS)
+#define PRIxNS "x"
+#endif
+#endif
+#endif  // defined(V8_OS_MACOSX)
+
+#else  // V8_OS_WIN
+
+#if !defined(PRId64) || !defined(PRIu64) || !defined(PRIx64)
+#error "inttypes.h provided by win toolchain should define these."
+#endif
+
+#define WidePRId64 L"I64d"
+#define WidePRIu64 L"I64u"
+#define WidePRIx64 L"I64x"
+
+#if !defined(PRIuS)
+#define PRIuS "Iu"
+#endif
+
+#endif
+
+#endif  // BASE_FORMAT_MACROS_H_
diff --git a/src/base/logging.h b/src/base/logging.h
index 15322f6..45bc3c4 100644
--- a/src/base/logging.h
+++ b/src/base/logging.h
@@ -10,9 +10,10 @@
 #include <string>
 
 #include "src/base/build_config.h"
+#include "src/base/compiler-specific.h"
 
-extern "C" V8_NORETURN void V8_Fatal(const char* file, int line,
-                                     const char* format, ...);
+extern "C" PRINTF_FORMAT(3, 4) V8_NORETURN
+    void V8_Fatal(const char* file, int line, const char* format, ...);
 
 extern "C" void V8_RuntimeError(const char* file, int line,
                                 const char* message);
diff --git a/src/base/macros.h b/src/base/macros.h
index 3f09b2b..382c30b 100644
--- a/src/base/macros.h
+++ b/src/base/macros.h
@@ -5,13 +5,8 @@
 #ifndef V8_BASE_MACROS_H_
 #define V8_BASE_MACROS_H_
 
-#include <stddef.h>
-#include <stdint.h>
-
-#include <cstring>
-
-#include "src/base/build_config.h"
 #include "src/base/compiler-specific.h"
+#include "src/base/format-macros.h"
 #include "src/base/logging.h"
 
 
@@ -274,23 +269,27 @@
 #define V8PRIdPTR V8_PTR_PREFIX "d"
 #define V8PRIuPTR V8_PTR_PREFIX "u"
 
+// ptrdiff_t is 't' according to the standard, but MSVC uses 'I'.
+#if V8_CC_MSVC
+#define V8PRIxPTRDIFF "Ix"
+#define V8PRIdPTRDIFF "Id"
+#define V8PRIuPTRDIFF "Iu"
+#else
+#define V8PRIxPTRDIFF "tx"
+#define V8PRIdPTRDIFF "td"
+#define V8PRIuPTRDIFF "tu"
+#endif
+
 // Fix for Mac OS X defining uintptr_t as "unsigned long":
 #if V8_OS_MACOSX
 #undef V8PRIxPTR
 #define V8PRIxPTR "lx"
+#undef V8PRIdPTR
+#define V8PRIdPTR "ld"
 #undef V8PRIuPTR
 #define V8PRIuPTR "lxu"
 #endif
 
-// GCC on S390 31-bit expands 'size_t' to 'long unsigned int'
-// instead of 'int', resulting in compilation errors with %d.
-// The printf format specifier needs to be %zd instead.
-#if V8_HOST_ARCH_S390 && !V8_HOST_ARCH_64_BIT
-#define V8_SIZET_PREFIX "z"
-#else
-#define V8_SIZET_PREFIX ""
-#endif
-
 // The following macro works on both 32 and 64-bit platforms.
 // Usage: instead of writing 0x1234567890123456
 //      write V8_2PART_UINT64_C(0x12345678,90123456);
diff --git a/src/base/platform/condition-variable.cc b/src/base/platform/condition-variable.cc
index fcd6cf7..19c33f8 100644
--- a/src/base/platform/condition-variable.cc
+++ b/src/base/platform/condition-variable.cc
@@ -36,6 +36,19 @@
 
 
 ConditionVariable::~ConditionVariable() {
+#if defined(V8_OS_MACOSX)
+  // This hack is necessary to avoid a fatal pthreads subsystem bug in the
+  // Darwin kernel. http://crbug.com/517681.
+  {
+    Mutex lock;
+    LockGuard<Mutex> l(&lock);
+    struct timespec ts;
+    ts.tv_sec = 0;
+    ts.tv_nsec = 1;
+    pthread_cond_timedwait_relative_np(&native_handle_, &lock.native_handle(),
+                                       &ts);
+  }
+#endif
   int result = pthread_cond_destroy(&native_handle_);
   DCHECK_EQ(0, result);
   USE(result);
diff --git a/src/base/platform/platform-macos.cc b/src/base/platform/platform-macos.cc
index 419281f..ecd440c 100644
--- a/src/base/platform/platform-macos.cc
+++ b/src/base/platform/platform-macos.cc
@@ -86,10 +86,10 @@
     char* code_ptr = getsectdatafromheader(header, SEG_TEXT, SECT_TEXT, &size);
 #endif
     if (code_ptr == NULL) continue;
-    const uintptr_t slide = _dyld_get_image_vmaddr_slide(i);
+    const intptr_t slide = _dyld_get_image_vmaddr_slide(i);
     const uintptr_t start = reinterpret_cast<uintptr_t>(code_ptr) + slide;
-    result.push_back(
-        SharedLibraryAddress(_dyld_get_image_name(i), start, start + size));
+    result.push_back(SharedLibraryAddress(_dyld_get_image_name(i), start,
+                                          start + size, slide));
   }
   return result;
 }
diff --git a/src/base/platform/platform.h b/src/base/platform/platform.h
index 5b2dbc9..9464fb1 100644
--- a/src/base/platform/platform.h
+++ b/src/base/platform/platform.h
@@ -26,6 +26,7 @@
 #include <vector>
 
 #include "src/base/build_config.h"
+#include "src/base/compiler-specific.h"
 #include "src/base/platform/mutex.h"
 #include "src/base/platform/semaphore.h"
 
@@ -154,18 +155,19 @@
   // 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 void Print(const char* format, ...);
-  static void VPrint(const char* format, va_list args);
+  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 void FPrint(FILE* out, const char* format, ...);
-  static void VFPrint(FILE* out, const char* format, va_list args);
+  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 void PrintError(const char* format, ...);
-  static void VPrintError(const char* format, va_list args);
+  static PRINTF_FORMAT(1, 2) void PrintError(const char* format, ...);
+  static PRINTF_FORMAT(1, 0) void VPrintError(const char* format, va_list args);
 
   // Allocate/Free memory used by JS heap. Pages are readable/writable, but
   // they are not guaranteed to be executable unless 'executable' is true.
@@ -222,11 +224,10 @@
 
   // Safe formatting print. Ensures that str is always null-terminated.
   // Returns the number of chars written, or -1 if output was truncated.
-  static int SNPrintF(char* str, int length, const char* format, ...);
-  static int VSNPrintF(char* str,
-                       int length,
-                       const char* format,
-                       va_list args);
+  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 char* StrChr(char* str, int c);
   static void StrNCpy(char* dest, int length, const char* src, size_t n);
@@ -234,13 +235,20 @@
   // Support for the profiler.  Can do nothing, in which case ticks
   // occuring 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) {}
+    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();
diff --git a/src/base/platform/semaphore.cc b/src/base/platform/semaphore.cc
index 284474e..a7e522a 100644
--- a/src/base/platform/semaphore.cc
+++ b/src/base/platform/semaphore.cc
@@ -34,7 +34,6 @@
   USE(result);
 }
 
-
 void Semaphore::Signal() {
   kern_return_t result = semaphore_signal(native_handle_);
   DCHECK_EQ(KERN_SUCCESS, result);
@@ -74,6 +73,19 @@
 #elif V8_OS_POSIX
 
 Semaphore::Semaphore(int count) {
+  // The sem_init() does not check for alignment of the native handle.
+  // Unaligned native handle can later cause a failure in semaphore signal.
+  // Check the alignment here to catch the failure earlier.
+  // Context: crbug.com/605349.
+#if V8_OS_AIX
+  // On aix sem_t is of type int
+  const uintptr_t kSemaphoreAlignmentMask = sizeof(int) - 1;
+#else
+  const uintptr_t kSemaphoreAlignmentMask = sizeof(void*) - 1;
+#endif
+  CHECK_EQ(
+      0, reinterpret_cast<uintptr_t>(&native_handle_) &
+      kSemaphoreAlignmentMask);
   DCHECK(count >= 0);
 #if V8_LIBC_GLIBC
   // sem_init in glibc prior to 2.1 does not zero out semaphores.
@@ -91,7 +103,6 @@
   USE(result);
 }
 
-
 void Semaphore::Signal() {
   int result = sem_post(&native_handle_);
   CHECK_EQ(0, result);
@@ -162,7 +173,6 @@
   USE(result);
 }
 
-
 void Semaphore::Signal() {
   LONG dummy;
   BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy);
diff --git a/src/base/platform/time.cc b/src/base/platform/time.cc
index 6d5e538..b2355a3 100644
--- a/src/base/platform/time.cc
+++ b/src/base/platform/time.cc
@@ -10,7 +10,9 @@
 #include <unistd.h>
 #endif
 #if V8_OS_MACOSX
+#include <mach/mach.h>
 #include <mach/mach_time.h>
+#include <pthread.h>
 #endif
 
 #include <cstring>
@@ -25,6 +27,51 @@
 #include "src/base/logging.h"
 #include "src/base/platform/platform.h"
 
+namespace {
+
+#if V8_OS_MACOSX
+int64_t ComputeThreadTicks() {
+  mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT;
+  thread_basic_info_data_t thread_info_data;
+  kern_return_t kr = thread_info(
+      pthread_mach_thread_np(pthread_self()),
+      THREAD_BASIC_INFO,
+      reinterpret_cast<thread_info_t>(&thread_info_data),
+      &thread_info_count);
+  CHECK(kr == KERN_SUCCESS);
+
+  v8::base::CheckedNumeric<int64_t> absolute_micros(
+      thread_info_data.user_time.seconds);
+  absolute_micros *= v8::base::Time::kMicrosecondsPerSecond;
+  absolute_micros += thread_info_data.user_time.microseconds;
+  return absolute_micros.ValueOrDie();
+}
+#elif V8_OS_POSIX
+// Helper function to get results from clock_gettime() and convert to a
+// microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported
+// on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines
+// _POSIX_MONOTONIC_CLOCK to -1.
+inline int64_t ClockNow(clockid_t clk_id) {
+#if (defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \
+  defined(V8_OS_BSD) || defined(V8_OS_ANDROID)
+  struct timespec ts;
+  if (clock_gettime(clk_id, &ts) != 0) {
+    UNREACHABLE();
+    return 0;
+  }
+  v8::base::internal::CheckedNumeric<int64_t> result(ts.tv_sec);
+  result *= v8::base::Time::kMicrosecondsPerSecond;
+  result += (ts.tv_nsec / v8::base::Time::kNanosecondsPerMicrosecond);
+  return result.ValueOrDie();
+#else  // Monotonic clock not supported.
+  return 0;
+#endif
+}
+#endif  // V8_OS_MACOSX
+
+
+}  // namespace
+
 namespace v8 {
 namespace base {
 
@@ -541,12 +588,7 @@
 #elif V8_OS_SOLARIS
   ticks = (gethrtime() / Time::kNanosecondsPerMicrosecond);
 #elif V8_OS_POSIX
-  struct timespec ts;
-  int result = clock_gettime(CLOCK_MONOTONIC, &ts);
-  DCHECK_EQ(0, result);
-  USE(result);
-  ticks = (ts.tv_sec * Time::kMicrosecondsPerSecond +
-           ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
+  ticks = ClockNow(CLOCK_MONOTONIC);
 #endif  // V8_OS_MACOSX
   // Make sure we never return 0 here.
   return TimeTicks(ticks + 1);
@@ -560,5 +602,30 @@
 
 #endif  // V8_OS_WIN
 
+
+// TODO(lpy): For windows ThreadTicks implementation,
+// see http://crbug.com/v8/5000
+bool ThreadTicks::IsSupported() {
+#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
+    defined(V8_OS_MACOSX) || defined(V8_OS_ANDROID)
+    return true;
+#else
+    return false;
+#endif
+}
+
+
+ThreadTicks ThreadTicks::Now() {
+#if V8_OS_MACOSX
+  return ThreadTicks(ComputeThreadTicks());
+#elif(defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
+  defined(V8_OS_ANDROID)
+  return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID));
+#else
+  UNREACHABLE();
+  return ThreadTicks();
+#endif
+}
+
 }  // namespace base
 }  // namespace v8
diff --git a/src/base/platform/time.h b/src/base/platform/time.h
index c8140ef..e17fc1d 100644
--- a/src/base/platform/time.h
+++ b/src/base/platform/time.h
@@ -9,7 +9,9 @@
 #include <iosfwd>
 #include <limits>
 
+#include "src/base/bits.h"
 #include "src/base/macros.h"
+#include "src/base/safe_math.h"
 
 // Forward declarations.
 extern "C" {
@@ -23,8 +25,14 @@
 namespace base {
 
 class Time;
+class TimeDelta;
 class TimeTicks;
 
+namespace time_internal {
+template<class TimeClass>
+class TimeBase;
+}
+
 // -----------------------------------------------------------------------------
 // TimeDelta
 //
@@ -143,6 +151,7 @@
   }
 
  private:
+  template<class TimeClass> friend class time_internal::TimeBase;
   // Constructs a delta given the duration in microseconds. This is private
   // to avoid confusion by callers with an integer constructor. Use
   // FromSeconds, FromMilliseconds, etc. instead.
@@ -153,34 +162,122 @@
 };
 
 
+namespace time_internal {
+
+// TimeBase--------------------------------------------------------------------
+
+// Provides value storage and comparison/math operations common to all time
+// classes. Each subclass provides for strong type-checking to ensure
+// semantically meaningful comparison/math of time values from the same clock
+// source or timeline.
+template<class TimeClass>
+class TimeBase {
+ public:
+  static const int64_t kHoursPerDay = 24;
+  static const int64_t kMillisecondsPerSecond = 1000;
+  static const int64_t kMillisecondsPerDay =
+      kMillisecondsPerSecond * 60 * 60 * kHoursPerDay;
+  static const int64_t kMicrosecondsPerMillisecond = 1000;
+  static const int64_t kMicrosecondsPerSecond =
+      kMicrosecondsPerMillisecond * kMillisecondsPerSecond;
+  static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
+  static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60;
+  static const int64_t kMicrosecondsPerDay =
+      kMicrosecondsPerHour * kHoursPerDay;
+  static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7;
+  static const int64_t kNanosecondsPerMicrosecond = 1000;
+  static const int64_t kNanosecondsPerSecond =
+      kNanosecondsPerMicrosecond * kMicrosecondsPerSecond;
+
+  // Returns true if this object has not been initialized.
+  //
+  // Warning: Be careful when writing code that performs math on time values,
+  // since it's possible to produce a valid "zero" result that should not be
+  // interpreted as a "null" value.
+  bool IsNull() const {
+    return us_ == 0;
+  }
+
+  // Returns true if this object represents the maximum time.
+  bool IsMax() const { return us_ == std::numeric_limits<int64_t>::max(); }
+
+  // For serializing only. Use FromInternalValue() to reconstitute. Please don't
+  // use this and do arithmetic on it, as it is more error prone than using the
+  // provided operators.
+  int64_t ToInternalValue() const { return us_; }
+
+  TimeClass& operator=(TimeClass other) {
+    us_ = other.us_;
+    return *(static_cast<TimeClass*>(this));
+  }
+
+  // Compute the difference between two times.
+  TimeDelta operator-(TimeClass other) const {
+    return TimeDelta::FromMicroseconds(us_ - other.us_);
+  }
+
+  // Return a new time modified by some delta.
+  TimeClass operator+(TimeDelta delta) const {
+    return TimeClass(bits::SignedSaturatedAdd64(delta.delta_, us_));
+  }
+  TimeClass operator-(TimeDelta delta) const {
+    return TimeClass(-bits::SignedSaturatedSub64(delta.delta_, us_));
+  }
+
+  // Modify by some time delta.
+  TimeClass& operator+=(TimeDelta delta) {
+    return static_cast<TimeClass&>(*this = (*this + delta));
+  }
+  TimeClass& operator-=(TimeDelta delta) {
+    return static_cast<TimeClass&>(*this = (*this - delta));
+  }
+
+  // Comparison operators
+  bool operator==(TimeClass other) const {
+    return us_ == other.us_;
+  }
+  bool operator!=(TimeClass other) const {
+    return us_ != other.us_;
+  }
+  bool operator<(TimeClass other) const {
+    return us_ < other.us_;
+  }
+  bool operator<=(TimeClass other) const {
+    return us_ <= other.us_;
+  }
+  bool operator>(TimeClass other) const {
+    return us_ > other.us_;
+  }
+  bool operator>=(TimeClass other) const {
+    return us_ >= other.us_;
+  }
+
+  // Converts an integer value representing TimeClass to a class. This is used
+  // when deserializing a |TimeClass| structure, using a value known to be
+  // compatible. It is not provided as a constructor because the integer type
+  // may be unclear from the perspective of a caller.
+  static TimeClass FromInternalValue(int64_t us) { return TimeClass(us); }
+
+ protected:
+  explicit TimeBase(int64_t us) : us_(us) {}
+
+  // Time value in a microsecond timebase.
+  int64_t us_;
+};
+
+}  // namespace time_internal
+
+
 // -----------------------------------------------------------------------------
 // Time
 //
 // This class represents an absolute point in time, internally represented as
 // microseconds (s/1,000,000) since 00:00:00 UTC, January 1, 1970.
 
-class Time final {
+class Time final : public time_internal::TimeBase<Time> {
  public:
-  static const int64_t kMillisecondsPerSecond = 1000;
-  static const int64_t kMicrosecondsPerMillisecond = 1000;
-  static const int64_t kMicrosecondsPerSecond = kMicrosecondsPerMillisecond *
-                                                kMillisecondsPerSecond;
-  static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
-  static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60;
-  static const int64_t kMicrosecondsPerDay = kMicrosecondsPerHour * 24;
-  static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7;
-  static const int64_t kNanosecondsPerMicrosecond = 1000;
-  static const int64_t kNanosecondsPerSecond = kNanosecondsPerMicrosecond *
-                                               kMicrosecondsPerSecond;
-
   // Contains the NULL time. Use Time::Now() to get the current time.
-  Time() : us_(0) {}
-
-  // Returns true if the time object has not been initialized.
-  bool IsNull() const { return us_ == 0; }
-
-  // Returns true if the time object is the maximum time.
-  bool IsMax() const { return us_ == std::numeric_limits<int64_t>::max(); }
+  Time() : TimeBase(0) {}
 
   // Returns the current time. Watch out, the system might adjust its clock
   // in which case time will actually go backwards. We don't guarantee that
@@ -200,15 +297,6 @@
   // with which we might compare it.
   static Time Max() { return Time(std::numeric_limits<int64_t>::max()); }
 
-  // Converts to/from internal values. The meaning of the "internal value" is
-  // completely up to the implementation, so it should be treated as opaque.
-  static Time FromInternalValue(int64_t value) {
-    return Time(value);
-  }
-  int64_t ToInternalValue() const {
-    return us_;
-  }
-
   // Converts to/from POSIX time specs.
   static Time FromTimespec(struct timespec ts);
   struct timespec ToTimespec() const;
@@ -226,59 +314,9 @@
   static Time FromJsTime(double ms_since_epoch);
   double ToJsTime() const;
 
-  Time& operator=(const Time& other) {
-    us_ = other.us_;
-    return *this;
-  }
-
-  // Compute the difference between two times.
-  TimeDelta operator-(const Time& other) const {
-    return TimeDelta::FromMicroseconds(us_ - other.us_);
-  }
-
-  // Modify by some time delta.
-  Time& operator+=(const TimeDelta& delta) {
-    us_ += delta.InMicroseconds();
-    return *this;
-  }
-  Time& operator-=(const TimeDelta& delta) {
-    us_ -= delta.InMicroseconds();
-    return *this;
-  }
-
-  // Return a new time modified by some delta.
-  Time operator+(const TimeDelta& delta) const {
-    return Time(us_ + delta.InMicroseconds());
-  }
-  Time operator-(const TimeDelta& delta) const {
-    return Time(us_ - delta.InMicroseconds());
-  }
-
-  // Comparison operators
-  bool operator==(const Time& other) const {
-    return us_ == other.us_;
-  }
-  bool operator!=(const Time& other) const {
-    return us_ != other.us_;
-  }
-  bool operator<(const Time& other) const {
-    return us_ < other.us_;
-  }
-  bool operator<=(const Time& other) const {
-    return us_ <= other.us_;
-  }
-  bool operator>(const Time& other) const {
-    return us_ > other.us_;
-  }
-  bool operator>=(const Time& other) const {
-    return us_ >= other.us_;
-  }
-
  private:
-  explicit Time(int64_t us) : us_(us) {}
-
-  // Time in microseconds in UTC.
-  int64_t us_;
+  friend class time_internal::TimeBase<Time>;
+  explicit Time(int64_t us) : TimeBase(us) {}
 };
 
 std::ostream& operator<<(std::ostream&, const Time&);
@@ -298,9 +336,9 @@
 // Time::Now() may actually decrease or jump).  But note that TimeTicks may
 // "stand still", for example if the computer suspended.
 
-class TimeTicks final {
+class TimeTicks final : public time_internal::TimeBase<TimeTicks> {
  public:
-  TimeTicks() : ticks_(0) {}
+  TimeTicks() : TimeBase(0) {}
 
   // Platform-dependent tick count representing "right now."
   // The resolution of this clock is ~1-15ms.  Resolution varies depending
@@ -318,79 +356,43 @@
   // Returns true if the high-resolution clock is working on this system.
   static bool IsHighResolutionClockWorking();
 
-  // Returns true if this object has not been initialized.
-  bool IsNull() const { return ticks_ == 0; }
-
-  // Converts to/from internal values. The meaning of the "internal value" is
-  // completely up to the implementation, so it should be treated as opaque.
-  static TimeTicks FromInternalValue(int64_t value) {
-    return TimeTicks(value);
-  }
-  int64_t ToInternalValue() const {
-    return ticks_;
-  }
-
-  TimeTicks& operator=(const TimeTicks other) {
-    ticks_ = other.ticks_;
-    return *this;
-  }
-
-  // Compute the difference between two times.
-  TimeDelta operator-(const TimeTicks other) const {
-    return TimeDelta::FromMicroseconds(ticks_ - other.ticks_);
-  }
-
-  // Modify by some time delta.
-  TimeTicks& operator+=(const TimeDelta& delta) {
-    ticks_ += delta.InMicroseconds();
-    return *this;
-  }
-  TimeTicks& operator-=(const TimeDelta& delta) {
-    ticks_ -= delta.InMicroseconds();
-    return *this;
-  }
-
-  // Return a new TimeTicks modified by some delta.
-  TimeTicks operator+(const TimeDelta& delta) const {
-    return TimeTicks(ticks_ + delta.InMicroseconds());
-  }
-  TimeTicks operator-(const TimeDelta& delta) const {
-    return TimeTicks(ticks_ - delta.InMicroseconds());
-  }
-
-  // Comparison operators
-  bool operator==(const TimeTicks& other) const {
-    return ticks_ == other.ticks_;
-  }
-  bool operator!=(const TimeTicks& other) const {
-    return ticks_ != other.ticks_;
-  }
-  bool operator<(const TimeTicks& other) const {
-    return ticks_ < other.ticks_;
-  }
-  bool operator<=(const TimeTicks& other) const {
-    return ticks_ <= other.ticks_;
-  }
-  bool operator>(const TimeTicks& other) const {
-    return ticks_ > other.ticks_;
-  }
-  bool operator>=(const TimeTicks& other) const {
-    return ticks_ >= other.ticks_;
-  }
-
  private:
-  // Please use Now() to create a new object. This is for internal use
-  // and testing. Ticks is in microseconds.
-  explicit TimeTicks(int64_t ticks) : ticks_(ticks) {}
+  friend class time_internal::TimeBase<TimeTicks>;
 
-  // Tick count in microseconds.
-  int64_t ticks_;
+  // Please use Now() to create a new object. This is for internal use
+  // and testing. Ticks are in microseconds.
+  explicit TimeTicks(int64_t ticks) : TimeBase(ticks) {}
 };
 
 inline TimeTicks operator+(const TimeDelta& delta, const TimeTicks& ticks) {
   return ticks + delta;
 }
 
+
+// ThreadTicks ----------------------------------------------------------------
+
+// Represents a clock, specific to a particular thread, than runs only while the
+// thread is running.
+class ThreadTicks final : public time_internal::TimeBase<ThreadTicks> {
+ public:
+  ThreadTicks() : TimeBase(0) {}
+
+  // Returns true if ThreadTicks::Now() is supported on this system.
+  static bool IsSupported();
+
+  // Returns thread-specific CPU-time on systems that support this feature.
+  // Needs to be guarded with a call to IsSupported(). Use this timer
+  // to (approximately) measure how much time the calling thread spent doing
+  // actual work vs. being de-scheduled. May return bogus results if the thread
+  // migrates to another CPU between two calls. Returns an empty ThreadTicks
+  // object until the initialization is completed.
+  static ThreadTicks Now();
+
+ private:
+  // This is for internal use and testing. Ticks are in microseconds.
+  explicit ThreadTicks(int64_t ticks) : TimeBase(ticks) {}
+};
+
 }  // namespace base
 }  // namespace v8