[Reland] Add aligned new/delete operators to allocator shim

This CL is a reland of [1] with a fix for when using precompiled headers.  The
object file allocator_shim.o is byte-for-byte identical to the one built at [1]
(at least on a Linux release build).

[1] https://chromium-review.googlesource.com/c/chromium/src/+/1401050

BUG=855773
R=thakis

Change-Id: Ic4321f5c1526e1ecfdffcb58cfb2687875316fa5
Reviewed-on: https://chromium-review.googlesource.com/c/1407435
Reviewed-by: Nico Weber <thakis@chromium.org>
Reviewed-by: Primiano Tucci <primiano@chromium.org>
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#622185}
diff --git a/base/allocator/allocator_shim.cc b/base/allocator/allocator_shim.cc
index 7f5f310..df30207 100644
--- a/base/allocator/allocator_shim.cc
+++ b/base/allocator/allocator_shim.cc
@@ -162,6 +162,20 @@
   return ptr;
 }
 
+ALWAYS_INLINE void* ShimCppAlignedNew(size_t size, size_t alignment) {
+  const allocator::AllocatorDispatch* const chain_head = GetChainHead();
+  void* ptr;
+  do {
+    void* context = nullptr;
+#if defined(OS_MACOSX)
+    context = malloc_default_zone();
+#endif
+    ptr = chain_head->alloc_aligned_function(chain_head, size, alignment,
+                                             context);
+  } while (!ptr && CallNewHandler(size));
+  return ptr;
+}
+
 ALWAYS_INLINE void ShimCppDelete(void* address) {
   void* context = nullptr;
 #if defined(OS_MACOSX)
diff --git a/base/allocator/allocator_shim_override_cpp_symbols.h b/base/allocator/allocator_shim_override_cpp_symbols.h
index b1e6ee2..09c83ff 100644
--- a/base/allocator/allocator_shim_override_cpp_symbols.h
+++ b/base/allocator/allocator_shim_override_cpp_symbols.h
@@ -14,6 +14,44 @@
 #include <new>
 
 #include "base/allocator/allocator_shim_internals.h"
+#include "build/build_config.h"
+
+// std::align_val_t isn't available until C++17, but we want to override aligned
+// new/delete anyway to prevent a possible situation where a library gets loaded
+// in that uses the aligned operators.  We want to avoid a situation where
+// separate heaps are used.
+// TODO(thomasanderson): Remove this once building with C++17 or later.
+#if defined(__cpp_aligned_new) && __cpp_aligned_new >= 201606
+#define ALIGN_VAL_T std::align_val_t
+#define ALIGN_LINKAGE
+#define ALIGN_NEW operator new
+#define ALIGN_NEW_NOTHROW operator new
+#define ALIGN_DEL operator delete
+#define ALIGN_DEL_SIZED operator delete
+#define ALIGN_DEL_NOTHROW operator delete
+#define ALIGN_NEW_ARR operator new[]
+#define ALIGN_NEW_ARR_NOTHROW operator new[]
+#define ALIGN_DEL_ARR operator delete[]
+#define ALIGN_DEL_ARR_SIZED operator delete[]
+#define ALIGN_DEL_ARR_NOTHROW operator delete[]
+#else
+#define ALIGN_VAL_T size_t
+#define ALIGN_LINKAGE extern "C"
+#if defined(OS_MACOSX) || defined(OS_WIN)
+#error "Mangling is different on these platforms."
+#else
+#define ALIGN_NEW _ZnwmSt11align_val_t
+#define ALIGN_NEW_NOTHROW _ZnwmSt11align_val_tRKSt9nothrow_t
+#define ALIGN_DEL _ZdlPvSt11align_val_t
+#define ALIGN_DEL_SIZED _ZdlPvmSt11align_val_t
+#define ALIGN_DEL_NOTHROW _ZdlPvSt11align_val_tRKSt9nothrow_t
+#define ALIGN_NEW_ARR _ZnamSt11align_val_t
+#define ALIGN_NEW_ARR_NOTHROW _ZnamSt11align_val_tRKSt9nothrow_t
+#define ALIGN_DEL_ARR _ZdaPvSt11align_val_t
+#define ALIGN_DEL_ARR_SIZED _ZdaPvmSt11align_val_t
+#define ALIGN_DEL_ARR_NOTHROW _ZdaPvSt11align_val_tRKSt9nothrow_t
+#endif
+#endif
 
 SHIM_ALWAYS_EXPORT void* operator new(size_t size) {
   return ShimCppNew(size);
@@ -57,3 +95,59 @@
 SHIM_ALWAYS_EXPORT void operator delete[](void* p, size_t) __THROW {
   ShimCppDelete(p);
 }
+
+SHIM_ALWAYS_EXPORT ALIGN_LINKAGE void* ALIGN_NEW(std::size_t size,
+                                                 ALIGN_VAL_T alignment) {
+  return ShimCppAlignedNew(size, static_cast<size_t>(alignment));
+}
+
+SHIM_ALWAYS_EXPORT ALIGN_LINKAGE void* ALIGN_NEW_NOTHROW(
+    std::size_t size,
+    ALIGN_VAL_T alignment,
+    const std::nothrow_t&) __THROW {
+  return ShimCppAlignedNew(size, static_cast<size_t>(alignment));
+}
+
+SHIM_ALWAYS_EXPORT ALIGN_LINKAGE void ALIGN_DEL(void* p, ALIGN_VAL_T) __THROW {
+  ShimCppDelete(p);
+}
+
+SHIM_ALWAYS_EXPORT ALIGN_LINKAGE void ALIGN_DEL_SIZED(void* p,
+                                                      std::size_t size,
+                                                      ALIGN_VAL_T) __THROW {
+  ShimCppDelete(p);
+}
+
+SHIM_ALWAYS_EXPORT ALIGN_LINKAGE void
+ALIGN_DEL_NOTHROW(void* p, ALIGN_VAL_T, const std::nothrow_t&) __THROW {
+  ShimCppDelete(p);
+}
+
+SHIM_ALWAYS_EXPORT ALIGN_LINKAGE void* ALIGN_NEW_ARR(
+    std::size_t size,
+    ALIGN_VAL_T alignment) __THROW {
+  return ShimCppAlignedNew(size, static_cast<size_t>(alignment));
+}
+
+SHIM_ALWAYS_EXPORT ALIGN_LINKAGE void* ALIGN_NEW_ARR_NOTHROW(
+    std::size_t size,
+    ALIGN_VAL_T alignment,
+    const std::nothrow_t&) __THROW {
+  return ShimCppAlignedNew(size, static_cast<size_t>(alignment));
+}
+
+SHIM_ALWAYS_EXPORT ALIGN_LINKAGE void ALIGN_DEL_ARR(void* p,
+                                                    ALIGN_VAL_T) __THROW {
+  ShimCppDelete(p);
+}
+
+SHIM_ALWAYS_EXPORT ALIGN_LINKAGE void ALIGN_DEL_ARR_SIZED(void* p,
+                                                          std::size_t size,
+                                                          ALIGN_VAL_T) __THROW {
+  ShimCppDelete(p);
+}
+
+SHIM_ALWAYS_EXPORT ALIGN_LINKAGE void
+ALIGN_DEL_ARR_NOTHROW(void* p, ALIGN_VAL_T, const std::nothrow_t&) __THROW {
+  ShimCppDelete(p);
+}