Bug 1443592: Part 1: Introduce opaque LiveSavedFrameCache::Key type for cache keys. r=fitzgen
authorJim Blandy <jimb@mozilla.com>
Mon, 05 Mar 2018 18:03:56 -0800
changeset 462168 faa2dd792d1cfdc83004c048a7bb9e41c388fb04
parent 462167 e101b0c833ffab505fe916afac194c01f0af37dd
child 462169 1790490874a09b2da5731945e629e6b708ce9f5f
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfitzgen
bugs1443592
milestone60.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 1443592: Part 1: Introduce opaque LiveSavedFrameCache::Key type for cache keys. r=fitzgen By design, the LiveSavedFrameCache holds the addresses of both live and dead stack frames. This change wraps those addresses in an opaque type that can only be compared for equality with other such values, and provides no interface to retrieve the underlying pointer, ensuring statically that we will not accidentally use a cache key to access memory. MozReview-Commit-ID: 9Wom5gFVQls
js/src/vm/SavedStacks.cpp
js/src/vm/Stack.h
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -105,24 +105,24 @@ LiveSavedFrameCache::find(JSContext* cx,
 {
     MOZ_ASSERT(initialized());
     MOZ_ASSERT(!frameIter.done());
     MOZ_ASSERT(frameIter.hasCachedSavedFrame());
 
     Maybe<FramePtr> maybeFramePtr = getFramePtr(frameIter);
     MOZ_ASSERT(maybeFramePtr.isSome());
 
-    FramePtr framePtr(*maybeFramePtr);
+    Key key(*maybeFramePtr);
     const jsbytecode* pc = frameIter.pc();
     size_t numberStillValid = 0;
 
     frame.set(nullptr);
     for (auto* p = frames->begin(); p < frames->end(); p++) {
         numberStillValid++;
-        if (framePtr == p->framePtr && pc == p->pc) {
+        if (key == p->key && pc == p->pc) {
             frame.set(p->savedFrame);
             break;
         }
     }
 
     if (!frame) {
         frames->clear();
         return;
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1168,24 +1168,37 @@ struct DefaultHasher<AbstractFramePtr> {
 // recently, so if there's a compartment mismatch, we throw away the whole
 // cache.
 class LiveSavedFrameCache
 {
   public:
     using FramePtr = mozilla::Variant<AbstractFramePtr, jit::CommonFrameLayout*>;
 
   private:
+    // A key in the cache: the address of a frame, live or dead, for which we
+    // can cache SavedFrames. Since the pointer may not be live, the only
+    // operation this type permits is comparison.
+    class Key {
+        FramePtr framePtr;
+
+      public:
+        MOZ_IMPLICIT Key(const FramePtr& framePtr) : framePtr(framePtr) { }
+
+        bool operator==(const Key& rhs) const { return rhs.framePtr == this->framePtr; }
+        bool operator!=(const Key& rhs) const { return !(rhs == *this); }
+    };
+
     struct Entry
     {
-        const FramePtr       framePtr;
+        const Key            key;
         const jsbytecode*    pc;
         HeapPtr<SavedFrame*> savedFrame;
 
-        Entry(const FramePtr& framePtr, const jsbytecode* pc, SavedFrame* savedFrame)
-          : framePtr(framePtr)
+        Entry(const Key& key, const jsbytecode* pc, SavedFrame* savedFrame)
+          : key(key)
           , pc(pc)
           , savedFrame(savedFrame)
         { }
     };
 
     using EntryVector = Vector<Entry, 0, SystemAllocPolicy>;
     EntryVector* frames;