Reland "Implement AlignedAlloc and AlignedFree"

This reverts commit 369001ee353fb6a8fa2414deaca56af289b89c87.

Reason for revert: Fix compilation error on Mac with Skia

Original change's description:
> Revert "Implement AlignedAlloc and AlignedFree"
>
> This reverts commit 0ac8c652c3568082ef6bcf6f3a1042a6ffad9bbb.
>
> Reason for revert: Breaking compilation in Skia
>
> Original change's description:
> > Implement AlignedAlloc and AlignedFree
> >
> > This patch implements `AlignedAlloc()` and `AlignedFree()` referenced
> > from `base::AlignedAlloc()` and `base::AlignedFree()` in Chromium.
> >
> > Bug: dawn:824
> > Change-Id: Ifcd794a14be29c006e9a39323252dd6b867a30dc
> > Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/183983
> > Reviewed-by: Corentin Wallez <cwallez@chromium.org>
> > Reviewed-by: Austin Eng <enga@chromium.org>
> > Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
>
> TBR=cwallez@chromium.org,jiawei.shao@intel.com,enga@chromium.org,dawn-scoped@luci-project-accounts.iam.gserviceaccount.com
>
> Change-Id: If4f76d409ae56aa4d35b2008c12860a005d9f285
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: dawn:824
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/184601
> Auto-Submit: Corentin Wallez <cwallez@chromium.org>
> Commit-Queue: Ben Clayton <bclayton@google.com>
> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
> Reviewed-by: Ben Clayton <bclayton@google.com>

