Bug 1338374 - Use alignas rather than AlignedStorage for public JS::ProfilingFrameIterator's internal storage of a private wasm or JIT profiling frame iterator. r=shu
authorJeff Walden <jwalden@mit.edu>
Mon, 30 Jan 2017 15:56:05 -0800
changeset 342804 eb9b629b161aa55f8147a444c9d61c5b7b0b0028
parent 342803 e3cc6b9b36b3aa13c6a6873617913423a0633e90
child 342805 f8970aa3b2d621c962cc9fbc29de2b1ae54f6bfb
push id86967
push userjwalden@mit.edu
push dateTue, 14 Feb 2017 19:36:59 +0000
treeherdermozilla-inbound@07fffe40a023 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1338374
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1338374 - Use alignas rather than AlignedStorage for public JS::ProfilingFrameIterator's internal storage of a private wasm or JIT profiling frame iterator. r=shu
js/public/ProfilingFrameIterator.h
js/src/vm/Stack.cpp
--- a/js/public/ProfilingFrameIterator.h
+++ b/js/public/ProfilingFrameIterator.h
@@ -2,17 +2,17 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef js_ProfilingFrameIterator_h
 #define js_ProfilingFrameIterator_h
 
-#include "mozilla/Alignment.h"
+#include "mozilla/Attributes.h"
 #include "mozilla/Maybe.h"
 
 #include "jsbytecode.h"
 #include "js/GCAPI.h"
 #include "js/TypeDecls.h"
 #include "js/Utility.h"
 
 struct JSContext;
@@ -39,50 +39,54 @@ struct ForEachTrackedOptimizationTypeInf
 // This iterator can be used to walk the stack of a thread suspended at an
 // arbitrary pc. To provide acurate results, profiling must have been enabled
 // (via EnableRuntimeProfilingStack) before executing the callstack being
 // unwound.
 //
 // Note that the caller must not do anything that could cause GC to happen while
 // the iterator is alive, since this could invalidate Ion code and cause its
 // contents to become out of date.
-class JS_PUBLIC_API(ProfilingFrameIterator)
+class MOZ_NON_PARAM JS_PUBLIC_API(ProfilingFrameIterator)
 {
     JSContext* cx_;
     uint32_t sampleBufferGen_;
     js::Activation* activation_;
 
     // When moving past a JitActivation, we need to save the prevJitTop
     // from it to use as the exit-frame pointer when the next caller jit
     // activation (if any) comes around.
     void* savedPrevJitTop_;
 
     static const unsigned StorageSpace = 8 * sizeof(void*);
-    mozilla::AlignedStorage<StorageSpace> storage_;
+    alignas(void*) unsigned char storage_[StorageSpace];
+
+    void* storage() { return storage_; }
+    const void* storage() const { return storage_; }
+
     js::wasm::ProfilingFrameIterator& wasmIter() {
         MOZ_ASSERT(!done());
         MOZ_ASSERT(isWasm());
-        return *reinterpret_cast<js::wasm::ProfilingFrameIterator*>(storage_.addr());
+        return *static_cast<js::wasm::ProfilingFrameIterator*>(storage());
     }
     const js::wasm::ProfilingFrameIterator& wasmIter() const {
         MOZ_ASSERT(!done());
         MOZ_ASSERT(isWasm());
-        return *reinterpret_cast<const js::wasm::ProfilingFrameIterator*>(storage_.addr());
+        return *static_cast<const js::wasm::ProfilingFrameIterator*>(storage());
     }
 
     js::jit::JitProfilingFrameIterator& jitIter() {
         MOZ_ASSERT(!done());
         MOZ_ASSERT(isJit());
-        return *reinterpret_cast<js::jit::JitProfilingFrameIterator*>(storage_.addr());
+        return *static_cast<js::jit::JitProfilingFrameIterator*>(storage());
     }
 
     const js::jit::JitProfilingFrameIterator& jitIter() const {
         MOZ_ASSERT(!done());
         MOZ_ASSERT(isJit());
-        return *reinterpret_cast<const js::jit::JitProfilingFrameIterator*>(storage_.addr());
+        return *static_cast<const js::jit::JitProfilingFrameIterator*>(storage());
     }
 
     void settle();
 
     bool hasSampleBufferGen() const {
         return sampleBufferGen_ != UINT32_MAX;
     }
 
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1776,17 +1776,20 @@ JS::ProfilingFrameIterator::ProfilingFra
         return;
 
     activation_ = cx->profilingActivation();
 
     MOZ_ASSERT(activation_->isProfiling());
 
     static_assert(sizeof(wasm::ProfilingFrameIterator) <= StorageSpace &&
                   sizeof(jit::JitProfilingFrameIterator) <= StorageSpace,
-                  "Need to increase storage");
+                  "ProfilingFrameIterator::storage_ is too small");
+    static_assert(alignof(void*) >= alignof(wasm::ProfilingFrameIterator) &&
+                  alignof(void*) >= alignof(jit::JitProfilingFrameIterator),
+                  "ProfilingFrameIterator::storage_ is too weakly aligned");
 
     iteratorConstruct(state);
     settle();
 }
 
 JS::ProfilingFrameIterator::~ProfilingFrameIterator()
 {
     if (!done()) {
@@ -1830,40 +1833,40 @@ JS::ProfilingFrameIterator::settle()
 
 void
 JS::ProfilingFrameIterator::iteratorConstruct(const RegisterState& state)
 {
     MOZ_ASSERT(!done());
     MOZ_ASSERT(activation_->isWasm() || activation_->isJit());
 
     if (activation_->isWasm()) {
-        new (storage_.addr()) wasm::ProfilingFrameIterator(*activation_->asWasm(), state);
+        new (storage()) wasm::ProfilingFrameIterator(*activation_->asWasm(), state);
         // Set savedPrevJitTop_ to the actual jitTop_ from the runtime.
         savedPrevJitTop_ = activation_->cx()->jitTop;
         return;
     }
 
     MOZ_ASSERT(activation_->asJit()->isActive());
-    new (storage_.addr()) jit::JitProfilingFrameIterator(cx_, state);
+    new (storage()) jit::JitProfilingFrameIterator(cx_, state);
 }
 
 void
 JS::ProfilingFrameIterator::iteratorConstruct()
 {
     MOZ_ASSERT(!done());
     MOZ_ASSERT(activation_->isWasm() || activation_->isJit());
 
     if (activation_->isWasm()) {
-        new (storage_.addr()) wasm::ProfilingFrameIterator(*activation_->asWasm());
+        new (storage()) wasm::ProfilingFrameIterator(*activation_->asWasm());
         return;
     }
 
     MOZ_ASSERT(activation_->asJit()->isActive());
     MOZ_ASSERT(savedPrevJitTop_ != nullptr);
-    new (storage_.addr()) jit::JitProfilingFrameIterator(savedPrevJitTop_);
+    new (storage()) jit::JitProfilingFrameIterator(savedPrevJitTop_);
 }
 
 void
 JS::ProfilingFrameIterator::iteratorDestroy()
 {
     MOZ_ASSERT(!done());
     MOZ_ASSERT(activation_->isWasm() || activation_->isJit());