Bug: dawn:824
Change-Id: I9a1892b0a6397194019a8251e287d063accb45b2
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/184682
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/common/AlignedAlloc.cpp b/src/dawn/common/AlignedAlloc.cpp
new file mode 100644
index 0000000..d3eca92
--- /dev/null
+++ b/src/dawn/common/AlignedAlloc.cpp
@@ -0,0 +1,66 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "dawn/common/AlignedAlloc.h"
+
+#include "dawn/common/Assert.h"
+#include "dawn/common/Math.h"
+#include "dawn/common/Platform.h"
+
+namespace dawn {
+
+void* AlignedAlloc(size_t size, size_t alignment) {
+    DAWN_ASSERT(size > 0);
+    DAWN_ASSERT(IsPowerOfTwo(alignment));
+    DAWN_ASSERT(size % alignment == 0);
+
+#if DAWN_PLATFORM_IS(WINDOWS)
+    return _aligned_malloc(size, alignment);
+
+#elif DAWN_PLATFORM_IS(ANDROID)
+    // Currently std::aligned_alloc() is not supported on the Android build of Chromium. Luckily,
+    // memalign() on Android returns pointers which can safely be used with free(), so we can use it
+    // instead.
+    return memalign(alignment, size);
+
+#else
+    return aligned_alloc(alignment, size);
+
+#endif
+}
+
+void AlignedFree(void* alignedPtr) {
+#if DAWN_PLATFORM_IS(WINDOWS)
+    _aligned_free(alignedPtr);
+
+#else
+    free(alignedPtr);
+
+#endif
+}
+
+}  // namespace dawn
diff --git a/src/dawn/common/AlignedAlloc.h b/src/dawn/common/AlignedAlloc.h
new file mode 100644
index 0000000..9dfe0ba
--- /dev/null
+++ b/src/dawn/common/AlignedAlloc.h
@@ -0,0 +1,70 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_DAWN_COMMON_ALIGNED_ALLOC_H_
+#define SRC_DAWN_COMMON_ALIGNED_ALLOC_H_
+
+#include <cstdlib>
+
+namespace dawn {
+
+// The implementations of dawn::AlignedAlloc() and dawn::AlignedFree() are referenced from
+// base::AlignedAlloc() and base::AlignedFree() in Chromium (in `base/memory/aligned_memory.h`).
+//
+// In Dawn, a runtime sized aligned allocation can be created:
+//
+//   float* my_array = static_cast<float*>(AlignedAlloc(size, alignment));
+//   CHECK(reinterpret_cast<uintptr_t>(my_array) % alignment == 0);
+//   memset(my_array, 0, size);  // fills entire object.
+//
+//   // ... later, to release the memory:
+//   AlignedFree(my_array);
+//
+// Or using unique_ptr:
+//
+//   std::unique_ptr<float, AlignedFreeDeleter> my_array(
+//       static_cast<float*>(AlignedAlloc(size, alignment)));
+
+// Allocate memory of size `size` aligned to `alignment`.
+// The `alignment` parameter must be an integer power of 2.
+// The `size` parameter must be an integral multiple of `alignment`.
+// Note that the memory allocated by `dawn::AlignedAlloc()` can only be deallocated by
+// `dawn::AlignedFree()` otherwise on Windows the aligned memory may not be reclaimed correctly.
+void* AlignedAlloc(size_t size, size_t alignment);
+
+// Deallocate memory allocated by `AlignedAlloc`.
+void AlignedFree(void* alignedPtr);
+
+// Deleter for use with unique_ptr. E.g., use as
+//   std::unique_ptr<Foo, dawn::AlignedFreeDeleter> foo;
+struct AlignedFreeDeleter {
+    inline void operator()(void* ptr) const { AlignedFree(ptr); }
+};
+
+}  // namespace dawn
+
+#endif  // SRC_DAWN_COMMON_ALIGNED_ALLOC_H_
diff --git a/src/dawn/common/BUILD.gn b/src/dawn/common/BUILD.gn
index aa6eecd..094e737 100644
--- a/src/dawn/common/BUILD.gn
+++ b/src/dawn/common/BUILD.gn
@@ -239,6 +239,8 @@
     is_ios) {
   static_library("common") {
     sources = [
+      "AlignedAlloc.cpp",
+      "AlignedAlloc.h",
       "Alloc.h",
       "Assert.cpp",
       "Assert.h",
diff --git a/src/dawn/common/CMakeLists.txt b/src/dawn/common/CMakeLists.txt
index 477ed12..37f7e66 100644
--- a/src/dawn/common/CMakeLists.txt
+++ b/src/dawn/common/CMakeLists.txt
@@ -46,6 +46,8 @@
 target_sources(dawn_common PRIVATE
     ${DAWN_VERSION_AUTOGEN_SOURCES}
     ${DAWN_GPU_INFO_AUTOGEN_SOURCES}
+    "AlignedAlloc.cpp"
+    "AlignedAlloc.h"
     "Alloc.h"
     "Assert.cpp"
     "Assert.h"
diff --git a/src/dawn/common/SlabAllocator.cpp b/src/dawn/common/SlabAllocator.cpp
index 3f095d6..f668f37 100644
--- a/src/dawn/common/SlabAllocator.cpp
+++ b/src/dawn/common/SlabAllocator.cpp
@@ -31,6 +31,7 @@
 #include <cstdlib>
 #include <limits>
 #include <new>
+#include "dawn/common/AlignedAlloc.h"
 #include "dawn/common/Assert.h"
 #include "dawn/common/Math.h"
 
@@ -62,7 +63,7 @@
         DAWN_ASSERT(slab->blocksInUse == 0);
         char* allocation = slab->allocation;
         slab->~Slab();  // Placement delete.
-        delete[] allocation;
+        AlignedFree(allocation);
     }
 }
 
@@ -79,12 +80,7 @@
       mIndexLinkNodeOffset(Align(objectSize, alignof(IndexLinkNode))),
       mBlockStride(Align(mIndexLinkNodeOffset + u32_sizeof<IndexLinkNode>, objectAlignment)),
       mBlocksPerSlab(blocksPerSlab),
-      mTotalAllocationSize(
-          // required allocation size
-          static_cast<size_t>(mSlabBlocksOffset) + mBlocksPerSlab * mBlockStride +
-          // Pad the allocation size by mAllocationAlignment so that the aligned allocation still
-          // fulfills the required size.
-          mAllocationAlignment) {
+      mTotalAllocationSize(static_cast<size_t>(mSlabBlocksOffset) + mBlocksPerSlab * mBlockStride) {
     DAWN_ASSERT(IsPowerOfTwo(mAllocationAlignment));
 }
 
@@ -232,10 +228,7 @@
         return;
     }
 
-    // TODO(crbug.com/dawn/824): Use aligned_alloc when possible. It should be available with
-    // C++17 but on macOS it also requires macOS 10.15 to work.
-    char* allocation = new char[mTotalAllocationSize];
-    char* alignedPtr = AlignPtr(allocation, mAllocationAlignment);
+    char* alignedPtr = static_cast<char*>(AlignedAlloc(mTotalAllocationSize, mAllocationAlignment));
 
     char* dataStart = alignedPtr + mSlabBlocksOffset;
 
@@ -247,7 +240,7 @@
     IndexLinkNode* lastNode = OffsetFrom(node, mBlocksPerSlab - 1);
     lastNode->nextIndex = kInvalidIndex;
 
-    mAvailableSlabs.Prepend(new (alignedPtr) Slab(allocation, node));
+    mAvailableSlabs.Prepend(new (alignedPtr) Slab(alignedPtr, node));
 }
 
 }  // namespace dawn