Merge mozilla-central to autoland. CLOSED TREE
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Thu, 08 Mar 2018 20:03:58 +0200
changeset 462233 c5650d15df01218401ce2ae9c57e1db6ae207054
parent 462232 322eaf394be01fb38438f28397fb90581cb50764 (current diff)
parent 462213 55d91695f4bb951c224005155baef054a786c1f7 (diff)
child 462234 3ebf1fc64bf0074c4fee1928df7542bd30b60ea6
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)
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
Merge mozilla-central to autoland. CLOSED TREE
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -2248,16 +2248,20 @@ this.PlacesPanelview = class extends Pla
     } else {
       panelview.removeAttribute("emptyplacesresult");
       try {
         panelview.removeChild(panelview._emptyMenuitem);
       } catch (ex) {}
     }
   }
 
+  _isPopupOpen() {
+    return PanelView.forNode(this._viewElt).active;
+  }
+
   _onPopupHidden(event) {
     let panelview = event.originalTarget;
     let placesNode = panelview._placesNode;
     // Avoid handling ViewHiding of inner views
     if (placesNode && PlacesUIUtils.getViewForNode(panelview) == this) {
       // UI performance: folder queries are cheap, keep the resultnode open
       // so we don't rebuild its contents whenever the popup is reopened.
       // Though, we want to always close feed containers so their expiration
--- a/browser/components/places/tests/browser/browser.ini
+++ b/browser/components/places/tests/browser/browser.ini
@@ -90,16 +90,17 @@ skip-if = (os == 'win' && ccov) # Bug 14
 [browser_library_openFlatContainer.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_panel_leak.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_search.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_views_liveupdate.js]
 [browser_markPageAsFollowedLink.js]
+[browser_panelview_bookmarks_delete.js]
 [browser_paste_bookmarks.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 subsuite = clipboard
 [browser_paste_into_tags.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_remove_bookmarks.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 subsuite = clipboard
new file mode 100644
--- /dev/null
+++ b/browser/components/places/tests/browser/browser_panelview_bookmarks_delete.js
@@ -0,0 +1,61 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_URL = "https://www.example.com/";
+
+/**
+ * Checks that the Bookmarks subview is updated after deleting an item.
+ */
+add_task(async function test_panelview_bookmarks_delete() {
+  await PlacesUtils.bookmarks.insert({
+    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+    url: TEST_URL,
+    title: TEST_URL,
+  });
+
+  let mainView = document.getElementById("appMenu-mainView");
+  let promise = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
+  PanelUI.show();
+  await promise;
+
+  let libraryView = document.getElementById("appMenu-libraryView");
+  promise = BrowserTestUtils.waitForEvent(libraryView, "ViewShown");
+  document.getElementById("appMenu-library-button").click();
+  await promise;
+
+  let bookmarksView = document.getElementById("PanelUI-bookmarks");
+  promise = BrowserTestUtils.waitForEvent(bookmarksView, "ViewShown");
+  document.getElementById("appMenu-library-bookmarks-button").click();
+  await promise;
+
+  let list = document.getElementById("panelMenu_bookmarksMenu");
+  let listItem = [...list.childNodes].find(node => node.label == TEST_URL);
+
+  let placesContext = document.getElementById("placesContext");
+  promise = BrowserTestUtils.waitForEvent(placesContext, "popupshown");
+  EventUtils.synthesizeMouseAtCenter(listItem, {
+    button: 2,
+    type: "contextmenu"
+  });
+  await promise;
+
+  promise = new Promise(resolve => {
+    let observer = new MutationObserver(mutations => {
+      if (listItem.parentNode == null) {
+        Assert.ok(true, "The bookmarks list item was removed.");
+        observer.disconnect();
+        resolve();
+      }
+    });
+    observer.observe(list, { childList: true });
+  });
+  let placesContextDelete = document.getElementById("placesContext_delete");
+  EventUtils.synthesizeMouseAtCenter(placesContextDelete, {});
+  await promise;
+
+  promise = BrowserTestUtils.waitForEvent(PanelUI.panel, "popuphidden");
+  PanelUI.hide();
+  await promise;
+});
--- a/devtools/server/actors/errordocs.js
+++ b/devtools/server/actors/errordocs.js
@@ -78,16 +78,17 @@ const ErrorDocs = {
   JSMSG_BAD_CONST_DECL: "Missing_initializer_in_const",
   JSMSG_OF_AFTER_FOR_LOOP_DECL: "Invalid_for-of_initializer",
   JSMSG_BAD_URI: "Malformed_URI",
   JSMSG_DEPRECATED_DELETE_OPERAND: "Delete_in_strict_mode",
   JSMSG_MISSING_FORMAL: "Missing_formal_parameter",
   JSMSG_CANT_TRUNCATE_ARRAY: "Non_configurable_array_element",
   JSMSG_INCOMPATIBLE_PROTO: "Called_on_incompatible_type",
   JSMSG_INCOMPATIBLE_METHOD: "Called_on_incompatible_type",
+  JSMSG_BAD_INSTANCEOF_RHS: "invalid_right_hand_side_instanceof_operand",
 };
 
 const MIXED_CONTENT_LEARN_MORE = "https://developer.mozilla.org/docs/Web/Security/Mixed_content";
 const TRACKING_PROTECTION_LEARN_MORE = "https://developer.mozilla.org/Firefox/Privacy/Tracking_Protection";
 const INSECURE_PASSWORDS_LEARN_MORE = "https://developer.mozilla.org/docs/Web/Security/Insecure_passwords";
 const PUBLIC_KEY_PINS_LEARN_MORE = "https://developer.mozilla.org/docs/Web/HTTP/Public_Key_Pinning";
 const STRICT_TRANSPORT_SECURITY_LEARN_MORE = "https://developer.mozilla.org/docs/Web/HTTP/Headers/Strict-Transport-Security";
 const WEAK_SIGNATURE_ALGORITHM_LEARN_MORE = "https://developer.mozilla.org/docs/Web/Security/Weak_Signature_Algorithm";
--- a/dom/base/NodeInfo.h
+++ b/dom/base/NodeInfo.h
@@ -20,18 +20,19 @@
 
 #ifndef mozilla_dom_NodeInfo_h___
 #define mozilla_dom_NodeInfo_h___
 
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/dom/NameSpaceConstants.h"
 #include "nsString.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/Maybe.h"
 #include "nsAtom.h"
-#include "plhash.h"
+#include "nsHashKeys.h"
 
 class nsIDocument;
 class nsNodeInfoManager;
 
 namespace mozilla {
 namespace dom {
 
 class NodeInfo final
@@ -243,42 +244,73 @@ protected:
    */
 
   class NodeInfoInner
   {
   public:
     NodeInfoInner()
       : mName(nullptr), mPrefix(nullptr), mNamespaceID(kNameSpaceID_Unknown),
         mNodeType(0), mNameString(nullptr), mExtraName(nullptr),
-        mHash(0), mHashInitialized(false)
+        mHash()
     {
     }
     NodeInfoInner(nsAtom *aName, nsAtom *aPrefix, int32_t aNamespaceID,
                     uint16_t aNodeType, nsAtom* aExtraName)
       : mName(aName), mPrefix(aPrefix), mNamespaceID(aNamespaceID),
         mNodeType(aNodeType), mNameString(nullptr), mExtraName(aExtraName),
-        mHash(aName->hash()), mHashInitialized(true)
+        mHash()
     {
     }
     NodeInfoInner(const nsAString& aTmpName, nsAtom *aPrefix,
                     int32_t aNamespaceID, uint16_t aNodeType)
       : mName(nullptr), mPrefix(aPrefix), mNamespaceID(aNamespaceID),
         mNodeType(aNodeType), mNameString(&aTmpName), mExtraName(nullptr),
-        mHash(0), mHashInitialized(false)
+        mHash()
+    {
+    }
+
+    bool operator==(const NodeInfoInner& aOther) const
     {
+      if (mPrefix != aOther.mPrefix ||
+          mNamespaceID != aOther.mNamespaceID ||
+          mNodeType != aOther.mNodeType ||
+          mExtraName != aOther.mExtraName) {
+        return false;
+      }
+
+      if (mName) {
+        if (aOther.mName) {
+          return mName == aOther.mName;
+        }
+        return mName->Equals(*(aOther.mNameString));
+      }
+
+      if (aOther.mName) {
+        return aOther.mName->Equals(*(mNameString));
+      }
+
+      return mNameString->Equals(*(aOther.mNameString));
+    }
+
+    uint32_t Hash() const
+    {
+      if (!mHash) {
+        mHash.emplace(
+            mName ? mName->hash() : mozilla::HashString(*mNameString));
+      }
+      return mHash.value();
     }
 
     nsAtom* const MOZ_OWNING_REF mName;
     nsAtom* MOZ_OWNING_REF mPrefix;
     int32_t             mNamespaceID;
     uint16_t            mNodeType; // As defined by nsIDOMNode.nodeType
     const nsAString* const mNameString;
     nsAtom* MOZ_OWNING_REF mExtraName; // Only used by PIs and DocTypes
-    PLHashNumber      mHash;
-    bool              mHashInitialized;
+    mutable mozilla::Maybe<const uint32_t> mHash;
   };
 
   // nsNodeInfoManager needs to pass mInner to the hash table.
   friend class ::nsNodeInfoManager;
 
   // This is a non-owning reference, but it's safe since it's set to nullptr
   // by nsNodeInfoManager::DropDocumentReference when the document is destroyed.
   nsIDocument* MOZ_NON_OWNING_REF mDocument; // Cache of mOwnerManager->mDocument
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -7423,17 +7423,17 @@ nsGlobalWindowInner::PromiseDocumentFlus
   RefPtr<Promise> resultPromise = Promise::Create(global, aError);
   if (aError.Failed()) {
     return nullptr;
   }
 
   UniquePtr<PromiseDocumentFlushedResolver> flushResolver(
     new PromiseDocumentFlushedResolver(resultPromise, aCallback));
 
-  if (!shell->NeedStyleFlush() && !shell->NeedLayoutFlush()) {
+  if (!shell->NeedFlush(FlushType::Style)) {
     flushResolver->Call();
     return resultPromise.forget();
   }
 
   if (!mObservingDidRefresh) {
     bool success = shell->AddPostRefreshObserver(this);
     if (!success) {
       aError.Throw(NS_ERROR_FAILURE);
@@ -7518,21 +7518,20 @@ nsGlobalWindowInner::DidRefresh()
     mObservingDidRefresh = false;
   });
 
   MOZ_ASSERT(mDoc);
 
   nsIPresShell* shell = mDoc->GetShell();
   MOZ_ASSERT(shell);
 
-  if (shell->NeedStyleFlush() || shell->NeedLayoutFlush()) {
+  if (shell->NeedStyleFlush() || shell->HasPendingReflow()) {
     // By the time our observer fired, something has already invalidated
-    // style or layout - or perhaps we're still in the middle of a flush that
-    // was interrupted. In either case, we'll wait until the next refresh driver
-    // tick instead and try again.
+    // style and maybe layout. We'll wait until the next refresh driver
+    // tick instead.
     rejectionGuard.release();
     return;
   }
 
   bool success = shell->RemovePostRefreshObserver(this);
   if (!success) {
     return;
   }
--- a/dom/base/nsNodeInfoManager.cpp
+++ b/dom/base/nsNodeInfoManager.cpp
@@ -33,117 +33,39 @@
 #include "NullPrincipal.h"
 
 using namespace mozilla;
 using mozilla::dom::NodeInfo;
 
 #include "mozilla/Logging.h"
 
 static LazyLogModule gNodeInfoManagerLeakPRLog("NodeInfoManagerLeak");
-
-PLHashNumber
-nsNodeInfoManager::GetNodeInfoInnerHashValue(const void *key)
-{
-  MOZ_ASSERT(key, "Null key passed to NodeInfo::GetHashValue!");
-
-  auto *node = const_cast<NodeInfo::NodeInfoInner*>
-    (reinterpret_cast<const NodeInfo::NodeInfoInner*>(key));
-  if (!node->mHashInitialized) {
-    node->mHash = node->mName ? node->mName->hash() : HashString(*(node->mNameString));
-    node->mHashInitialized = true;
-  }
-
-  return node->mHash;
-}
-
-
-int
-nsNodeInfoManager::NodeInfoInnerKeyCompare(const void *key1, const void *key2)
-{
-  MOZ_ASSERT(key1 && key2, "Null key passed to NodeInfoInnerKeyCompare!");
-
-  auto *node1 = reinterpret_cast<const NodeInfo::NodeInfoInner*>(key1);
-  auto *node2 = reinterpret_cast<const NodeInfo::NodeInfoInner*>(key2);
-
-  if (node1->mPrefix != node2->mPrefix ||
-      node1->mNamespaceID != node2->mNamespaceID ||
-      node1->mNodeType != node2->mNodeType ||
-      node1->mExtraName != node2->mExtraName) {
-    return 0;
-  }
-
-  if (node1->mName) {
-    if (node2->mName) {
-      return (node1->mName == node2->mName);
-    }
-    return (node1->mName->Equals(*(node2->mNameString)));
-  }
-  if (node2->mName) {
-    return (node2->mName->Equals(*(node1->mNameString)));
-  }
-  return (node1->mNameString->Equals(*(node2->mNameString)));
-}
-
-
-static void* PR_CALLBACK
-AllocTable(void* pool, size_t size)
-{
-  return malloc(size);
-}
-
-static void PR_CALLBACK
-FreeTable(void* pool, void* item)
-{
-  free(item);
-}
-
-static PLHashEntry* PR_CALLBACK
-AllocEntry(void* pool, const void* key)
-{
-  return (PLHashEntry*)malloc(sizeof(PLHashEntry));
-}
-
-static void PR_CALLBACK
-FreeEntry(void* pool, PLHashEntry* he, unsigned flag)
-{
-  if (flag == HT_FREE_ENTRY) {
-    free(he);
-  }
-}
-
-static PLHashAllocOps allocOps =
-  { AllocTable, FreeTable, AllocEntry, FreeEntry };
+static const uint32_t kInitialNodeInfoHashSize = 32;
 
 nsNodeInfoManager::nsNodeInfoManager()
-  : mDocument(nullptr),
+  : mNodeInfoHash(kInitialNodeInfoHashSize),
+    mDocument(nullptr),
     mNonDocumentNodeInfos(0),
     mTextNodeInfo(nullptr),
     mCommentNodeInfo(nullptr),
     mDocumentNodeInfo(nullptr),
     mRecentlyUsedNodeInfos{},
     mSVGEnabled(eTriUnset),
     mMathMLEnabled(eTriUnset)
 {
   nsLayoutStatics::AddRef();
 
   if (gNodeInfoManagerLeakPRLog)
     MOZ_LOG(gNodeInfoManagerLeakPRLog, LogLevel::Debug,
            ("NODEINFOMANAGER %p created", this));
-
-  mNodeInfoHash = PL_NewHashTable(32, GetNodeInfoInnerHashValue,
-                                  NodeInfoInnerKeyCompare,
-                                  PL_CompareValues, &allocOps, nullptr);
 }
 
 
 nsNodeInfoManager::~nsNodeInfoManager()
 {
-  if (mNodeInfoHash)
-    PL_HashTableDestroy(mNodeInfoHash);
-
   // Note: mPrincipal may be null here if we never got inited correctly
   mPrincipal = nullptr;
 
   mBindingManager = nullptr;
 
   if (gNodeInfoManagerLeakPRLog)
     MOZ_LOG(gNodeInfoManagerLeakPRLog, LogLevel::Debug,
            ("NODEINFOMANAGER %p destroyed", this));
@@ -180,18 +102,16 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_B
   if (tmp->mDocument) {
     return NS_CYCLE_COLLECTION_PARTICIPANT(nsDocument)->CanSkipThis(tmp->mDocument);
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
 nsresult
 nsNodeInfoManager::Init(nsIDocument *aDocument)
 {
-  NS_ENSURE_TRUE(mNodeInfoHash, NS_ERROR_OUT_OF_MEMORY);
-
   NS_PRECONDITION(!mPrincipal,
                   "Being inited when we already have a principal?");
 
   mPrincipal = NullPrincipal::Create();
 
   if (aDocument) {
     mBindingManager = new nsBindingManager(aDocument);
   }
@@ -202,135 +122,107 @@ nsNodeInfoManager::Init(nsIDocument *aDo
 
   if (gNodeInfoManagerLeakPRLog)
     MOZ_LOG(gNodeInfoManagerLeakPRLog, LogLevel::Debug,
            ("NODEINFOMANAGER %p Init document=%p", this, aDocument));
 
   return NS_OK;
 }
 
-// static
-int
-nsNodeInfoManager::DropNodeInfoDocument(PLHashEntry *he, int hashIndex, void *arg)
-{
-  static_cast<mozilla::dom::NodeInfo*>(he->value)->mDocument = nullptr;
-  return HT_ENUMERATE_NEXT;
-}
-
 void
 nsNodeInfoManager::DropDocumentReference()
 {
   if (mBindingManager) {
     mBindingManager->DropDocumentReference();
   }
 
   // This is probably not needed anymore.
-  PL_HashTableEnumerateEntries(mNodeInfoHash, DropNodeInfoDocument, nullptr);
+  for (auto iter = mNodeInfoHash.Iter(); !iter.Done(); iter.Next()) {
+    iter.Data()->mDocument = nullptr;
+  }
 
   NS_ASSERTION(!mNonDocumentNodeInfos, "Shouldn't have non-document nodeinfos!");
   mDocument = nullptr;
 }
 
 
 already_AddRefed<mozilla::dom::NodeInfo>
 nsNodeInfoManager::GetNodeInfo(nsAtom *aName, nsAtom *aPrefix,
                                int32_t aNamespaceID, uint16_t aNodeType,
                                nsAtom* aExtraName /* = nullptr */)
 {
   CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
 
   NodeInfo::NodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType,
                                  aExtraName);
 
-  uint32_t index =
-    GetNodeInfoInnerHashValue(&tmpKey) % RECENTLY_USED_NODEINFOS_SIZE;
+  uint32_t index = tmpKey.Hash() % RECENTLY_USED_NODEINFOS_SIZE;
   NodeInfo* ni = mRecentlyUsedNodeInfos[index];
-  if (ni && NodeInfoInnerKeyCompare(&(ni->mInner), &tmpKey)) {
+  if (ni && tmpKey == ni->mInner) {
     RefPtr<NodeInfo> nodeInfo = ni;
     return nodeInfo.forget();
   }
 
-  void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
+  // We don't use LookupForAdd here as that would end up storing the temporary
+  // key instead of using `mInner`.
+  RefPtr<NodeInfo> nodeInfo = mNodeInfoHash.Get(&tmpKey);
+  if (!nodeInfo) {
+    ++mNonDocumentNodeInfos;
+    if (mNonDocumentNodeInfos == 1) {
+      NS_IF_ADDREF(mDocument);
+    }
 
-  if (node) {
-    RefPtr<NodeInfo> nodeInfo = static_cast<NodeInfo*>(node);
-    mRecentlyUsedNodeInfos[index] = nodeInfo;
-    return nodeInfo.forget();
+    nodeInfo = new NodeInfo(aName, aPrefix, aNamespaceID, aNodeType, aExtraName, this);
+    mNodeInfoHash.Put(&nodeInfo->mInner, nodeInfo);
   }
 
-  RefPtr<NodeInfo> newNodeInfo =
-    new NodeInfo(aName, aPrefix, aNamespaceID, aNodeType, aExtraName, this);
-
-  DebugOnly<PLHashEntry*> he =
-    PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
-  MOZ_ASSERT(he, "PL_HashTableAdd() failed");
-
   // Have to do the swap thing, because already_AddRefed<nsNodeInfo>
   // doesn't cast to already_AddRefed<mozilla::dom::NodeInfo>
-  ++mNonDocumentNodeInfos;
-  if (mNonDocumentNodeInfos == 1) {
-    NS_IF_ADDREF(mDocument);
-  }
-
-  mRecentlyUsedNodeInfos[index] = newNodeInfo;
-  return newNodeInfo.forget();
+  mRecentlyUsedNodeInfos[index] = nodeInfo;
+  return nodeInfo.forget();
 }
 
 
 nsresult
 nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsAtom *aPrefix,
                                int32_t aNamespaceID, uint16_t aNodeType,
                                NodeInfo** aNodeInfo)
 {
+  // TODO(erahm): Combine this with the atom version.
 #ifdef DEBUG
   {
     RefPtr<nsAtom> nameAtom = NS_Atomize(aName);
     CheckValidNodeInfo(aNodeType, nameAtom, aNamespaceID, nullptr);
   }
 #endif
 
   NodeInfo::NodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType);
 
-  uint32_t index =
-    GetNodeInfoInnerHashValue(&tmpKey) % RECENTLY_USED_NODEINFOS_SIZE;
+  uint32_t index = tmpKey.Hash() % RECENTLY_USED_NODEINFOS_SIZE;
   NodeInfo* ni = mRecentlyUsedNodeInfos[index];
-  if (ni && NodeInfoInnerKeyCompare(&(ni->mInner), &tmpKey)) {
+  if (ni && ni->mInner == tmpKey) {
     RefPtr<NodeInfo> nodeInfo = ni;
     nodeInfo.forget(aNodeInfo);
     return NS_OK;
   }
 
-  void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
+  RefPtr<NodeInfo> nodeInfo = mNodeInfoHash.Get(&tmpKey);
+  if (!nodeInfo) {
+    ++mNonDocumentNodeInfos;
+    if (mNonDocumentNodeInfos == 1) {
+      NS_IF_ADDREF(mDocument);
+    }
 
-  if (node) {
-    RefPtr<NodeInfo> nodeInfo = static_cast<NodeInfo*>(node);
-    mRecentlyUsedNodeInfos[index] = nodeInfo;
-    nodeInfo.forget(aNodeInfo);
-
-    return NS_OK;
+    RefPtr<nsAtom> nameAtom = NS_Atomize(aName);
+    nodeInfo = new NodeInfo(nameAtom, aPrefix, aNamespaceID, aNodeType, nullptr, this);
+    mNodeInfoHash.Put(&nodeInfo->mInner, nodeInfo);
   }
 
-  RefPtr<nsAtom> nameAtom = NS_Atomize(aName);
-  NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
-
-  RefPtr<NodeInfo> newNodeInfo =
-    new NodeInfo(nameAtom, aPrefix, aNamespaceID, aNodeType, nullptr, this);
-  NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
-
-  PLHashEntry *he;
-  he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
-  NS_ENSURE_TRUE(he, NS_ERROR_FAILURE);
-
-  ++mNonDocumentNodeInfos;
-  if (mNonDocumentNodeInfos == 1) {
-    NS_IF_ADDREF(mDocument);
-  }
-
-  mRecentlyUsedNodeInfos[index] = newNodeInfo;
-  newNodeInfo.forget(aNodeInfo);
+  mRecentlyUsedNodeInfos[index] = nodeInfo;
+  nodeInfo.forget(aNodeInfo);
 
   return NS_OK;
 }
 
 
 nsresult
 nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsAtom *aPrefix,
                                const nsAString& aNamespaceURI,
@@ -444,27 +336,22 @@ nsNodeInfoManager::RemoveNodeInfo(NodeIn
     if (aNodeInfo == mTextNodeInfo) {
       mTextNodeInfo = nullptr;
     }
     else if (aNodeInfo == mCommentNodeInfo) {
       mCommentNodeInfo = nullptr;
     }
   }
 
-  uint32_t index =
-    GetNodeInfoInnerHashValue(&aNodeInfo->mInner) % RECENTLY_USED_NODEINFOS_SIZE;
+  uint32_t index = aNodeInfo->mInner.Hash() % RECENTLY_USED_NODEINFOS_SIZE;
   if (mRecentlyUsedNodeInfos[index] == aNodeInfo) {
     mRecentlyUsedNodeInfos[index] = nullptr;
   }
 
-#ifdef DEBUG
-  bool ret =
-#endif
-  PL_HashTableRemove(mNodeInfoHash, &aNodeInfo->mInner);
-
+  DebugOnly<bool> ret = mNodeInfoHash.Remove(&aNodeInfo->mInner);
   MOZ_ASSERT(ret, "Can't find mozilla::dom::NodeInfo to remove!!!");
 }
 
 bool
 nsNodeInfoManager::InternalSVGEnabled()
 {
   // If the svg.disabled pref. is true, convert all SVG nodes into
   // disabled SVG nodes by swapping the namespace.
--- a/dom/base/nsNodeInfoManager.h
+++ b/dom/base/nsNodeInfoManager.h
@@ -7,37 +7,32 @@
 /*
  * A class for handing out nodeinfos and ensuring sharing of them as needed.
  */
 
 #ifndef nsNodeInfoManager_h___
 #define nsNodeInfoManager_h___
 
 #include "mozilla/Attributes.h"           // for final
+#include "mozilla/dom/NodeInfo.h"
 #include "nsCOMPtr.h"                     // for member
 #include "nsCycleCollectionParticipant.h" // for NS_DECL_CYCLE_*
+#include "nsDataHashtable.h"
 #include "nsStringFwd.h"
-#include "plhash.h"                       // for typedef PLHashNumber
 
 class nsBindingManager;
 class nsAtom;
 class nsIDocument;
 class nsIDOMDocumentType;
 class nsIPrincipal;
 class nsWindowSizes;
 struct PLHashEntry;
 struct PLHashTable;
 template<class T> struct already_AddRefed;
 
-namespace mozilla {
-namespace dom {
-class NodeInfo;
-} // namespace dom
-} // namespace mozilla
-
 #define RECENTLY_USED_NODEINFOS_SIZE 31
 
 class nsNodeInfoManager final
 {
 private:
   ~nsNodeInfoManager();
 
 public:
@@ -150,25 +145,30 @@ protected:
                                         const nsAString& );
 
   /**
    * Sets the principal of the document this nodeinfo manager belongs to.
    */
   void SetDocumentPrincipal(nsIPrincipal *aPrincipal);
 
 private:
-  static int NodeInfoInnerKeyCompare(const void *key1, const void *key2);
-  static PLHashNumber GetNodeInfoInnerHashValue(const void *key);
-  static int DropNodeInfoDocument(PLHashEntry *he, int hashIndex,
-                                     void *arg);
-
   bool InternalSVGEnabled();
   bool InternalMathMLEnabled();
 
-  PLHashTable *mNodeInfoHash;
+  class NodeInfoInnerKey :
+    public nsPtrHashKey<mozilla::dom::NodeInfo::NodeInfoInner>
+  {
+  public:
+    explicit NodeInfoInnerKey(KeyTypePointer aKey) : nsPtrHashKey(aKey) {}
+    ~NodeInfoInnerKey() = default;
+    bool KeyEquals(KeyTypePointer aKey) const { return *mKey == *aKey; }
+    static PLDHashNumber HashKey(KeyTypePointer aKey) { return aKey->Hash(); }
+  };
+
+  nsDataHashtable<NodeInfoInnerKey, mozilla::dom::NodeInfo*> mNodeInfoHash;
   nsIDocument * MOZ_NON_OWNING_REF mDocument; // WEAK
   uint32_t mNonDocumentNodeInfos;
   nsCOMPtr<nsIPrincipal> mPrincipal; // Never null after Init() succeeds.
   nsCOMPtr<nsIPrincipal> mDefaultPrincipal; // Never null after Init() succeeds
   mozilla::dom::NodeInfo * MOZ_NON_OWNING_REF mTextNodeInfo; // WEAK to avoid circular ownership
   mozilla::dom::NodeInfo * MOZ_NON_OWNING_REF mCommentNodeInfo; // WEAK to avoid circular ownership
   mozilla::dom::NodeInfo * MOZ_NON_OWNING_REF mDocumentNodeInfo; // WEAK to avoid circular ownership
   RefPtr<nsBindingManager> mBindingManager;
--- a/dom/base/test/browser_promiseDocumentFlushed.js
+++ b/dom/base/test/browser_promiseDocumentFlushed.js
@@ -26,30 +26,26 @@ const gWindowUtils = window.QueryInterfa
                            .getInterface(Ci.nsIDOMWindowUtils);
 
 /**
  * Asserts that no style or layout flushes are required by the
  * current window.
  */
 function assertNoFlushesRequired() {
   Assert.ok(!gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_STYLE),
-            "No style flushes are required.");
-  Assert.ok(!gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_LAYOUT),
-            "No layout flushes are required.");
+            "No flushes are required.");
 }
 
 /**
  * Asserts that the DOM has been dirtied, and so style and layout flushes
  * are required.
  */
 function assertFlushesRequired() {
-  Assert.ok(gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_STYLE),
-            "Style flush required.");
   Assert.ok(gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_LAYOUT),
-            "Layout flush required.");
+            "Style and layout flushes are required.");
 }
 
 /**
  * Removes style changes from dirtyTheDOM() from the browser window,
  * and resolves once the refresh driver ticks.
  */
 async function cleanTheDOM() {
   gNavToolbox.style.padding = "";
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -241,16 +241,27 @@ Event::GetTarget() const
 
 NS_IMETHODIMP
 Event::GetTarget(nsIDOMEventTarget** aTarget)
 {
   NS_IF_ADDREF(*aTarget = GetTarget());
   return NS_OK;
 }
 
+bool
+Event::IsSrcElementEnabled(JSContext* /* unused */, JSObject* /* unused */)
+{
+  // Not a pref, because that's a pain on workers.
+#ifdef NIGHTLY_BUILD
+  return true;
+#else
+  return false;
+#endif
+}
+
 EventTarget*
 Event::GetCurrentTarget() const
 {
   return mEvent->GetCurrentDOMEventTarget();
 }
 
 void
 Event::ComposedPath(nsTArray<RefPtr<EventTarget>>& aPath)
--- a/dom/events/Event.h
+++ b/dom/events/Event.h
@@ -166,16 +166,17 @@ public:
                                              const nsAString& aType,
                                              const EventInit& aParam,
                                              ErrorResult& aRv);
 
   // Implemented as xpidl method
   // void GetType(nsString& aRetval) {}
 
   EventTarget* GetTarget() const;
+  static bool IsSrcElementEnabled(JSContext* /* unused */, JSObject* /* unused */);
   EventTarget* GetCurrentTarget() const;
 
   void ComposedPath(nsTArray<RefPtr<EventTarget>>& aPath);
 
   uint16_t EventPhase() const;
 
   // xpidl implementation
   // void StopPropagation();
--- a/dom/events/EventDispatcher.cpp
+++ b/dom/events/EventDispatcher.cpp
@@ -675,16 +675,18 @@ EventDispatcher::Dispatch(nsISupports* a
   // sure it is initialized!
   // If aTargets is non-null, the event isn't going to be dispatched.
   NS_ENSURE_TRUE(aEvent->mMessage || !aDOMEvent || aTargets,
                  NS_ERROR_DOM_INVALID_STATE_ERR);
 
   // Events shall not be fired while we are in stable state to prevent anything
   // visible from the scripts.
   MOZ_ASSERT(!nsContentUtils::IsInStableOrMetaStableState());
+  NS_ENSURE_TRUE(!nsContentUtils::IsInStableOrMetaStableState(),
+                 NS_ERROR_DOM_INVALID_STATE_ERR);
 
 #ifdef MOZ_TASK_TRACER
   if (MOZ_UNLIKELY(mozilla::tasktracer::IsStartLogging())) {
     nsAutoCString eventType;
     nsAutoString eventTypeU16;
     if (aDOMEvent) {
       aDOMEvent->GetType(eventTypeU16);
     } else {
--- a/dom/serviceworkers/test/test_self_update_worker.html
+++ b/dom/serviceworkers/test/test_self_update_worker.html
@@ -1,13 +1,26 @@
 <!DOCTYPE HTML>
 <html>
 <!--
   Test that a self updating service worker can't keep running forever when the
   script changes.
+
+  - self_update_worker.sjs is a stateful server-side js script that returns a
+  SW script with a different version every time it's invoked. (version=1..n)
+  - The SW script will trigger an update when it reaches the activating state,
+  which, if not for the update delaying mechanism, would result in an iterative
+  cycle.
+  - We currently delay registration.update() calls originating from SWs not currently
+  controlling any clients. The delay is: 0s, 30s, 900s etc, but for the purpose of
+  this test, the delay is: 0s, infinite etc.
+  - We assert that the SW script never reaches version 3, meaning it will only
+  successfully update once.
+  - We give the worker reasonable time to self update by repeatedly registering
+  and unregistering an empty service worker.
   -->
 <head>
   <title>Test for Bug 1432846</title>
   <script src="/tests/SimpleTest/SimpleTest.js"></script>
   <script src="/tests/SimpleTest/SpawnTask.js"></script>
   <script src="error_reporting_helpers.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
@@ -42,30 +55,32 @@ function activateDummyWorker() {
 }
 
 add_task(async function test_update() {
   navigator.serviceWorker.onmessage = function(event) {
     ok (event.data.version < 3, "Service worker updated too many times." + event.data.version);
   }
 
   await SpecialPowers.pushPrefEnv({"set": [
-    ["dom.serviceWorkers.idle_timeout", 0],
     ["dom.serviceWorkers.update_delay", 30000],
     ["dom.serviceWorkers.idle_extended_timeout", 299999]]});
 
   // clear version counter
   await fetch("self_update_worker.sjs?clearcounter");
 
   var worker;
   let registration = await navigator.serviceWorker.register(
     "self_update_worker.sjs",
     { scope: "./test_self_update_worker.html?random=" + Date.now()})
     .then(function(registration) {
       worker = registration.installing;
-      return waitForState(worker, 'activated', registration);
+      // We can't wait for 'activated' here, since it's possible for
+      // the update process to kill the worker before it activates.
+      // See: https://github.com/w3c/ServiceWorker/issues/1285
+      return waitForState(worker, 'activating', registration);
     });
 
   // We need to wait a reasonable time to give the self updating worker a chance
   // to change to a newer version. Register and activate an empty worker 5 times.
   for (i = 0; i < 5; i++) {
     await activateDummyWorker();
   }
 
--- a/dom/svg/SVGElementFactory.cpp
+++ b/dom/svg/SVGElementFactory.cpp
@@ -5,27 +5,26 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SVGElementFactory.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FromParser.h"
+#include "mozilla/StaticPtr.h"
+#include "nsDataHashtable.h"
+#include "nsHashKeys.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
-// Hash table that maps nsAtom* SVG tags to an offset index
-// within the array sSVGContentCreatorFunctions (offset by TABLE_VALUE_OFFSET)
-static PLHashTable* sTagAtomTable = nullptr;
-
-// We don't want to store 0 in the hash table as a return value of 0 from
-// PL_HashTableLookupConst indicates that the value is not found
-#define TABLE_VALUE_OFFSET 1
+// Hash table that maps nsAtom* SVG tags to a SVGContentCreatorFunction.
+using TagAtomTable = nsDataHashtable<nsPtrHashKey<nsAtom>, SVGContentCreatorFunction>;
+StaticAutoPtr<TagAtomTable> sTagAtomTable;
 
 #define SVG_TAG(_tag, _classname)                                              \
   nsresult NS_NewSVG##_classname##Element(                                     \
     nsIContent** aResult,                                                      \
     already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);                     \
                                                                                \
   nsresult NS_NewSVG##_classname##Element(                                     \
     nsIContent** aResult,                                                      \
@@ -40,89 +39,59 @@ static PLHashTable* sTagAtomTable = null
 #include "SVGTagList.h"
 #undef SVG_TAG
 #undef SVG_FROM_PARSER_TAG
 
 nsresult
 NS_NewSVGElement(Element** aResult,
                  already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
 
-static const SVGContentCreatorFunction sSVGContentCreatorFunctions[] = {
-#define SVG_TAG(_tag, _classname) NS_NewSVG##_classname##Element,
-#define SVG_FROM_PARSER_TAG(_tag, _classname)  NS_NewSVG##_classname##Element,
-#include "SVGTagList.h"
-#undef SVG_TAG
-#undef SVG_FROM_PARSER_TAG
-};
-
 enum SVGTag {
 #define SVG_TAG(_tag, _classname) eSVGTag_##_tag,
 #define SVG_FROM_PARSER_TAG(_tag, _classname) eSVGTag_##_tag,
 #include "SVGTagList.h"
 #undef SVG_TAG
 #undef SVG_FROM_PARSER_TAG
   eSVGTag_Count
 };
 
-// nsAtom* -> id hash
-static PLHashNumber
-SVGTagsHashCodeAtom(const void* key)
-{
-  return NS_PTR_TO_INT32(key) >> 2;
-}
-
 void
 SVGElementFactory::Init()
 {
-  sTagAtomTable = PL_NewHashTable(64, SVGTagsHashCodeAtom,
-                                  PL_CompareValues, PL_CompareValues,
-                                  nullptr, nullptr);
+  sTagAtomTable = new TagAtomTable(64);
 
 #define SVG_TAG(_tag, _classname) \
-  PL_HashTableAdd(sTagAtomTable, nsGkAtoms::_tag,\
-                  NS_INT32_TO_PTR(eSVGTag_##_tag + TABLE_VALUE_OFFSET));
+  sTagAtomTable->Put(nsGkAtoms::_tag, NS_NewSVG##_classname##Element);
 #define SVG_FROM_PARSER_TAG(_tag, _classname) \
-  PL_HashTableAdd(sTagAtomTable, nsGkAtoms::_tag,\
-                  NS_INT32_TO_PTR(eSVGTag_##_tag + TABLE_VALUE_OFFSET));
+  sTagAtomTable->Put(nsGkAtoms::_tag, NS_NewSVG##_classname##Element);
 #include "SVGTagList.h"
 #undef SVG_TAG
 #undef SVG_FROM_PARSER_TAG
 }
 
 void
 SVGElementFactory::Shutdown()
 {
-  if (sTagAtomTable) {
-    PL_HashTableDestroy(sTagAtomTable);
-    sTagAtomTable = nullptr;
-  }
+  sTagAtomTable = nullptr;
 }
 
 nsresult
 NS_NewSVGElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
                  FromParser aFromParser)
 {
   NS_ASSERTION(sTagAtomTable, "no lookup table, needs SVGElementFactory::Init");
 
   RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
   nsAtom* name = ni->NameAtom();
 
   NS_ASSERTION(ni->NamespaceEquals(kNameSpaceID_SVG),
                "Trying to create SVG elements that aren't in the SVG namespace");
 
-  void* tag = PL_HashTableLookupConst(sTagAtomTable, name);
-  if (tag) {
-    int32_t index = NS_PTR_TO_INT32(tag) - TABLE_VALUE_OFFSET;
-    if (index < 0 || index >= eSVGTag_Count) {
-      NS_WARNING("About to index out of array bounds - crashing instead");
-      MOZ_CRASH();
-    }
-
-    SVGContentCreatorFunction cb = sSVGContentCreatorFunctions[index];
-
+  SVGContentCreatorFunction cb = sTagAtomTable->Get(name);
+  if (cb) {
     nsCOMPtr<nsIContent> content;
     nsresult rv = cb(getter_AddRefs(content), ni.forget(), aFromParser);
     *aResult = content.forget().take()->AsElement();
     return rv;
   }
 
   // if we don't know what to create, just create a standard svg element:
   return NS_NewSVGElement(aResult, ni.forget());
--- a/dom/webidl/Event.webidl
+++ b/dom/webidl/Event.webidl
@@ -12,16 +12,18 @@
 
 [Constructor(DOMString type, optional EventInit eventInitDict),
  Exposed=(Window,Worker,System), ProbablyShortLivingWrapper]
 interface Event {
   [Pure]
   readonly attribute DOMString type;
   [Pure]
   readonly attribute EventTarget? target;
+  [Pure, BinaryName="target", Func="Event::IsSrcElementEnabled"]
+  readonly attribute EventTarget? srcElement;
   [Pure]
   readonly attribute EventTarget? currentTarget;
 
   sequence<EventTarget> composedPath();
 
   const unsigned short NONE = 0;
   const unsigned short CAPTURING_PHASE = 1;
   const unsigned short AT_TARGET = 2;
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -1308,17 +1308,17 @@ ContainerLayer::DefaultComputeEffectiveT
 
   // For layers extending 3d context, its ideal transform should be
   // applied on children.
   if (!Extend3DContext()) {
     // Without this projection, non-container children would get a 3D
     // transform while 2D is expected.
     idealTransform.ProjectTo2D();
   }
-  mUseIntermediateSurface = useIntermediateSurface && !GetLocalVisibleRegion().IsEmpty();
+  mUseIntermediateSurface = useIntermediateSurface;
   if (useIntermediateSurface) {
     ComputeEffectiveTransformsForChildren(Matrix4x4::From2D(residual));
   } else {
     ComputeEffectiveTransformsForChildren(idealTransform);
   }
 
   ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
 }
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1606,31 +1606,37 @@ bool
 CompositorBridgeParent::DeallocPLayerTransactionParent(PLayerTransactionParent* actor)
 {
   static_cast<LayerTransactionParent*>(actor)->ReleaseIPDLReference();
   return true;
 }
 
 CompositorBridgeParent* CompositorBridgeParent::GetCompositorBridgeParent(uint64_t id)
 {
+  MOZ_RELEASE_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+
   CompositorMap::iterator it = sCompositorMap->find(id);
   return it != sCompositorMap->end() ? it->second : nullptr;
 }
 
 void CompositorBridgeParent::AddCompositor(CompositorBridgeParent* compositor, uint64_t* outID)
 {
+  MOZ_RELEASE_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+
   static uint64_t sNextID = 1;
 
   ++sNextID;
   (*sCompositorMap)[sNextID] = compositor;
   *outID = sNextID;
 }
 
 CompositorBridgeParent* CompositorBridgeParent::RemoveCompositor(uint64_t id)
 {
+  MOZ_RELEASE_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+
   CompositorMap::iterator it = sCompositorMap->find(id);
   if (it == sCompositorMap->end()) {
     return nullptr;
   }
   CompositorBridgeParent *retval = it->second;
   sCompositorMap->erase(it);
   return retval;
 }
--- a/js/src/jit/BacktrackingAllocator.cpp
+++ b/js/src/jit/BacktrackingAllocator.cpp
@@ -1169,17 +1169,18 @@ BacktrackingAllocator::mergeAndQueueRegi
 
     // Try to merge registers with their reused inputs.
     for (size_t i = 1; i < graph.numVirtualRegisters(); i++) {
         VirtualRegister& reg = vregs[i];
         if (!reg.hasRanges())
             continue;
 
         if (reg.def()->policy() == LDefinition::MUST_REUSE_INPUT) {
-            LUse* use = reg.ins()->getOperand(reg.def()->getReusedInput())->toUse();
+            LUse* use =
+                reg.ins()->toInstruction()->getOperand(reg.def()->getReusedInput())->toUse();
             if (!tryMergeReusedRegister(reg, vreg(use)))
                 return false;
         }
     }
 
     // Try to merge phis with their inputs.
     for (size_t i = 0; i < graph.numBlocks(); i++) {
         LBlock* block = graph.getBlock(i);
--- a/js/src/jit/BaselineFrame.h
+++ b/js/src/jit/BaselineFrame.h
@@ -67,21 +67,16 @@ class BaselineFrame
         //
         // This flag should never be set when we're executing JIT code.
         HAS_OVERRIDE_PC = 1 << 11,
 
         // If set, we're handling an exception for this frame. This is set for
         // debug mode OSR sanity checking when it handles corner cases which
         // only arise during exception handling.
         HANDLING_EXCEPTION = 1 << 12,
-
-        // If set, this frame has been on the stack when
-        // |js::SavedStacks::saveCurrentStack| was called, and so there is a
-        // |js::SavedFrame| object cached for this frame.
-        HAS_CACHED_SAVED_FRAME = 1 << 13
     };
 
   protected: // Silence Clang warning about unused private fields.
     // We need to split the Value into 2 fields of 32 bits, otherwise the C++
     // compiler may add some padding between the fields.
 
     union {
         struct {
@@ -307,23 +302,16 @@ class BaselineFrame
     }
     void setIsHandlingException() {
         flags_ |= HANDLING_EXCEPTION;
     }
     void unsetIsHandlingException() {
         flags_ &= ~HANDLING_EXCEPTION;
     }
 
-    bool hasCachedSavedFrame() const {
-        return flags_ & HAS_CACHED_SAVED_FRAME;
-    }
-    void setHasCachedSavedFrame() {
-        flags_ |= HAS_CACHED_SAVED_FRAME;
-    }
-
     bool overRecursed() const {
         return flags_ & OVER_RECURSED;
     }
 
     void setOverRecursed() {
         flags_ |= OVER_RECURSED;
     }
 
--- a/js/src/jit/LIR.cpp
+++ b/js/src/jit/LIR.cpp
@@ -4,16 +4,17 @@
  * 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/. */
 
 #include "jit/LIR.h"
 
 #include "mozilla/ScopeExit.h"
 
 #include <ctype.h>
+#include <type_traits>
 
 #include "jit/JitSpewer.h"
 #include "jit/MIR.h"
 #include "jit/MIRGenerator.h"
 #include "js/Printf.h"
 
 using namespace js;
 using namespace js::jit;
@@ -475,31 +476,41 @@ LAllocation::dump() const
 }
 
 void
 LDefinition::dump() const
 {
     fprintf(stderr, "%s\n", toString().get());
 }
 
+template <typename T>
+static void
+PrintOperands(GenericPrinter& out, T* node)
+{
+    size_t numOperands = node->numOperands();
+
+    for (size_t i = 0; i < numOperands; i++) {
+        out.printf(" (%s)", node->getOperand(i)->toString().get());
+        if (i != numOperands - 1)
+            out.printf(",");
+    }
+}
+
 void
 LNode::printOperands(GenericPrinter& out)
 {
     if (isMoveGroup()) {
         toMoveGroup()->printOperands(out);
         return;
     }
 
-    size_t numOperands = isPhi() ? toPhi()->numOperands() : toInstruction()->numOperands();
-
-    for (size_t i = 0; i < numOperands; i++) {
-        out.printf(" (%s)", getOperand(i)->toString().get());
-        if (i != numOperands - 1)
-            out.printf(",");
-    }
+    if (isPhi())
+        PrintOperands(out, toPhi());
+    else
+        PrintOperands(out, toInstruction());
 }
 
 void
 LInstruction::assignSnapshot(LSnapshot* snapshot)
 {
     MOZ_ASSERT(!snapshot_);
     snapshot_ = snapshot;
 
@@ -511,33 +522,57 @@ LInstruction::assignSnapshot(LSnapshot* 
                    (void*)snapshot, (void*)this);
         printName(out);
         out.printf(")\n");
     }
 #endif
 }
 
 #ifdef JS_JITSPEW
+static size_t
+NumSuccessorsHelper(const LNode* ins)
+{
+    return 0;
+}
+
+template <size_t Succs, size_t Operands, size_t Temps>
+static size_t
+NumSuccessorsHelper(const LControlInstructionHelper<Succs, Operands, Temps>* ins)
+{
+    return Succs;
+}
+
+static size_t
+NumSuccessors(const LInstruction* ins)
+{
+    switch (ins->op()) {
+      default: MOZ_CRASH("Unexpected LIR op");
+# define LIROP(x) case LNode::LOp_##x: return NumSuccessorsHelper(ins->to##x());
+    LIR_OPCODE_LIST(LIROP)
+# undef LIROP
+    }
+}
+
 static MBasicBlock*
 GetSuccessorHelper(const LNode* ins, size_t i)
 {
     MOZ_CRASH("Unexpected instruction with successors");
 }
 
 template <size_t Succs, size_t Operands, size_t Temps>
 static MBasicBlock*
 GetSuccessorHelper(const LControlInstructionHelper<Succs, Operands, Temps>* ins, size_t i)
 {
     return ins->getSuccessor(i);
 }
 
 static MBasicBlock*
 GetSuccessor(const LInstruction* ins, size_t i)
 {
-    MOZ_ASSERT(i < ins->numSuccessors());
+    MOZ_ASSERT(i < NumSuccessors(ins));
 
     switch (ins->op()) {
       default: MOZ_CRASH("Unexpected LIR op");
 # define LIROP(x) case LNode::LOp_##x: return GetSuccessorHelper(ins->to##x(), i);
     LIR_OPCODE_LIST(LIROP)
 # undef LIROP
     }
 }
@@ -568,31 +603,29 @@ LNode::dump(GenericPrinter& out)
             for (size_t i = 0; i < numTemps; i++) {
                 out.printf("%s", ins->getTemp(i)->toString().get());
                 if (i != numTemps - 1)
                     out.printf(", ");
             }
             out.printf(")");
         }
 
-        size_t numSuccessors = ins->numSuccessors();
+#ifdef JS_JITSPEW
+        size_t numSuccessors = NumSuccessors(ins);
         if (numSuccessors > 0) {
             out.printf(" s=(");
             for (size_t i = 0; i < numSuccessors; i++) {
-#ifdef JS_JITSPEW
                 MBasicBlock* succ = GetSuccessor(ins, i);
                 out.printf("block%u", succ->id());
-#else
-                out.put("block<unknown>");
-#endif
                 if (i != numSuccessors - 1)
                     out.printf(", ");
             }
             out.printf(")");
         }
+#endif
     }
 }
 
 void
 LNode::dump()
 {
     Fprinter out(stderr);
     dump(out);
@@ -684,8 +717,13 @@ LMoveGroup::printOperands(GenericPrinter
 #ifdef DEBUG
         out.printf(", %s", typeName(move.type()));
 #endif
         out.printf("]");
         if (i != numMoves() - 1)
             out.printf(",");
     }
 }
+
+#define LIROP(x) static_assert(!std::is_polymorphic<L##x>::value, \
+                               "LIR instructions should not have virtual methods");
+    LIR_OPCODE_LIST(LIROP)
+#undef LIROP
--- a/js/src/jit/LIR.h
+++ b/js/src/jit/LIR.h
@@ -660,86 +660,91 @@ class LNode
     MDefinition* mir_;
 
   private:
     LBlock* block_;
     uint32_t id_;
 
   protected:
     // Bitfields below are all uint32_t to make sure MSVC packs them correctly.
+    uint32_t op_ : 10;
     uint32_t isCall_ : 1;
     // LPhi::numOperands() may not fit in this bitfield, so we only use this
     // field for LInstruction.
     uint32_t nonPhiNumOperands_ : 6;
+    // For LInstruction, the first operand is stored at offset
+    // sizeof(LInstruction) + nonPhiOperandsOffset_ * sizeof(uintptr_t).
+    uint32_t nonPhiOperandsOffset_ : 5;
     uint32_t numDefs_ : 4;
     uint32_t numTemps_ : 4;
-    uint32_t numSuccessors_ : 2;
 
   public:
-    LNode(uint32_t nonPhiNumOperands, uint32_t numDefs, uint32_t numTemps)
+    enum Opcode {
+#define LIROP(name) LOp_##name,
+        LIR_OPCODE_LIST(LIROP)
+#undef LIROP
+        LOp_Invalid
+    };
+
+    LNode(Opcode op, uint32_t nonPhiNumOperands, uint32_t numDefs, uint32_t numTemps)
       : mir_(nullptr),
         block_(nullptr),
         id_(0),
+        op_(op),
         isCall_(false),
         nonPhiNumOperands_(nonPhiNumOperands),
+        nonPhiOperandsOffset_(0),
         numDefs_(numDefs),
-        numTemps_(numTemps),
-        numSuccessors_(0)
+        numTemps_(numTemps)
     {
+        MOZ_ASSERT(op_ < LOp_Invalid);
+        MOZ_ASSERT(op_ == op, "opcode must fit in bitfield");
         MOZ_ASSERT(nonPhiNumOperands_ == nonPhiNumOperands,
                    "nonPhiNumOperands must fit in bitfield");
         MOZ_ASSERT(numDefs_ == numDefs, "numDefs must fit in bitfield");
         MOZ_ASSERT(numTemps_ == numTemps, "numTemps must fit in bitfield");
     }
 
-    enum Opcode {
-#   define LIROP(name) LOp_##name,
-        LIR_OPCODE_LIST(LIROP)
-#   undef LIROP
-        LOp_Invalid
-    };
-
     const char* opName() {
         switch (op()) {
-#   define LIR_NAME_INS(name)                   \
+#define LIR_NAME_INS(name)                   \
             case LOp_##name: return #name;
             LIR_OPCODE_LIST(LIR_NAME_INS)
-#   undef LIR_NAME_INS
+#undef LIR_NAME_INS
           default:
             return "Invalid";
         }
     }
 
     // Hook for opcodes to add extra high level detail about what code will be
     // emitted for the op.
   private:
     const char* extraName() const {
         return nullptr;
     }
 
   public:
     const char* getExtraName() const;
 
-    virtual Opcode op() const = 0;
+    Opcode op() const {
+        return Opcode(op_);
+    }
 
     bool isInstruction() const {
         return op() != LOp_Phi;
     }
     inline LInstruction* toInstruction();
     inline const LInstruction* toInstruction() const;
 
     // Returns the number of outputs of this instruction. If an output is
     // unallocated, it is an LDefinition, defining a virtual register.
     size_t numDefs() const {
         return numDefs_;
     }
 
-    // Returns information about operands.
-    virtual LAllocation* getOperand(size_t index) = 0;
-
     bool isCall() const {
         return isCall_;
     }
 
     // Does this call preserve the given register?
     // By default, it is assumed that all registers are clobbered by a call.
     inline bool isCallPreserved(AnyRegister reg) const;
 
@@ -772,29 +777,27 @@ class LNode
     void dump(GenericPrinter& out);
     void dump();
     static void printName(GenericPrinter& out, Opcode op);
     void printName(GenericPrinter& out);
     void printOperands(GenericPrinter& out);
 
   public:
     // Opcode testing and casts.
-#   define LIROP(name)                                                      \
+#define LIROP(name)                                                         \
     bool is##name() const {                                                 \
         return op() == LOp_##name;                                          \
     }                                                                       \
     inline L##name* to##name();                                             \
     inline const L##name* to##name() const;
     LIR_OPCODE_LIST(LIROP)
-#   undef LIROP
+#undef LIROP
 
 #define LIR_HEADER(opcode)                                                  \
-    Opcode op() const override {                                            \
-        return LInstruction::LOp_##opcode;                                  \
-    }
+    static constexpr LNode::Opcode classOpcode = LNode::LOp_##opcode;
 };
 
 class LInstruction
   : public LNode
   , public TempObject
   , public InlineListNode<LInstruction>
 {
     // This snapshot could be set after a ResumePoint.  It is used to restart
@@ -805,18 +808,18 @@ class LInstruction
     // to hold either gcthings or Values.
     LSafepoint* safepoint_;
 
     LMoveGroup* inputMoves_;
     LMoveGroup* fixReuseMoves_;
     LMoveGroup* movesAfter_;
 
   protected:
-    LInstruction(uint32_t numOperands, uint32_t numDefs, uint32_t numTemps)
-      : LNode(numOperands, numDefs, numTemps),
+    LInstruction(Opcode opcode, uint32_t numOperands, uint32_t numDefs, uint32_t numTemps)
+      : LNode(opcode, numOperands, numDefs, numTemps),
         snapshot_(nullptr),
         safepoint_(nullptr),
         inputMoves_(nullptr),
         fixReuseMoves_(nullptr),
         movesAfter_(nullptr)
     { }
 
     void setIsCall() {
@@ -824,38 +827,45 @@ class LInstruction
     }
 
   public:
     inline LDefinition* getDef(size_t index);
 
     void setDef(size_t index, const LDefinition& def) {
         *getDef(index) = def;
     }
+
+    LAllocation* getOperand(size_t index) const {
+        MOZ_ASSERT(index < numOperands());
+        MOZ_ASSERT(nonPhiOperandsOffset_ > 0);
+        uintptr_t p = reinterpret_cast<uintptr_t>(this + 1) + nonPhiOperandsOffset_ * sizeof(uintptr_t);
+        return reinterpret_cast<LAllocation*>(p) + index;
+    }
     void setOperand(size_t index, const LAllocation& a) {
         *getOperand(index) = a;
     }
 
+    void initOperandsOffset(size_t offset) {
+        MOZ_ASSERT(nonPhiOperandsOffset_ == 0);
+        MOZ_ASSERT(offset >= sizeof(LInstruction));
+        MOZ_ASSERT(((offset - sizeof(LInstruction)) % sizeof(uintptr_t)) == 0);
+        offset = (offset - sizeof(LInstruction)) / sizeof(uintptr_t);
+        nonPhiOperandsOffset_ = offset;
+        MOZ_ASSERT(nonPhiOperandsOffset_ == offset,
+                   "offset must fit in bitfield");
+    }
+
     // Returns information about temporary registers needed. Each temporary
     // register is an LDefinition with a fixed or virtual register and
     // either GENERAL, FLOAT32, or DOUBLE type.
     size_t numTemps() const {
         return numTemps_;
     }
     inline LDefinition* getTemp(size_t index);
 
-    // Returns the number of successors of this instruction, if it is a control
-    // transfer instruction, or zero otherwise.
-    size_t numSuccessors() const {
-        return numSuccessors_;
-    }
-    void setNumSuccessors(size_t succ) {
-        numSuccessors_ = succ;
-        MOZ_ASSERT(numSuccessors_ == succ, "Number of successors must fit in bitfield");
-    }
-
     LSnapshot* snapshot() const {
         return snapshot_;
     }
     LSafepoint* safepoint() const {
         return safepoint_;
     }
     LMoveGroup* inputMoves() const {
         return inputMoves_;
@@ -943,17 +953,18 @@ class LPhi final : public LNode
 {
     LAllocation* const inputs_;
     LDefinition def_;
 
   public:
     LIR_HEADER(Phi)
 
     LPhi(MPhi* ins, LAllocation* inputs)
-      : LNode(/* nonPhiNumOperands = */ 0,
+      : LNode(classOpcode,
+              /* nonPhiNumOperands = */ 0,
               /* numDefs = */ 1,
               /* numTemps = */ 0),
         inputs_(inputs)
     {
         setMir(ins);
     }
 
     LDefinition* getDef(size_t index) {
@@ -962,17 +973,17 @@ class LPhi final : public LNode
     }
     void setDef(size_t index, const LDefinition& def) {
         MOZ_ASSERT(index == 0);
         def_ = def;
     }
     size_t numOperands() const {
         return mir_->toPhi()->numOperands();
     }
-    LAllocation* getOperand(size_t index) override {
+    LAllocation* getOperand(size_t index) {
         MOZ_ASSERT(index < numOperands());
         return &inputs_[index];
     }
     void setOperand(size_t index, const LAllocation& a) {
         MOZ_ASSERT(index < numOperands());
         inputs_[index] = a;
     }
 
@@ -1080,21 +1091,23 @@ class LBlock
 
 namespace details {
     template <size_t Defs, size_t Temps>
     class LInstructionFixedDefsTempsHelper : public LInstruction
     {
         mozilla::Array<LDefinition, Defs + Temps> defsAndTemps_;
 
       protected:
-        explicit LInstructionFixedDefsTempsHelper(uint32_t numOperands)
-          : LInstruction(numOperands, Defs, Temps)
+        LInstructionFixedDefsTempsHelper(Opcode opcode, uint32_t numOperands)
+          : LInstruction(opcode, numOperands, Defs, Temps)
         {}
 
       public:
+        // Override the methods in LInstruction with more optimized versions
+        // for when we know the exact instruction type.
         LDefinition* getDef(size_t index) {
             MOZ_ASSERT(index < Defs);
             return &defsAndTemps_[index];
         }
         LDefinition* getTemp(size_t index) {
             MOZ_ASSERT(index < Temps);
             return &defsAndTemps_[Defs + index];
         }
@@ -1155,22 +1168,31 @@ LInstruction::getTemp(size_t index)
 }
 
 template <size_t Defs, size_t Operands, size_t Temps>
 class LInstructionHelper : public details::LInstructionFixedDefsTempsHelper<Defs, Temps>
 {
     mozilla::Array<LAllocation, Operands> operands_;
 
   protected:
-    LInstructionHelper()
-      : details::LInstructionFixedDefsTempsHelper<Defs, Temps>(Operands)
-    {}
+    explicit LInstructionHelper(LNode::Opcode opcode)
+      : details::LInstructionFixedDefsTempsHelper<Defs, Temps>(opcode, Operands)
+    {
+        static_assert(Operands == 0 || sizeof(operands_) == Operands * sizeof(LAllocation),
+                      "mozilla::Array should not contain other fields");
+        if (Operands > 0) {
+            using T = LInstructionHelper<Defs, Operands, Temps>;
+            this->initOperandsOffset(offsetof(T, operands_));
+        }
+    }
 
   public:
-    LAllocation* getOperand(size_t index) final {
+    // Override the methods in LInstruction with more optimized versions
+    // for when we know the exact instruction type.
+    LAllocation* getOperand(size_t index) {
         return &operands_[index];
     }
     void setOperand(size_t index, const LAllocation& a) {
         operands_[index] = a;
     }
     void setBoxOperand(size_t index, const LBoxAllocation& alloc) {
 #ifdef JS_NUNBOX32
         operands_[index + TYPE_INDEX] = alloc.type();
@@ -1195,55 +1217,51 @@ class LInstructionHelper : public detail
         return LInt64Allocation(operands_[offset]);
 #endif
     }
 };
 
 template<size_t Defs, size_t Temps>
 class LVariadicInstruction : public details::LInstructionFixedDefsTempsHelper<Defs, Temps>
 {
-    FixedList<LAllocation> operands_;
-
   protected:
-    explicit LVariadicInstruction(size_t numOperands)
-      : details::LInstructionFixedDefsTempsHelper<Defs, Temps>(numOperands)
+    LVariadicInstruction(LNode::Opcode opcode, size_t numOperands)
+      : details::LInstructionFixedDefsTempsHelper<Defs, Temps>(opcode, numOperands)
     {}
 
   public:
-    MOZ_MUST_USE bool init(TempAllocator& alloc) {
-        return operands_.init(alloc, this->nonPhiNumOperands_);
-    }
-    LAllocation* getOperand(size_t index) final {
-        return &operands_[index];
-    }
-    void setOperand(size_t index, const LAllocation& a) {
-        operands_[index] = a;
-    }
     void setBoxOperand(size_t index, const LBoxAllocation& a) {
 #ifdef JS_NUNBOX32
-        operands_[index + TYPE_INDEX] = a.type();
-        operands_[index + PAYLOAD_INDEX] = a.payload();
+        this->setOperand(index + TYPE_INDEX, a.type());
+        this->setOperand(index + PAYLOAD_INDEX, a.payload());
 #else
-        operands_[index] = a.value();
+        this->setOperand(index, a.value());
 #endif
     }
 };
 
 template <size_t Defs, size_t Operands, size_t Temps>
 class LCallInstructionHelper : public LInstructionHelper<Defs, Operands, Temps>
 {
-  public:
-    LCallInstructionHelper() {
+  protected:
+    explicit LCallInstructionHelper(LNode::Opcode opcode)
+      : LInstructionHelper<Defs, Operands, Temps>(opcode)
+    {
         this->setIsCall();
     }
 };
 
 template <size_t Defs, size_t Temps>
 class LBinaryCallInstructionHelper : public LCallInstructionHelper<Defs, 2, Temps>
 {
+  protected:
+    explicit LBinaryCallInstructionHelper(LNode::Opcode opcode)
+      : LCallInstructionHelper<Defs, 2, Temps>(opcode)
+    {}
+
   public:
     const LAllocation* lhs() {
         return this->getOperand(0);
     }
     const LAllocation* rhs() {
         return this->getOperand(1);
     }
 };
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -3318,28 +3318,29 @@ LIRGenerator::visitLoadElementFromState(
     LDefinition temp1 = LDefinition::BogusTemp();
 #ifdef JS_NUNBOX32
     temp1 = temp();
 #endif
     MOZ_ASSERT(ins->array()->isArgumentState(),
                "LIRGenerator::visitLoadElementFromState: Unsupported state object");
     MArgumentState* array = ins->array()->toArgumentState();
 
-    size_t numOperands = 1 + BOX_PIECES * array->numElements();
-    LLoadElementFromStateV* lir = new(alloc()) LLoadElementFromStateV(temp(), temp1, tempDouble(),
-                                                                      numOperands);
-
     //   1                                 -- for the index as a register
     //   BOX_PIECES * array->numElements() -- for using as operand all the
     //                                        elements of the inlined array.
-    if (!lir->init(alloc())) {
+    size_t numOperands = 1 + BOX_PIECES * array->numElements();
+
+    auto* lir = allocateVariadic<LLoadElementFromStateV>(numOperands, temp(), temp1, tempDouble());
+    if (!lir) {
         abort(AbortReason::Alloc, "OOM: LIRGenerator::visitLoadElementFromState");
         return;
     }
+
     lir->setOperand(0, useRegister(ins->index())); // index
+
     for (size_t i = 0, e = array->numElements(); i < e; i++) {
         MDefinition* elem = array->getElement(i);
         if (elem->isConstant() && elem->isEmittedAtUses()) {
             lir->setOperand(1 + BOX_PIECES * i, LAllocation());
 #ifdef JS_NUNBOX32
             lir->setOperand(1 + BOX_PIECES * i + 1, LAllocation());
 #endif
             continue;
@@ -4687,18 +4688,18 @@ LIRGenerator::visitWasmStackArg(MWasmSta
         add(new(alloc()) LWasmStackArg(useRegisterOrConstantAtStart(ins->arg())), ins);
     }
 }
 
 template <typename LClass>
 LInstruction*
 LIRGenerator::lowerWasmCall(MWasmCall* ins, bool needsBoundsCheck)
 {
-    auto* lir = new(alloc()) LClass(ins->numOperands(), needsBoundsCheck);
-    if (!lir->init(alloc())) {
+    auto* lir = allocateVariadic<LClass>(ins->numOperands(), needsBoundsCheck);
+    if (!lir) {
         abort(AbortReason::Alloc, "Couldn't allocate for MWasmCall");
         return nullptr;
     }
 
     for (unsigned i = 0; i < ins->numArgs(); i++)
         lir->setOperand(i, useFixedAtStart(ins->getOperand(i), ins->registerForArg(i)));
 
     if (ins->callee().isTable()) {
--- a/js/src/jit/arm/LIR-arm.h
+++ b/js/src/jit/arm/LIR-arm.h
@@ -13,17 +13,18 @@ namespace jit {
 class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1>
 {
     MIRType type_;
 
   public:
     LIR_HEADER(BoxFloatingPoint);
 
     LBoxFloatingPoint(const LAllocation& in, const LDefinition& temp, MIRType type)
-      : type_(type)
+      : LInstructionHelper(classOpcode),
+        type_(type)
     {
         setOperand(0, in);
         setTemp(0, temp);
     }
 
     MIRType type() const {
         return type_;
     }
@@ -32,16 +33,20 @@ class LBoxFloatingPoint : public LInstru
     }
 };
 
 class LUnbox : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(Unbox);
 
+    LUnbox()
+      : LInstructionHelper(classOpcode)
+    {}
+
     MUnbox* mir() const {
         return mir_->toUnbox();
     }
     const LAllocation* payload() {
         return getOperand(0);
     }
     const LAllocation* type() {
         return getOperand(1);
@@ -56,17 +61,18 @@ class LUnboxFloatingPoint : public LInst
     MIRType type_;
 
   public:
     LIR_HEADER(UnboxFloatingPoint);
 
     static const size_t Input = 0;
 
     LUnboxFloatingPoint(const LBoxAllocation& input, MIRType type)
-      : type_(type)
+      : LInstructionHelper(classOpcode),
+        type_(type)
     {
         setBoxOperand(Input, input);
     }
 
     MUnbox* mir() const {
         return mir_->toUnbox();
     }
 
@@ -79,39 +85,45 @@ class LUnboxFloatingPoint : public LInst
 };
 
 // Convert a 32-bit unsigned integer to a double.
 class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(WasmUint32ToDouble)
 
-    LWasmUint32ToDouble(const LAllocation& input) {
+    explicit LWasmUint32ToDouble(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 // Convert a 32-bit unsigned integer to a float32.
 class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(WasmUint32ToFloat32)
 
-    LWasmUint32ToFloat32(const LAllocation& input) {
+    explicit LWasmUint32ToFloat32(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 class LDivI : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(DivI);
 
     LDivI(const LAllocation& lhs, const LAllocation& rhs,
-          const LDefinition& temp) {
+          const LDefinition& temp)
+      : LBinaryMath(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
 
     MDiv* mir() const {
         return mir_->toDiv();
     }
@@ -121,16 +133,17 @@ class LDivOrModI64 : public LCallInstruc
 {
   public:
     LIR_HEADER(DivOrModI64)
 
     static const size_t Lhs = 0;
     static const size_t Rhs = INT64_PIECES;
 
     LDivOrModI64(const LInt64Allocation& lhs, const LInt64Allocation& rhs)
+      : LCallInstructionHelper(classOpcode)
     {
         setInt64Operand(Lhs, lhs);
         setInt64Operand(Rhs, rhs);
     }
 
     MBinaryArithInstruction* mir() const {
         MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
         return static_cast<MBinaryArithInstruction*>(mir_);
@@ -157,16 +170,17 @@ class LUDivOrModI64 : public LCallInstru
 {
   public:
     LIR_HEADER(UDivOrModI64)
 
     static const size_t Lhs = 0;
     static const size_t Rhs = INT64_PIECES;
 
     LUDivOrModI64(const LInt64Allocation& lhs, const LInt64Allocation& rhs)
+      : LCallInstructionHelper(classOpcode)
     {
         setInt64Operand(Lhs, lhs);
         setInt64Operand(Rhs, rhs);
     }
 
     MBinaryArithInstruction* mir() const {
         MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
         return static_cast<MBinaryArithInstruction*>(mir_);
@@ -191,17 +205,19 @@ class LUDivOrModI64 : public LCallInstru
 
 // LSoftDivI is a software divide for ARM cores that don't support a hardware
 // divide instruction, implemented as a C++ native call.
 class LSoftDivI : public LBinaryCallInstructionHelper<1, 0>
 {
   public:
     LIR_HEADER(SoftDivI);
 
-    LSoftDivI(const LAllocation& lhs, const LAllocation& rhs) {
+    LSoftDivI(const LAllocation& lhs, const LAllocation& rhs)
+      : LBinaryCallInstructionHelper(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
     }
 
     MDiv* mir() const {
         return mir_->toDiv();
     }
 };
@@ -209,17 +225,18 @@ class LSoftDivI : public LBinaryCallInst
 class LDivPowTwoI : public LInstructionHelper<1, 1, 0>
 {
     const int32_t shift_;
 
   public:
     LIR_HEADER(DivPowTwoI)
 
     LDivPowTwoI(const LAllocation& lhs, int32_t shift)
-      : shift_(shift)
+      : LInstructionHelper(classOpcode),
+        shift_(shift)
     {
         setOperand(0, lhs);
     }
 
     const LAllocation* numerator() {
         return getOperand(0);
     }
 
@@ -234,16 +251,17 @@ class LDivPowTwoI : public LInstructionH
 
 class LModI : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(ModI);
 
     LModI(const LAllocation& lhs, const LAllocation& rhs,
           const LDefinition& callTemp)
+      : LBinaryMath(classOpcode)
     {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, callTemp);
     }
 
     const LDefinition* callTemp() {
         return getTemp(0);
@@ -256,16 +274,17 @@ class LModI : public LBinaryMath<1>
 
 class LSoftModI : public LBinaryCallInstructionHelper<1, 1>
 {
   public:
     LIR_HEADER(SoftModI);
 
     LSoftModI(const LAllocation& lhs, const LAllocation& rhs,
               const LDefinition& temp)
+      : LBinaryCallInstructionHelper(classOpcode)
     {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
 
     const LDefinition* callTemp() {
         return getTemp(0);
@@ -283,17 +302,18 @@ class LModPowTwoI : public LInstructionH
   public:
     LIR_HEADER(ModPowTwoI);
     int32_t shift()
     {
         return shift_;
     }
 
     LModPowTwoI(const LAllocation& lhs, int32_t shift)
-      : shift_(shift)
+      : LInstructionHelper(classOpcode),
+        shift_(shift)
     {
         setOperand(0, lhs);
     }
 
     MMod* mir() const {
         return mir_->toMod();
     }
 };
@@ -302,17 +322,18 @@ class LModMaskI : public LInstructionHel
 {
     const int32_t shift_;
 
   public:
     LIR_HEADER(ModMaskI);
 
     LModMaskI(const LAllocation& lhs, const LDefinition& temp1, const LDefinition& temp2,
               int32_t shift)
-      : shift_(shift)
+      : LInstructionHelper(classOpcode),
+        shift_(shift)
     {
         setOperand(0, lhs);
         setTemp(0, temp1);
         setTemp(1, temp2);
     }
 
     int32_t shift() const {
         return shift_;
@@ -324,17 +345,19 @@ class LModMaskI : public LInstructionHel
 };
 
 // Takes a tableswitch with an integer to decide.
 class LTableSwitch : public LInstructionHelper<0, 1, 1>
 {
   public:
     LIR_HEADER(TableSwitch);
 
-    LTableSwitch(const LAllocation& in, const LDefinition& inputCopy, MTableSwitch* ins) {
+    LTableSwitch(const LAllocation& in, const LDefinition& inputCopy, MTableSwitch* ins)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
         setTemp(0, inputCopy);
         setMir(ins);
     }
 
     MTableSwitch* mir() const {
         return mir_->toTableSwitch();
     }
@@ -354,16 +377,17 @@ class LTableSwitch : public LInstruction
 // Takes a tableswitch with an integer to decide.
 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2>
 {
   public:
     LIR_HEADER(TableSwitchV);
 
     LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
                   const LDefinition& floatCopy, MTableSwitch* ins)
+      : LInstructionHelper(classOpcode)
     {
         setBoxOperand(InputValue, input);
         setTemp(0, inputCopy);
         setTemp(1, floatCopy);
         setMir(ins);
     }
 
     MTableSwitch* mir() const {
@@ -383,92 +407,113 @@ class LTableSwitchV : public LInstructio
     }
 };
 
 class LMulI : public LBinaryMath<0>
 {
   public:
     LIR_HEADER(MulI);
 
+    LMulI()
+      : LBinaryMath(classOpcode)
+    {}
+
     MMul* mir() {
         return mir_->toMul();
     }
 };
 
 class LUDiv : public LBinaryMath<0>
 {
   public:
     LIR_HEADER(UDiv);
 
+    LUDiv()
+      : LBinaryMath(classOpcode)
+    {}
+
     MDiv* mir() {
         return mir_->toDiv();
     }
 };
 
 class LUMod : public LBinaryMath<0>
 {
   public:
     LIR_HEADER(UMod);
 
+    LUMod()
+      : LBinaryMath(classOpcode)
+    {}
+
     MMod* mir() {
         return mir_->toMod();
     }
 };
 
 class LSoftUDivOrMod : public LBinaryCallInstructionHelper<1, 0>
 {
   public:
     LIR_HEADER(SoftUDivOrMod);
 
-    LSoftUDivOrMod(const LAllocation& lhs, const LAllocation& rhs) {
+    LSoftUDivOrMod(const LAllocation& lhs, const LAllocation& rhs)
+      : LBinaryCallInstructionHelper(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
     }
 
     MInstruction* mir() {
         return mir_->toInstruction();
     }
 };
 
 class LWasmTruncateToInt64 : public LCallInstructionHelper<INT64_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(WasmTruncateToInt64);
 
-    LWasmTruncateToInt64(const LAllocation& in) {
+    explicit LWasmTruncateToInt64(const LAllocation& in)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
     }
 
     MWasmTruncateToInt64* mir() const {
         return mir_->toWasmTruncateToInt64();
     }
 };
 
 class LInt64ToFloatingPointCall: public LCallInstructionHelper<1, INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(Int64ToFloatingPointCall);
 
+    LInt64ToFloatingPointCall()
+      : LCallInstructionHelper(classOpcode)
+    {}
+
     MInt64ToFloatingPoint* mir() const {
         return mir_->toInt64ToFloatingPoint();
     }
 };
 
 namespace details {
 
 // Base class for the int64 and non-int64 variants.
 template<size_t NumDefs>
 class LWasmUnalignedLoadBase : public details::LWasmLoadBase<NumDefs, 4>
 {
   public:
     typedef LWasmLoadBase<NumDefs, 4> Base;
-    explicit LWasmUnalignedLoadBase(const LAllocation& ptr, const LDefinition& ptrCopy,
+    explicit LWasmUnalignedLoadBase(LNode::Opcode opcode,
+                                    const LAllocation& ptr, const LDefinition& ptrCopy,
                                     const LDefinition& temp1, const LDefinition& temp2,
                                     const LDefinition& temp3)
-      : Base(ptr, LAllocation())
+      : Base(opcode, ptr, LAllocation())
     {
         Base::setTemp(0, ptrCopy);
         Base::setTemp(1, temp1);
         Base::setTemp(2, temp2);
         Base::setTemp(3, temp3);
     }
 
     const LDefinition* ptrCopy() {
@@ -479,45 +524,46 @@ class LWasmUnalignedLoadBase : public de
 } // namespace details
 
 class LWasmUnalignedLoad : public details::LWasmUnalignedLoadBase<1>
 {
   public:
     explicit LWasmUnalignedLoad(const LAllocation& ptr, const LDefinition& ptrCopy,
                                 const LDefinition& temp1, const LDefinition& temp2,
                                 const LDefinition& temp3)
-      : LWasmUnalignedLoadBase(ptr, ptrCopy, temp1, temp2, temp3)
+      : LWasmUnalignedLoadBase(classOpcode, ptr, ptrCopy, temp1, temp2, temp3)
     {}
     LIR_HEADER(WasmUnalignedLoad);
 };
 
 class LWasmUnalignedLoadI64 : public details::LWasmUnalignedLoadBase<INT64_PIECES>
 {
   public:
     explicit LWasmUnalignedLoadI64(const LAllocation& ptr, const LDefinition& ptrCopy,
                                    const LDefinition& temp1, const LDefinition& temp2,
                                    const LDefinition& temp3)
-      : LWasmUnalignedLoadBase(ptr, ptrCopy, temp1, temp2, temp3)
+      : LWasmUnalignedLoadBase(classOpcode, ptr, ptrCopy, temp1, temp2, temp3)
     {}
     LIR_HEADER(WasmUnalignedLoadI64);
 };
 
 namespace details {
 
 // Base class for the int64 and non-int64 variants.
 template<size_t NumOps>
 class LWasmUnalignedStoreBase : public LInstructionHelper<0, NumOps, 2>
 {
   public:
     typedef LInstructionHelper<0, NumOps, 2> Base;
 
     static const uint32_t ValueIndex = 1;
 
-    LWasmUnalignedStoreBase(const LAllocation& ptr, const LDefinition& ptrCopy,
-                            const LDefinition& valueHelper)
+    LWasmUnalignedStoreBase(LNode::Opcode opcode, const LAllocation& ptr,
+                            const LDefinition& ptrCopy, const LDefinition& valueHelper)
+      : Base(opcode)
     {
         Base::setOperand(0, ptr);
         Base::setTemp(0, ptrCopy);
         Base::setTemp(1, valueHelper);
     }
     MWasmStore* mir() const {
         return Base::mir_->toWasmStore();
     }
@@ -532,40 +578,42 @@ class LWasmUnalignedStoreBase : public L
 } // namespace details
 
 class LWasmUnalignedStore : public details::LWasmUnalignedStoreBase<2>
 {
   public:
     LIR_HEADER(WasmUnalignedStore);
     LWasmUnalignedStore(const LAllocation& ptr, const LAllocation& value,
                         const LDefinition& ptrCopy, const LDefinition& valueHelper)
-      : LWasmUnalignedStoreBase(ptr, ptrCopy, valueHelper)
+      : LWasmUnalignedStoreBase(classOpcode, ptr, ptrCopy, valueHelper)
     {
         setOperand(1, value);
     }
 };
 
 class LWasmUnalignedStoreI64 : public details::LWasmUnalignedStoreBase<1 + INT64_PIECES>
 {
   public:
     LIR_HEADER(WasmUnalignedStoreI64);
     LWasmUnalignedStoreI64(const LAllocation& ptr, const LInt64Allocation& value,
                            const LDefinition& ptrCopy, const LDefinition& valueHelper)
-      : LWasmUnalignedStoreBase(ptr, ptrCopy, valueHelper)
+      : LWasmUnalignedStoreBase(classOpcode, ptr, ptrCopy, valueHelper)
     {
         setInt64Operand(1, value);
     }
 };
 
 class LWasmAtomicLoadI64 : public LInstructionHelper<INT64_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(WasmAtomicLoadI64);
 
-    LWasmAtomicLoadI64(const LAllocation& ptr) {
+    explicit LWasmAtomicLoadI64(const LAllocation& ptr)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, ptr);
     }
 
     MWasmLoad* mir() const {
         return mir_->toWasmLoad();
     }
     const LAllocation* ptr() {
         return getOperand(0);
@@ -574,16 +622,17 @@ class LWasmAtomicLoadI64 : public LInstr
 
 class LWasmAtomicStoreI64 : public LInstructionHelper<0, 1 + INT64_PIECES, 2>
 {
   public:
     LIR_HEADER(WasmAtomicStoreI64);
 
     LWasmAtomicStoreI64(const LAllocation& ptr, const LInt64Allocation& value,
                         const LDefinition& tmpLow, const LDefinition& tmpHigh)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setInt64Operand(1, value);
         setTemp(0, tmpLow);
         setTemp(1, tmpHigh);
     }
 
     MWasmStore* mir() const {
@@ -605,16 +654,17 @@ class LWasmAtomicStoreI64 : public LInst
 
 class LWasmCompareExchangeI64 : public LInstructionHelper<INT64_PIECES, 1 + 2*INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(WasmCompareExchangeI64);
 
     LWasmCompareExchangeI64(const LAllocation& ptr, const LInt64Allocation& expected,
                             const LInt64Allocation& replacement)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setInt64Operand(1, expected);
         setInt64Operand(1 + INT64_PIECES, replacement);
     }
 
     MWasmCompareExchangeHeap* mir() const {
         return mir_->toWasmCompareExchangeHeap();
@@ -636,17 +686,18 @@ class LWasmAtomicBinopI64 : public LInst
     AtomicOp op_;
 
   public:
     LIR_HEADER(WasmAtomicBinopI64);
 
     LWasmAtomicBinopI64(const LAllocation& ptr, const LInt64Allocation& value,
                         const LDefinition& tmpLow, const LDefinition& tmpHigh,
                         const wasm::MemoryAccessDesc& access, AtomicOp op)
-      : access_(access),
+      : LInstructionHelper(classOpcode),
+        access_(access),
         op_(op)
     {
         setOperand(0, ptr);
         setInt64Operand(1, value);
         setTemp(0, tmpLow);
         setTemp(1, tmpHigh);
     }
 
@@ -674,17 +725,18 @@ class LWasmAtomicExchangeI64 : public LI
 {
     const wasm::MemoryAccessDesc& access_;
 
   public:
     LIR_HEADER(WasmAtomicExchangeI64);
 
     LWasmAtomicExchangeI64(const LAllocation& ptr, const LInt64Allocation& value,
                            const wasm::MemoryAccessDesc& access)
-      : access_(access)
+      : LInstructionHelper(classOpcode),
+        access_(access)
     {
         setOperand(0, ptr);
         setInt64Operand(1, value);
     }
 
     const LAllocation* ptr() {
         return getOperand(0);
     }
--- a/js/src/jit/arm64/LIR-arm64.h
+++ b/js/src/jit/arm64/LIR-arm64.h
@@ -8,50 +8,52 @@
 #define jit_arm64_LIR_arm64_h
 
 namespace js {
 namespace jit {
 
 class LUnboxBase : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LUnboxBase(const LAllocation& input) {
+    LUnboxBase(LNode::Opcode opcode, const LAllocation& input)
+      : LInstructionHelper(opcode)
+    {
         setOperand(0, input);
     }
 
     static const size_t Input = 0;
 
     MUnbox* mir() const {
         return mir_->toUnbox();
     }
 };
 
 class LUnbox : public LUnboxBase
 {
   public:
     LIR_HEADER(Unbox);
 
-    LUnbox(const LAllocation& input)
-      : LUnboxBase(input)
+    explicit LUnbox(const LAllocation& input)
+      : LUnboxBase(classOpcode, input)
     { }
 
     const char* extraName() const {
         return StringFromMIRType(mir()->type());
     }
 };
 
 class LUnboxFloatingPoint : public LUnboxBase
 {
     MIRType type_;
 
   public:
     LIR_HEADER(UnboxFloatingPoint);
 
     LUnboxFloatingPoint(const LAllocation& input, MIRType type)
-      : LUnboxBase(input),
+      : LUnboxBase(classOpcode, input),
         type_(type)
     { }
 
     MIRType type() const {
         return type_;
     }
     const char* extraName() const {
         return StringFromMIRType(type_);
@@ -59,39 +61,44 @@ class LUnboxFloatingPoint : public LUnbo
 };
 
 // Convert a 32-bit unsigned integer to a double.
 class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(WasmUint32ToDouble)
 
-    LWasmUint32ToDouble(const LAllocation& input) {
+    explicit LWasmUint32ToDouble(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 // Convert a 32-bit unsigned integer to a float32.
 class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(WasmUint32ToFloat32)
 
-    LWasmUint32ToFloat32(const LAllocation& input) {
+    explicit LWasmUint32ToFloat32(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 class LDivI : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(DivI);
 
     LDivI(const LAllocation& lhs, const LAllocation& rhs,
           const LDefinition& temp)
+      : LBinaryMath(classOpcode)
     {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
 
     MDiv* mir() const {
         return mir_->toDiv();
@@ -111,17 +118,19 @@ class LDivI : public LBinaryMath<1>
 // register is not marked as trashed because we never allocate to the link
 // register.  The FP registers are not trashed.
 class LSoftDivI : public LBinaryMath<3>
 {
   public:
     LIR_HEADER(SoftDivI);
 
     LSoftDivI(const LAllocation& lhs, const LAllocation& rhs,
-              const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) {
+              const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3)
+      : LBinaryMath(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp1);
         setTemp(1, temp2);
         setTemp(2, temp3);
     }
 
     MDiv* mir() const {
@@ -132,17 +141,18 @@ class LSoftDivI : public LBinaryMath<3>
 class LDivPowTwoI : public LInstructionHelper<1, 1, 0>
 {
     const int32_t shift_;
 
   public:
     LIR_HEADER(DivPowTwoI)
 
     LDivPowTwoI(const LAllocation& lhs, int32_t shift)
-      : shift_(shift)
+      : LInstructionHelper(classOpcode),
+        shift_(shift)
     {
         setOperand(0, lhs);
     }
 
     const LAllocation* numerator() {
         return getOperand(0);
     }
 
@@ -157,16 +167,17 @@ class LDivPowTwoI : public LInstructionH
 
 class LModI : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(ModI);
 
     LModI(const LAllocation& lhs, const LAllocation& rhs,
           const LDefinition& callTemp)
+      : LBinaryMath(classOpcode)
     {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, callTemp);
     }
 
     const LDefinition* callTemp() {
         return getTemp(0);
@@ -180,16 +191,17 @@ class LModI : public LBinaryMath<1>
 class LSoftModI : public LBinaryMath<4>
 {
   public:
     LIR_HEADER(SoftModI);
 
     LSoftModI(const LAllocation& lhs, const LAllocation& rhs,
               const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3,
               const LDefinition& callTemp)
+      : LBinaryMath(classOpcode)
     {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp1);
         setTemp(1, temp2);
         setTemp(2, temp3);
         setTemp(3, callTemp);
     }
@@ -210,17 +222,18 @@ class LModPowTwoI : public LInstructionH
   public:
     LIR_HEADER(ModPowTwoI);
     int32_t shift()
     {
         return shift_;
     }
 
     LModPowTwoI(const LAllocation& lhs, int32_t shift)
-      : shift_(shift)
+      : LInstructionHelper(classOpcode),
+        shift_(shift)
     {
         setOperand(0, lhs);
     }
 
     MMod* mir() const {
         return mir_->toMod();
     }
 };
@@ -228,17 +241,18 @@ class LModPowTwoI : public LInstructionH
 class LModMaskI : public LInstructionHelper<1, 1, 1>
 {
     const int32_t shift_;
 
   public:
     LIR_HEADER(ModMaskI);
 
     LModMaskI(const LAllocation& lhs, const LDefinition& temp1, int32_t shift)
-      : shift_(shift)
+      : LInstructionHelper(classOpcode),
+        shift_(shift)
     {
         setOperand(0, lhs);
         setTemp(0, temp1);
     }
 
     int32_t shift() const {
         return shift_;
     }
@@ -249,17 +263,19 @@ class LModMaskI : public LInstructionHel
 };
 
 // Takes a tableswitch with an integer to decide
 class LTableSwitch : public LInstructionHelper<0, 1, 1>
 {
   public:
     LIR_HEADER(TableSwitch);
 
-    LTableSwitch(const LAllocation& in, const LDefinition& inputCopy, MTableSwitch* ins) {
+    LTableSwitch(const LAllocation& in, const LDefinition& inputCopy, MTableSwitch* ins)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
         setTemp(0, inputCopy);
         setMir(ins);
     }
 
     MTableSwitch* mir() const {
         return mir_->toTableSwitch();
     }
@@ -279,16 +295,17 @@ class LTableSwitch : public LInstruction
 // Takes a tableswitch with an integer to decide
 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2>
 {
   public:
     LIR_HEADER(TableSwitchV);
 
     LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
                   const LDefinition& floatCopy, MTableSwitch* ins)
+      : LInstructionHelper(classOpcode)
     {
         setBoxOperand(InputValue, input);
         setTemp(0, inputCopy);
         setTemp(1, floatCopy);
         setMir(ins);
     }
 
     MTableSwitch* mir() const {
@@ -341,17 +358,19 @@ class LUMod : public LBinaryMath<0>
 // This class performs a simple x86 'div', yielding either a quotient or remainder depending on
 // whether this instruction is defined to output eax (quotient) or edx (remainder).
 class LSoftUDivOrMod : public LBinaryMath<3>
 {
   public:
     LIR_HEADER(SoftUDivOrMod);
 
     LSoftUDivOrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp1,
-                   const LDefinition& temp2, const LDefinition& temp3) {
+                   const LDefinition& temp2, const LDefinition& temp3)
+      : LBinaryMath(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp1);
         setTemp(1, temp2);
         setTemp(2, temp3);
     }
 };
 
--- a/js/src/jit/none/LIR-none.h
+++ b/js/src/jit/none/LIR-none.h
@@ -41,68 +41,83 @@ class LTableSwitchV : public LInstructio
     const LDefinition* tempPointer() { MOZ_CRASH(); }
 
     static const size_t InputValue = 0;
 };
 
 class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LWasmUint32ToFloat32(const LAllocation&) { MOZ_CRASH(); }
+    explicit LWasmUint32ToFloat32(const LAllocation&)
+      : LInstructionHelper(LOp_Invalid)
+    {
+        MOZ_CRASH();
+    }
 };
 
 class LUnbox : public LInstructionHelper<1, 2, 0>
 {
   public:
 
     MUnbox* mir() const { MOZ_CRASH(); }
     const LAllocation* payload() { MOZ_CRASH(); }
     const LAllocation* type() { MOZ_CRASH(); }
     const char* extraName() const { MOZ_CRASH(); }
 };
 class LDivI : public LBinaryMath<1>
 {
   public:
     LDivI(const LAllocation& , const LAllocation& ,
-          const LDefinition& ) {
+          const LDefinition& )
+      : LBinaryMath(LOp_Invalid)
+    {
         MOZ_CRASH();
     }
     MDiv* mir() const { MOZ_CRASH(); }
 };
 class LDivPowTwoI : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LDivPowTwoI(const LAllocation& , int32_t ) { MOZ_CRASH(); }
+    LDivPowTwoI(const LAllocation&, int32_t) : LInstructionHelper(LOp_Invalid) { MOZ_CRASH(); }
     const LAllocation* numerator() { MOZ_CRASH(); }
     int32_t shift() { MOZ_CRASH(); }
     MDiv* mir() const { MOZ_CRASH(); }
 };
 class LModI : public LBinaryMath<1>
 {
   public:
     LModI(const LAllocation&, const LAllocation&,
           const LDefinition&)
+      : LBinaryMath(LOp_Invalid)
     {
         MOZ_CRASH();
     }
 
     const LDefinition* callTemp() { MOZ_CRASH(); }
     MMod* mir() const { MOZ_CRASH(); }
 };
 class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0>
 {
   public:
-    LWasmUint32ToDouble(const LAllocation&) { MOZ_CRASH(); }
+    explicit LWasmUint32ToDouble(const LAllocation&)
+      : LInstructionHelper(LOp_Invalid)
+    {
+        MOZ_CRASH();
+    }
 };
 class LModPowTwoI : public LInstructionHelper<1, 1, 0>
 {
 
   public:
     int32_t shift() { MOZ_CRASH(); }
-    LModPowTwoI(const LAllocation& lhs, int32_t shift) { MOZ_CRASH(); }
+    LModPowTwoI(const LAllocation& lhs, int32_t shift)
+      : LInstructionHelper(LOp_Invalid)
+    {
+        MOZ_CRASH();
+    }
     MMod* mir() const { MOZ_CRASH(); }
 };
 
 class LMulI : public LInstruction {};
 
 } // namespace jit
 } // namespace js
 
--- a/js/src/jit/shared/CodeGenerator-shared.h
+++ b/js/src/jit/shared/CodeGenerator-shared.h
@@ -367,18 +367,19 @@ class CodeGeneratorShared : public LElem
     void emitPreBarrier(Register base, const LAllocation* index, int32_t offsetAdjustment);
     void emitPreBarrier(Address address);
 
     // We don't emit code for trivial blocks, so if we want to branch to the
     // given block, and it's trivial, return the ultimate block we should
     // actually branch directly to.
     MBasicBlock* skipTrivialBlocks(MBasicBlock* block) {
         while (block->lir()->isTrivial()) {
-            MOZ_ASSERT(block->lir()->rbegin()->numSuccessors() == 1);
-            block = block->lir()->rbegin()->toGoto()->getSuccessor(0);
+            LGoto* ins = block->lir()->rbegin()->toGoto();
+            MOZ_ASSERT(ins->numSuccessors() == 1);
+            block = ins->getSuccessor(0);
         }
         return block;
     }
 
     // Test whether the given block can be reached via fallthrough from the
     // current block.
     inline bool isNextBlock(LBlock* block) {
         uint32_t target = skipTrivialBlocks(block->mir())->id();
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -20,32 +20,38 @@ namespace jit {
 class LBox : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
     MIRType type_;
 
   public:
     LIR_HEADER(Box);
 
     LBox(const LAllocation& payload, MIRType type)
-      : type_(type)
+      : LInstructionHelper(classOpcode),
+        type_(type)
     {
         setOperand(0, payload);
     }
 
     MIRType type() const {
         return type_;
     }
     const char* extraName() const {
         return StringFromMIRType(type_);
     }
 };
 
 template <size_t Temps, size_t ExtraUses = 0>
 class LBinaryMath : public LInstructionHelper<1, 2 + ExtraUses, Temps>
 {
+  protected:
+    explicit LBinaryMath(LNode::Opcode opcode)
+      : LInstructionHelper<1, 2 + ExtraUses, Temps>(opcode)
+    {}
+
   public:
     const LAllocation* lhs() {
         return this->getOperand(0);
     }
     const LAllocation* rhs() {
         return this->getOperand(1);
     }
 };
@@ -57,17 +63,18 @@ class LBinaryMath : public LInstructionH
 // corresponding LSafepoint to inform it of the LOsiPoint's masm offset when it
 // gets CG'd.
 class LOsiPoint : public LInstructionHelper<0, 0, 0>
 {
     LSafepoint* safepoint_;
 
   public:
     LOsiPoint(LSafepoint* safepoint, LSnapshot* snapshot)
-      : safepoint_(safepoint)
+      : LInstructionHelper(classOpcode),
+        safepoint_(safepoint)
     {
         MOZ_ASSERT(safepoint && snapshot);
         assignSnapshot(snapshot);
     }
 
     LSafepoint* associatedSafepoint() {
         return safepoint_;
     }
@@ -104,17 +111,18 @@ class LMoveGroup : public LInstructionHe
     js::Vector<LMove, 2, JitAllocPolicy> moves_;
 
 #ifdef JS_CODEGEN_X86
     // Optional general register available for use when executing moves.
     LAllocation scratchRegister_;
 #endif
 
     explicit LMoveGroup(TempAllocator& alloc)
-      : moves_(alloc)
+      : LInstructionHelper(classOpcode),
+        moves_(alloc)
     { }
 
   public:
     LIR_HEADER(MoveGroup)
 
     static LMoveGroup* New(TempAllocator& alloc) {
         return new(alloc) LMoveGroup(alloc);
     }
@@ -156,16 +164,17 @@ class LMoveGroup : public LInstructionHe
 
 // Constructs a SIMD object (value type) based on the MIRType of its input.
 class LSimdBox : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(SimdBox)
 
     explicit LSimdBox(const LAllocation& simd, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, simd);
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
@@ -176,16 +185,17 @@ class LSimdBox : public LInstructionHelp
 };
 
 class LSimdUnbox : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(SimdUnbox)
 
     LSimdUnbox(const LAllocation& obj, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, obj);
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
@@ -196,74 +206,80 @@ class LSimdUnbox : public LInstructionHe
 };
 
 // Constructs a SIMD value with 16 equal components (int8x16).
 class LSimdSplatX16 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(SimdSplatX16)
     explicit LSimdSplatX16(const LAllocation& v)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, v);
     }
 
     MSimdSplat* mir() const {
         return mir_->toSimdSplat();
     }
 };
 
 // Constructs a SIMD value with 8 equal components (int16x8).
 class LSimdSplatX8 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(SimdSplatX8)
     explicit LSimdSplatX8(const LAllocation& v)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, v);
     }
 
     MSimdSplat* mir() const {
         return mir_->toSimdSplat();
     }
 };
 
 // Constructs a SIMD value with 4 equal components (e.g. int32x4, float32x4).
 class LSimdSplatX4 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(SimdSplatX4)
     explicit LSimdSplatX4(const LAllocation& v)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, v);
     }
 
     MSimdSplat* mir() const {
         return mir_->toSimdSplat();
     }
 };
 
 // Reinterpret the bits of a SIMD value with a different type.
 class LSimdReinterpretCast : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(SimdReinterpretCast)
     explicit LSimdReinterpretCast(const LAllocation& v)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, v);
     }
 
     MSimdReinterpretCast* mir() const {
         return mir_->toSimdReinterpretCast();
     }
 };
 
 class LSimdExtractElementBase : public LInstructionHelper<1, 1, 0>
 {
   protected:
-    explicit LSimdExtractElementBase(const LAllocation& base) {
+    LSimdExtractElementBase(Opcode opcode, const LAllocation& base)
+      : LInstructionHelper(opcode)
+    {
         setOperand(0, base);
     }
 
   public:
     const LAllocation* getBase() {
         return getOperand(0);
     }
     MSimdExtractElement* mir() const {
@@ -272,62 +288,65 @@ class LSimdExtractElementBase : public L
 };
 
 // Extracts an element from a given SIMD bool32x4 lane.
 class LSimdExtractElementB : public LSimdExtractElementBase
 {
   public:
     LIR_HEADER(SimdExtractElementB);
     explicit LSimdExtractElementB(const LAllocation& base)
-      : LSimdExtractElementBase(base)
+      : LSimdExtractElementBase(classOpcode, base)
     {}
 };
 
 // Extracts an element from a given SIMD int32x4 lane.
 class LSimdExtractElementI : public LSimdExtractElementBase
 {
   public:
     LIR_HEADER(SimdExtractElementI);
     explicit LSimdExtractElementI(const LAllocation& base)
-      : LSimdExtractElementBase(base)
+      : LSimdExtractElementBase(classOpcode, base)
     {}
 };
 
 // Extracts an element from a given SIMD float32x4 lane.
 class LSimdExtractElementF : public LSimdExtractElementBase
 {
   public:
     LIR_HEADER(SimdExtractElementF);
     explicit LSimdExtractElementF(const LAllocation& base)
-      : LSimdExtractElementBase(base)
+      : LSimdExtractElementBase(classOpcode, base)
     {}
 };
 
 // Extracts an element from an Uint32x4 SIMD vector, converts to double.
 class LSimdExtractElementU2D : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(SimdExtractElementU2D);
-    explicit LSimdExtractElementU2D(const LAllocation& base, const LDefinition& temp) {
+    LSimdExtractElementU2D(const LAllocation& base, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, base);
         setTemp(0, temp);
     }
     MSimdExtractElement* mir() const {
         return mir_->toSimdExtractElement();
     }
     const LDefinition* temp() {
         return getTemp(0);
     }
 };
 
 
 class LSimdInsertElementBase : public LInstructionHelper<1, 2, 0>
 {
   protected:
-    LSimdInsertElementBase(const LAllocation& vec, const LAllocation& val)
+    LSimdInsertElementBase(Opcode opcode, const LAllocation& vec, const LAllocation& val)
+      : LInstructionHelper(opcode)
     {
         setOperand(0, vec);
         setOperand(1, val);
     }
 
   public:
     const LAllocation* vector() {
         return getOperand(0);
@@ -345,35 +364,36 @@ class LSimdInsertElementBase : public LI
 
 // Replace an element from a given SIMD integer or boolean lane with a given value.
 // The value inserted into a boolean lane should be 0 or -1.
 class LSimdInsertElementI : public LSimdInsertElementBase
 {
   public:
     LIR_HEADER(SimdInsertElementI);
     LSimdInsertElementI(const LAllocation& vec, const LAllocation& val)
-      : LSimdInsertElementBase(vec, val)
+      : LSimdInsertElementBase(classOpcode, vec, val)
     {}
 };
 
 // Replace an element from a given SIMD float32x4 lane with a given value.
 class LSimdInsertElementF : public LSimdInsertElementBase
 {
   public:
     LIR_HEADER(SimdInsertElementF);
     LSimdInsertElementF(const LAllocation& vec, const LAllocation& val)
-      : LSimdInsertElementBase(vec, val)
+      : LSimdInsertElementBase(classOpcode, vec, val)
     {}
 };
 
 // Base class for both int32x4 and float32x4 shuffle instructions.
 class LSimdSwizzleBase : public LInstructionHelper<1, 1, 1>
 {
   public:
-    explicit LSimdSwizzleBase(const LAllocation& base)
+    LSimdSwizzleBase(Opcode opcode, const LAllocation& base)
+      : LInstructionHelper(opcode)
     {
         setOperand(0, base);
     }
 
     const LAllocation* getBase() {
         return getOperand(0);
     }
 
@@ -385,33 +405,33 @@ class LSimdSwizzleBase : public LInstruc
     }
 };
 
 // Shuffles a int32x4 into another int32x4 vector.
 class LSimdSwizzleI : public LSimdSwizzleBase
 {
   public:
     LIR_HEADER(SimdSwizzleI);
-    explicit LSimdSwizzleI(const LAllocation& base) : LSimdSwizzleBase(base)
+    explicit LSimdSwizzleI(const LAllocation& base) : LSimdSwizzleBase(classOpcode, base)
     {}
 };
 // Shuffles a float32x4 into another float32x4 vector.
 class LSimdSwizzleF : public LSimdSwizzleBase
 {
   public:
     LIR_HEADER(SimdSwizzleF);
-    explicit LSimdSwizzleF(const LAllocation& base) : LSimdSwizzleBase(base)
+    explicit LSimdSwizzleF(const LAllocation& base) : LSimdSwizzleBase(classOpcode, base)
     {}
 };
 
 class LSimdGeneralShuffleBase : public LVariadicInstruction<1, 1>
 {
   public:
-    LSimdGeneralShuffleBase(const LDefinition& temp, uint32_t numOperands)
-      : LVariadicInstruction<1, 1>(numOperands)
+    LSimdGeneralShuffleBase(LNode::Opcode opcode, uint32_t numOperands, const LDefinition& temp)
+      : LVariadicInstruction<1, 1>(opcode, numOperands)
     {
         setTemp(0, temp);
     }
     const LAllocation* vector(unsigned i) {
         MOZ_ASSERT(i < mir()->numVectors());
         return getOperand(i);
     }
     const LAllocation* lane(unsigned i) {
@@ -426,37 +446,38 @@ class LSimdGeneralShuffleBase : public L
     }
 };
 
 class LSimdGeneralShuffleI : public LSimdGeneralShuffleBase
 {
   public:
     LIR_HEADER(SimdGeneralShuffleI);
 
-    LSimdGeneralShuffleI(const LDefinition& temp, uint32_t numOperands)
-      : LSimdGeneralShuffleBase(temp, numOperands)
+    LSimdGeneralShuffleI(uint32_t numOperands, const LDefinition& temp)
+      : LSimdGeneralShuffleBase(classOpcode, numOperands, temp)
     {}
 };
 
 class LSimdGeneralShuffleF : public LSimdGeneralShuffleBase
 {
   public:
     LIR_HEADER(SimdGeneralShuffleF);
 
-    LSimdGeneralShuffleF(const LDefinition& temp, uint32_t numOperands)
-      : LSimdGeneralShuffleBase(temp, numOperands)
+    LSimdGeneralShuffleF(uint32_t numOperands, const LDefinition& temp)
+      : LSimdGeneralShuffleBase(classOpcode, numOperands, temp)
     {}
 };
 
 // Base class for both int32x4 and float32x4 shuffle instructions.
 class LSimdShuffleX4 : public LInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(SimdShuffleX4);
     LSimdShuffleX4()
+      : LInstructionHelper(classOpcode)
     {}
 
     const LAllocation* lhs() {
         return getOperand(0);
     }
     const LAllocation* rhs() {
         return getOperand(1);
     }
@@ -472,16 +493,17 @@ class LSimdShuffleX4 : public LInstructi
 };
 
 // Remaining shuffles (8x16, 16x8).
 class LSimdShuffle : public LInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(SimdShuffle);
     LSimdShuffle()
+      : LInstructionHelper(classOpcode)
     {}
 
     const LAllocation* lhs() {
         return getOperand(0);
     }
     const LAllocation* rhs() {
         return getOperand(1);
     }
@@ -492,19 +514,21 @@ class LSimdShuffle : public LInstruction
     unsigned numLanes() const { return mir_->toSimdShuffle()->numLanes(); }
     unsigned lane(unsigned i) const { return mir_->toSimdShuffle()->lane(i); }
 };
 
 // Binary SIMD comparison operation between two SIMD operands
 class LSimdBinaryComp: public LInstructionHelper<1, 2, 0>
 {
   protected:
-    LSimdBinaryComp() {}
-
-public:
+    explicit LSimdBinaryComp(LNode::Opcode opcode)
+      : LInstructionHelper<1, 2, 0>(opcode)
+    {}
+
+  public:
     const LAllocation* lhs() {
         return getOperand(0);
     }
     const LAllocation* rhs() {
         return getOperand(1);
     }
     MSimdBinaryComp::Operation operation() const {
         return mir_->toSimdBinaryComp()->operation();
@@ -514,48 +538,50 @@ public:
     }
 };
 
 // Binary SIMD comparison operation between two Int8x16 operands.
 class LSimdBinaryCompIx16 : public LSimdBinaryComp
 {
   public:
     LIR_HEADER(SimdBinaryCompIx16);
-    LSimdBinaryCompIx16() : LSimdBinaryComp() {}
+    LSimdBinaryCompIx16() : LSimdBinaryComp(classOpcode) {}
 };
 
 // Binary SIMD comparison operation between two Int16x8 operands.
 class LSimdBinaryCompIx8 : public LSimdBinaryComp
 {
   public:
     LIR_HEADER(SimdBinaryCompIx8);
-    LSimdBinaryCompIx8() : LSimdBinaryComp() {}
+    LSimdBinaryCompIx8() : LSimdBinaryComp(classOpcode) {}
 };
 
 // Binary SIMD comparison operation between two Int32x4 operands.
 class LSimdBinaryCompIx4 : public LSimdBinaryComp
 {
   public:
     LIR_HEADER(SimdBinaryCompIx4);
-    LSimdBinaryCompIx4() : LSimdBinaryComp() {}
+    LSimdBinaryCompIx4() : LSimdBinaryComp(classOpcode) {}
 };
 
 // Binary SIMD comparison operation between two Float32x4 operands
 class LSimdBinaryCompFx4 : public LSimdBinaryComp
 {
   public:
     LIR_HEADER(SimdBinaryCompFx4);
-    LSimdBinaryCompFx4() : LSimdBinaryComp() {}
+    LSimdBinaryCompFx4() : LSimdBinaryComp(classOpcode) {}
 };
 
 // Binary SIMD arithmetic operation between two SIMD operands
 class LSimdBinaryArith : public LInstructionHelper<1, 2, 1>
 {
   public:
-    LSimdBinaryArith() {}
+    explicit LSimdBinaryArith(LNode::Opcode opcode)
+      : LInstructionHelper<1, 2, 1>(opcode)
+    {}
 
     const LAllocation* lhs() {
         return this->getOperand(0);
     }
     const LAllocation* rhs() {
         return this->getOperand(1);
     }
     const LDefinition* temp() {
@@ -570,49 +596,51 @@ class LSimdBinaryArith : public LInstruc
     }
 };
 
 // Binary SIMD arithmetic operation between two Int8x16 operands
 class LSimdBinaryArithIx16 : public LSimdBinaryArith
 {
   public:
     LIR_HEADER(SimdBinaryArithIx16);
-    LSimdBinaryArithIx16() : LSimdBinaryArith() {}
+    LSimdBinaryArithIx16() : LSimdBinaryArith(classOpcode) {}
 };
 
 // Binary SIMD arithmetic operation between two Int16x8 operands
 class LSimdBinaryArithIx8 : public LSimdBinaryArith
 {
   public:
     LIR_HEADER(SimdBinaryArithIx8);
-    LSimdBinaryArithIx8() : LSimdBinaryArith() {}
+    LSimdBinaryArithIx8() : LSimdBinaryArith(classOpcode) {}
 };
 
 // Binary SIMD arithmetic operation between two Int32x4 operands
 class LSimdBinaryArithIx4 : public LSimdBinaryArith
 {
   public:
     LIR_HEADER(SimdBinaryArithIx4);
-    LSimdBinaryArithIx4() : LSimdBinaryArith() {}
+    LSimdBinaryArithIx4() : LSimdBinaryArith(classOpcode) {}
 };
 
 // Binary SIMD arithmetic operation between two Float32x4 operands
 class LSimdBinaryArithFx4 : public LSimdBinaryArith
 {
   public:
     LIR_HEADER(SimdBinaryArithFx4);
-    LSimdBinaryArithFx4() : LSimdBinaryArith() {}
+    LSimdBinaryArithFx4() : LSimdBinaryArith(classOpcode) {}
 };
 
 // Binary SIMD saturating arithmetic operation between two SIMD operands
 class LSimdBinarySaturating : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(SimdBinarySaturating);
-    LSimdBinarySaturating() {}
+    LSimdBinarySaturating()
+      : LInstructionHelper(classOpcode)
+    {}
 
     const LAllocation* lhs() {
         return this->getOperand(0);
     }
     const LAllocation* rhs() {
         return this->getOperand(1);
     }
 
@@ -629,61 +657,66 @@ class LSimdBinarySaturating : public LIn
         return MSimdBinarySaturating::OperationName(operation());
     }
 };
 
 // Unary SIMD arithmetic operation on a SIMD operand
 class LSimdUnaryArith : public LInstructionHelper<1, 1, 0>
 {
   public:
-    explicit LSimdUnaryArith(const LAllocation& in) {
+    LSimdUnaryArith(LNode::Opcode opcode, const LAllocation& in)
+      : LInstructionHelper(opcode)
+    {
         setOperand(0, in);
     }
     MSimdUnaryArith::Operation operation() const {
         return mir_->toSimdUnaryArith()->operation();
     }
 };
 
 // Unary SIMD arithmetic operation on a Int8x16 operand
 class LSimdUnaryArithIx16 : public LSimdUnaryArith
 {
   public:
     LIR_HEADER(SimdUnaryArithIx16);
-    explicit LSimdUnaryArithIx16(const LAllocation& in) : LSimdUnaryArith(in) {}
+    explicit LSimdUnaryArithIx16(const LAllocation& in) : LSimdUnaryArith(classOpcode, in) {}
 };
 
 // Unary SIMD arithmetic operation on a Int16x8 operand
 class LSimdUnaryArithIx8 : public LSimdUnaryArith
 {
   public:
     LIR_HEADER(SimdUnaryArithIx8);
-    explicit LSimdUnaryArithIx8(const LAllocation& in) : LSimdUnaryArith(in) {}
+    explicit LSimdUnaryArithIx8(const LAllocation& in) : LSimdUnaryArith(classOpcode, in) {}
 };
 
 // Unary SIMD arithmetic operation on a Int32x4 operand
 class LSimdUnaryArithIx4 : public LSimdUnaryArith
 {
   public:
     LIR_HEADER(SimdUnaryArithIx4);
-    explicit LSimdUnaryArithIx4(const LAllocation& in) : LSimdUnaryArith(in) {}
+    explicit LSimdUnaryArithIx4(const LAllocation& in) : LSimdUnaryArith(classOpcode, in) {}
 };
 
 // Unary SIMD arithmetic operation on a Float32x4 operand
 class LSimdUnaryArithFx4 : public LSimdUnaryArith
 {
   public:
     LIR_HEADER(SimdUnaryArithFx4);
-    explicit LSimdUnaryArithFx4(const LAllocation& in) : LSimdUnaryArith(in) {}
+    explicit LSimdUnaryArithFx4(const LAllocation& in) : LSimdUnaryArith(classOpcode, in) {}
 };
 
 // Binary SIMD bitwise operation between two 128-bit operands.
 class LSimdBinaryBitwise : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(SimdBinaryBitwise);
+    LSimdBinaryBitwise()
+      : LInstructionHelper(classOpcode)
+    {}
     const LAllocation* lhs() {
         return getOperand(0);
     }
     const LAllocation* rhs() {
         return getOperand(1);
     }
     MSimdBinaryBitwise::Operation operation() const {
         return mir_->toSimdBinaryBitwise()->operation();
@@ -698,17 +731,19 @@ class LSimdBinaryBitwise : public LInstr
 
 // Shift a SIMD vector by a scalar amount.
 // The temp register is only required if the shift amount is a dynamical
 // value. If it is a constant, use a BogusTemp instead.
 class LSimdShift : public LInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(SimdShift)
-    LSimdShift(const LAllocation& vec, const LAllocation& val, const LDefinition& temp) {
+    LSimdShift(const LAllocation& vec, const LAllocation& val, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, vec);
         setOperand(1, val);
         setTemp(0, temp);
     }
     const LAllocation* vector() {
         return getOperand(0);
     }
     const LAllocation* value() {
@@ -732,16 +767,19 @@ class LSimdShift : public LInstructionHe
 };
 
 // SIMD selection of lanes from two int32x4 or float32x4 arguments based on a
 // int32x4 argument.
 class LSimdSelect : public LInstructionHelper<1, 3, 1>
 {
   public:
     LIR_HEADER(SimdSelect);
+    LSimdSelect()
+      : LInstructionHelper(classOpcode)
+    {}
     const LAllocation* mask() {
         return getOperand(0);
     }
     const LAllocation* lhs() {
         return getOperand(1);
     }
     const LAllocation* rhs() {
         return getOperand(2);
@@ -753,32 +791,36 @@ class LSimdSelect : public LInstructionH
         return mir_->toSimdSelect();
     }
 };
 
 class LSimdAnyTrue : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(SimdAnyTrue)
-    explicit LSimdAnyTrue(const LAllocation& input) {
+    explicit LSimdAnyTrue(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
     const LAllocation* vector() {
         return getOperand(0);
     }
     MSimdAnyTrue* mir() const {
         return mir_->toSimdAnyTrue();
     }
 };
 
 class LSimdAllTrue : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(SimdAllTrue)
-    explicit LSimdAllTrue(const LAllocation& input) {
+    explicit LSimdAllTrue(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
     const LAllocation* vector() {
         return getOperand(0);
     }
     MSimdAllTrue* mir() const {
         return mir_->toSimdAllTrue();
     }
@@ -789,34 +831,36 @@ class LSimdAllTrue : public LInstruction
 class LInteger : public LInstructionHelper<1, 0, 0>
 {
     int32_t i32_;
 
   public:
     LIR_HEADER(Integer)
 
     explicit LInteger(int32_t i32)
-      : i32_(i32)
+      : LInstructionHelper(classOpcode),
+        i32_(i32)
     { }
 
     int32_t getValue() const {
         return i32_;
     }
 };
 
 // Constant 64-bit integer.
 class LInteger64 : public LInstructionHelper<INT64_PIECES, 0, 0>
 {
     int64_t i64_;
 
   public:
     LIR_HEADER(Integer64)
 
     explicit LInteger64(int64_t i64)
-      : i64_(i64)
+      : LInstructionHelper(classOpcode),
+        i64_(i64)
     { }
 
     int64_t getValue() const {
         return i64_;
     }
 };
 
 // Constant pointer.
@@ -831,21 +875,25 @@ class LPointer : public LInstructionHelp
   private:
     void* ptr_;
     Kind kind_;
 
   public:
     LIR_HEADER(Pointer)
 
     explicit LPointer(gc::Cell* ptr)
-      : ptr_(ptr), kind_(GC_THING)
+      : LInstructionHelper(classOpcode),
+        ptr_(ptr),
+        kind_(GC_THING)
     { }
 
     LPointer(void* ptr, Kind kind)
-      : ptr_(ptr), kind_(kind)
+      : LInstructionHelper(classOpcode),
+        ptr_(ptr),
+        kind_(kind)
     { }
 
     void* ptr() const {
         return ptr_;
     }
     Kind kind() const {
         return kind_;
     }
@@ -861,86 +909,91 @@ class LPointer : public LInstructionHelp
 
 // Constant double.
 class LDouble : public LInstructionHelper<1, 0, 0>
 {
     double d_;
   public:
     LIR_HEADER(Double);
 
-    explicit LDouble(double d) : d_(d)
+    explicit LDouble(double d)
+      : LInstructionHelper(classOpcode),
+        d_(d)
     { }
 
     const double& getDouble() const {
         return d_;
     }
 };
 
 // Constant float32.
 class LFloat32 : public LInstructionHelper<1, 0, 0>
 {
     float f_;
   public:
     LIR_HEADER(Float32);
 
     explicit LFloat32(float f)
-      : f_(f)
+      : LInstructionHelper(classOpcode),
+        f_(f)
     { }
 
     const float& getFloat() const {
         return f_;
     }
 };
 
 // Constant 128-bit SIMD integer vector (8x16, 16x8, 32x4).
 // Also used for Bool32x4, Bool16x8, etc.
 class LSimd128Int : public LInstructionHelper<1, 0, 0>
 {
   public:
     LIR_HEADER(Simd128Int);
 
-    explicit LSimd128Int() {}
+    explicit LSimd128Int() : LInstructionHelper(classOpcode) {}
     const SimdConstant& getValue() const { return mir_->toSimdConstant()->value(); }
 };
 
 // Constant 128-bit SIMD floating point vector (32x4, 64x2).
 class LSimd128Float : public LInstructionHelper<1, 0, 0>
 {
   public:
     LIR_HEADER(Simd128Float);
 
-    explicit LSimd128Float() {}
+    explicit LSimd128Float() : LInstructionHelper(classOpcode) {}
     const SimdConstant& getValue() const { return mir_->toSimdConstant()->value(); }
 };
 
 // A constant Value.
 class LValue : public LInstructionHelper<BOX_PIECES, 0, 0>
 {
     Value v_;
 
   public:
     LIR_HEADER(Value)
 
     explicit LValue(const Value& v)
-      : v_(v)
+      : LInstructionHelper(classOpcode),
+        v_(v)
     { }
 
     Value value() const {
         return v_;
     }
 };
 
 // Clone an object literal such as we are not modifying the object contained in
 // the sources.
 class LCloneLiteral : public LCallInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(CloneLiteral)
 
     explicit LCloneLiteral(const LAllocation& obj)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, obj);
     }
 
     const LAllocation* getObjectLiteral() {
         return getOperand(0);
     }
 
@@ -950,74 +1003,92 @@ class LCloneLiteral : public LCallInstru
 };
 
 // Formal argument for a function, returning a box. Formal arguments are
 // initially read from the stack.
 class LParameter : public LInstructionHelper<BOX_PIECES, 0, 0>
 {
   public:
     LIR_HEADER(Parameter)
+
+    LParameter()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 // Stack offset for a word-sized immutable input value to a frame.
 class LCallee : public LInstructionHelper<1, 0, 0>
 {
   public:
     LIR_HEADER(Callee)
+
+    LCallee()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 class LIsConstructing : public LInstructionHelper<1, 0, 0>
 {
   public:
     LIR_HEADER(IsConstructing)
+
+    LIsConstructing()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 // Base class for control instructions (goto, branch, etc.)
 template <size_t Succs, size_t Operands, size_t Temps>
 class LControlInstructionHelper : public LInstructionHelper<0, Operands, Temps> {
 
     mozilla::Array<MBasicBlock*, Succs> successors_;
 
   protected:
-    LControlInstructionHelper() {
-        this->setNumSuccessors(Succs);
-    }
-
-  public:
+    explicit LControlInstructionHelper(LNode::Opcode opcode)
+      : LInstructionHelper<0, Operands, Temps>(opcode)
+    {}
+
+  public:
+    size_t numSuccessors() const {
+        return Succs;
+    }
     MBasicBlock* getSuccessor(size_t i) const {
         return successors_[i];
     }
 
     void setSuccessor(size_t i, MBasicBlock* successor) {
         successors_[i] = successor;
     }
 };
 
 // Jumps to the start of a basic block.
 class LGoto : public LControlInstructionHelper<1, 0, 0>
 {
   public:
     LIR_HEADER(Goto)
 
     explicit LGoto(MBasicBlock* block)
+      : LControlInstructionHelper(classOpcode)
     {
          setSuccessor(0, block);
     }
 
     MBasicBlock* target() const {
         return getSuccessor(0);
     }
 };
 
 class LNewArray : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(NewArray)
 
-    explicit LNewArray(const LDefinition& temp) {
+    explicit LNewArray(const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp);
     }
 
     const char* extraName() const {
         return mir()->isVMCall() ? "VMCall" : nullptr;
     }
 
     const LDefinition* temp() {
@@ -1029,17 +1100,19 @@ class LNewArray : public LInstructionHel
     }
 };
 
 class LNewArrayCopyOnWrite : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(NewArrayCopyOnWrite)
 
-    explicit LNewArrayCopyOnWrite(const LDefinition& temp) {
+    explicit LNewArrayCopyOnWrite(const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
     MNewArrayCopyOnWrite* mir() const {
@@ -1047,17 +1120,19 @@ class LNewArrayCopyOnWrite : public LIns
     }
 };
 
 class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(NewArrayDynamicLength)
 
-    explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp) {
+    explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, length);
         setTemp(0, temp);
     }
 
     const LAllocation* length() {
         return getOperand(0);
     }
     const LDefinition* temp() {
@@ -1069,17 +1144,19 @@ class LNewArrayDynamicLength : public LI
     }
 };
 
 class LNewIterator : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(NewIterator)
 
-    explicit LNewIterator(const LDefinition& temp) {
+    explicit LNewIterator(const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
     MNewIterator* mir() const {
@@ -1087,17 +1164,19 @@ class LNewIterator : public LInstruction
     }
 };
 
 class LNewTypedArray : public LInstructionHelper<1, 0, 2>
 {
   public:
     LIR_HEADER(NewTypedArray)
 
-    explicit LNewTypedArray(const LDefinition& temp1, const LDefinition& temp2) {
+    LNewTypedArray(const LDefinition& temp1, const LDefinition& temp2)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp1);
         setTemp(1, temp2);
     }
 
     const LDefinition* temp1() {
         return getTemp(0);
     }
 
@@ -1110,17 +1189,19 @@ class LNewTypedArray : public LInstructi
     }
 };
 
 class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(NewTypedArrayDynamicLength)
 
-    explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp) {
+    LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, length);
         setTemp(0, temp);
     }
 
     const LAllocation* length() {
         return getOperand(0);
     }
     const LDefinition* temp() {
@@ -1132,17 +1213,19 @@ class LNewTypedArrayDynamicLength : publ
     }
 };
 
 class LNewObject : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(NewObject)
 
-    explicit LNewObject(const LDefinition& temp) {
+    explicit LNewObject(const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp);
     }
 
     const char* extraName() const {
         return mir()->isVMCall() ? "VMCall" : nullptr;
     }
 
     const LDefinition* temp() {
@@ -1154,17 +1237,19 @@ class LNewObject : public LInstructionHe
     }
 };
 
 class LNewTypedObject : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(NewTypedObject)
 
-    explicit LNewTypedObject(const LDefinition& temp) {
+    explicit LNewTypedObject(const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
     MNewTypedObject* mir() const {
@@ -1178,17 +1263,19 @@ class LNewTypedObject : public LInstruct
 //   (1) An inline allocation of the call object is attempted.
 //   (2) Otherwise, a callVM create a new object.
 //
 class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(NewNamedLambdaObject);
 
-    explicit LNewNamedLambdaObject(const LDefinition& temp) {
+    explicit LNewNamedLambdaObject(const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
     MNewNamedLambdaObject* mir() const {
@@ -1203,17 +1290,19 @@ class LNewNamedLambdaObject : public LIn
 //       call object.
 //   (2) Otherwise, an inline allocation of the call object is attempted.
 //
 class LNewCallObject : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(NewCallObject)
 
-    explicit LNewCallObject(const LDefinition& temp) {
+    explicit LNewCallObject(const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
 
@@ -1223,17 +1312,19 @@ class LNewCallObject : public LInstructi
 };
 
 // Performs a callVM to allocate a new CallObject with singleton type.
 class LNewSingletonCallObject : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(NewSingletonCallObject)
 
-    explicit LNewSingletonCallObject(const LDefinition& temp) {
+    explicit LNewSingletonCallObject(const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
     MNewSingletonCallObject* mir() const {
@@ -1243,17 +1334,19 @@ class LNewSingletonCallObject : public L
 
 class LNewDerivedTypedObject : public LCallInstructionHelper<1, 3, 0>
 {
   public:
     LIR_HEADER(NewDerivedTypedObject);
 
     LNewDerivedTypedObject(const LAllocation& type,
                            const LAllocation& owner,
-                           const LAllocation& offset) {
+                           const LAllocation& offset)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, type);
         setOperand(1, owner);
         setOperand(2, offset);
     }
 
     const LAllocation* type() {
         return getOperand(0);
     }
@@ -1267,17 +1360,19 @@ class LNewDerivedTypedObject : public LC
     }
 };
 
 class LNewStringObject : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(NewStringObject)
 
-    LNewStringObject(const LAllocation& input, const LDefinition& temp) {
+    LNewStringObject(const LAllocation& input, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
         setTemp(0, temp);
     }
 
     const LAllocation* input() {
         return getOperand(0);
     }
     const LDefinition* temp() {
@@ -1288,17 +1383,19 @@ class LNewStringObject : public LInstruc
     }
 };
 
 class LInitElem : public LCallInstructionHelper<0, 1 + 2*BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(InitElem)
 
-    LInitElem(const LAllocation& object, const LBoxAllocation& id, const LBoxAllocation& value) {
+    LInitElem(const LAllocation& object, const LBoxAllocation& id, const LBoxAllocation& value)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setBoxOperand(IdIndex, id);
         setBoxOperand(ValueIndex, value);
     }
 
     static const size_t IdIndex = 1;
     static const size_t ValueIndex = 1 + BOX_PIECES;
 
@@ -1311,17 +1408,19 @@ class LInitElem : public LCallInstructio
 };
 
 class LInitElemGetterSetter : public LCallInstructionHelper<0, 2 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(InitElemGetterSetter)
 
     LInitElemGetterSetter(const LAllocation& object, const LBoxAllocation& id,
-                          const LAllocation& value) {
+                          const LAllocation& value)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setOperand(1, value);
         setBoxOperand(IdIndex, id);
     }
 
     static const size_t IdIndex = 2;
 
     const LAllocation* object() {
@@ -1336,17 +1435,19 @@ class LInitElemGetterSetter : public LCa
 };
 
 // Takes in an Object and a Value.
 class LMutateProto : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(MutateProto)
 
-    LMutateProto(const LAllocation& object, const LBoxAllocation& value) {
+    LMutateProto(const LAllocation& object, const LBoxAllocation& value)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setBoxOperand(ValueIndex, value);
     }
 
     static const size_t ValueIndex = 1;
 
     const LAllocation* getObject() {
         return getOperand(0);
@@ -1356,17 +1457,19 @@ class LMutateProto : public LCallInstruc
     }
 };
 
 class LInitPropGetterSetter : public LCallInstructionHelper<0, 2, 0>
 {
   public:
     LIR_HEADER(InitPropGetterSetter)
 
-    LInitPropGetterSetter(const LAllocation& object, const LAllocation& value) {
+    LInitPropGetterSetter(const LAllocation& object, const LAllocation& value)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setOperand(1, value);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
     const LAllocation* value() {
@@ -1378,17 +1481,19 @@ class LInitPropGetterSetter : public LCa
     }
 };
 
 class LCheckOverRecursed : public LInstructionHelper<0, 0, 1>
 {
   public:
     LIR_HEADER(CheckOverRecursed)
 
-    explicit LCheckOverRecursed(const LDefinition& temp) {
+    explicit LCheckOverRecursed(const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
     MCheckOverRecursed* mir() const {
@@ -1397,91 +1502,114 @@ class LCheckOverRecursed : public LInstr
 };
 
 class LWasmTrap : public LInstructionHelper<0, 0, 0>
 {
   public:
     LIR_HEADER(WasmTrap);
 
     LWasmTrap()
+      : LInstructionHelper(classOpcode)
     { }
 
     const MWasmTrap* mir() const {
         return mir_->toWasmTrap();
     }
 };
 
 template<size_t Defs, size_t Ops>
 class LWasmReinterpretBase : public LInstructionHelper<Defs, Ops, 0>
 {
     typedef LInstructionHelper<Defs, Ops, 0> Base;
 
+  protected:
+    explicit LWasmReinterpretBase(LNode::Opcode opcode)
+      : Base(opcode)
+    {}
+
   public:
     const LAllocation* input() {
         return Base::getOperand(0);
     }
     MWasmReinterpret* mir() const {
         return Base::mir_->toWasmReinterpret();
     }
 };
 
 class LWasmReinterpret : public LWasmReinterpretBase<1, 1>
 {
   public:
     LIR_HEADER(WasmReinterpret);
-    explicit LWasmReinterpret(const LAllocation& input) {
+    explicit LWasmReinterpret(const LAllocation& input)
+      : LWasmReinterpretBase(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 class LWasmReinterpretFromI64 : public LWasmReinterpretBase<1, INT64_PIECES>
 {
   public:
     LIR_HEADER(WasmReinterpretFromI64);
-    explicit LWasmReinterpretFromI64(const LInt64Allocation& input) {
+    explicit LWasmReinterpretFromI64(const LInt64Allocation& input)
+      : LWasmReinterpretBase(classOpcode)
+    {
         setInt64Operand(0, input);
     }
 };
 
 class LWasmReinterpretToI64 : public LWasmReinterpretBase<INT64_PIECES, 1>
 {
   public:
     LIR_HEADER(WasmReinterpretToI64);
-    explicit LWasmReinterpretToI64(const LAllocation& input) {
+    explicit LWasmReinterpretToI64(const LAllocation& input)
+      : LWasmReinterpretBase(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 namespace details {
     template<size_t Defs, size_t Ops, size_t Temps>
     class RotateBase : public LInstructionHelper<Defs, Ops, Temps>
     {
         typedef LInstructionHelper<Defs, Ops, Temps> Base;
+
+      protected:
+        explicit RotateBase(LNode::Opcode opcode)
+          : Base(opcode)
+        {}
+
       public:
         MRotate* mir() {
             return Base::mir_->toRotate();
         }
     };
 } // details
 
 class LRotate : public details::RotateBase<1, 2, 0>
 {
   public:
     LIR_HEADER(Rotate);
 
+    LRotate()
+      : RotateBase(classOpcode)
+    {}
+
     const LAllocation* input() { return getOperand(0); }
     LAllocation* count() { return getOperand(1); }
 };
 
 class LRotateI64 : public details::RotateBase<INT64_PIECES, INT64_PIECES + 1, 1>
 {
   public:
     LIR_HEADER(RotateI64);
 
     LRotateI64()
+      : RotateBase(classOpcode)
     {
         setTemp(0, LDefinition::BogusTemp());
     }
 
     static const size_t Input = 0;
     static const size_t Count = INT64_PIECES;
 
     const LInt64Allocation input() { return getInt64Operand(Input); }
@@ -1497,17 +1625,18 @@ class LInterruptCheck : public LInstruct
     // use a patchable backedge and signal handlers instead of an explicit
     // cx->interrupt check.
     bool implicit_;
 
   public:
     LIR_HEADER(InterruptCheck)
 
     explicit LInterruptCheck(const LDefinition& temp)
-      : oolEntry_(nullptr),
+      : LInstructionHelper(classOpcode),
+        oolEntry_(nullptr),
         implicit_(false)
     {
         setTemp(0, temp);
     }
 
     Label* oolEntry() {
         MOZ_ASSERT(implicit_);
         return oolEntry_;
@@ -1535,16 +1664,17 @@ class LInterruptCheck : public LInstruct
 };
 
 class LDefVar : public LCallInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(DefVar)
 
     explicit LDefVar(const LAllocation& envChain)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, envChain);
     }
 
     const LAllocation* environmentChain() {
         return getOperand(0);
     }
     MDefVar* mir() const {
@@ -1552,27 +1682,32 @@ class LDefVar : public LCallInstructionH
     }
 };
 
 class LDefLexical : public LCallInstructionHelper<0, 0, 0>
 {
   public:
     LIR_HEADER(DefLexical)
 
+    LDefLexical()
+      : LCallInstructionHelper(classOpcode)
+    {}
+
     MDefLexical* mir() const {
         return mir_->toDefLexical();
     }
 };
 
 class LDefFun : public LCallInstructionHelper<0, 2, 0>
 {
   public:
     LIR_HEADER(DefFun)
 
     LDefFun(const LAllocation& fun, const LAllocation& envChain)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, fun);
         setOperand(1, envChain);
     }
 
     const LAllocation* fun() {
         return getOperand(0);
     }
@@ -1584,17 +1719,19 @@ class LDefFun : public LCallInstructionH
     }
 };
 
 class LTypeOfV : public LInstructionHelper<1, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(TypeOfV)
 
-    LTypeOfV(const LBoxAllocation& input, const LDefinition& tempToUnbox) {
+    LTypeOfV(const LBoxAllocation& input, const LDefinition& tempToUnbox)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
         setTemp(0, tempToUnbox);
     }
 
     static const size_t Input = 0;
 
     const LDefinition* tempToUnbox() {
         return getTemp(0);
@@ -1604,43 +1741,52 @@ class LTypeOfV : public LInstructionHelp
         return mir_->toTypeOf();
     }
 };
 
 class LToAsync : public LCallInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(ToAsync)
-    explicit LToAsync(const LAllocation& input) {
+
+    explicit LToAsync(const LAllocation& input)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 
     const LAllocation* unwrapped() {
         return getOperand(0);
     }
 };
 
 class LToAsyncGen : public LCallInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(ToAsyncGen)
-    explicit LToAsyncGen(const LAllocation& input) {
+
+    explicit LToAsyncGen(const LAllocation& input)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 
     const LAllocation* unwrapped() {
         return getOperand(0);
     }
 };
 
 class LToAsyncIter : public LCallInstructionHelper<1, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(ToAsyncIter)
-    explicit LToAsyncIter(const LAllocation& iterator, const LBoxAllocation& nextMethod) {
+
+    explicit LToAsyncIter(const LAllocation& iterator, const LBoxAllocation& nextMethod)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, iterator);
         setBoxOperand(NextMethodIndex, nextMethod);
     }
 
     static const size_t NextMethodIndex = 1;
 
     const LAllocation* iterator() {
         return getOperand(0);
@@ -1648,16 +1794,17 @@ class LToAsyncIter : public LCallInstruc
 };
 
 class LToIdV : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(ToIdV)
 
     LToIdV(const LBoxAllocation& input, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
     {
         setBoxOperand(Input, input);
         setTemp(0, temp);
     }
 
     static const size_t Input = 0;
 
     MToId* mir() const {
@@ -1672,16 +1819,17 @@ class LToIdV : public LInstructionHelper
 // Allocate an object for |new| on the caller-side,
 // when there is no templateObject or prototype known
 class LCreateThis : public LCallInstructionHelper<BOX_PIECES, 2, 0>
 {
   public:
     LIR_HEADER(CreateThis)
 
     LCreateThis(const LAllocation& callee, const LAllocation& newTarget)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, callee);
         setOperand(1, newTarget);
     }
 
     const LAllocation* getCallee() {
         return getOperand(0);
     }
@@ -1698,16 +1846,17 @@ class LCreateThis : public LCallInstruct
 // when the prototype is known.
 class LCreateThisWithProto : public LCallInstructionHelper<1, 3, 0>
 {
   public:
     LIR_HEADER(CreateThisWithProto)
 
     LCreateThisWithProto(const LAllocation& callee, const LAllocation& newTarget,
                          const LAllocation& prototype)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, callee);
         setOperand(1, newTarget);
         setOperand(2, prototype);
     }
 
     const LAllocation* getCallee() {
         return getOperand(0);
@@ -1726,17 +1875,19 @@ class LCreateThisWithProto : public LCal
 
 // Allocate an object for |new| on the caller-side.
 // Always performs object initialization with a fast path.
 class LCreateThisWithTemplate : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(CreateThisWithTemplate)
 
-    explicit LCreateThisWithTemplate(const LDefinition& temp) {
+    explicit LCreateThisWithTemplate(const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp);
     }
 
     MCreateThisWithTemplate* mir() const {
         return mir_->toCreateThisWithTemplate();
     }
 
     const LDefinition* temp() {
@@ -1747,16 +1898,17 @@ class LCreateThisWithTemplate : public L
 // Allocate a new arguments object for the frame.
 class LCreateArgumentsObject : public LCallInstructionHelper<1, 1, 3>
 {
   public:
     LIR_HEADER(CreateArgumentsObject)
 
     LCreateArgumentsObject(const LAllocation& callObj, const LDefinition& temp0,
                            const LDefinition& temp1, const LDefinition& temp2)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, callObj);
         setTemp(0, temp0);
         setTemp(1, temp1);
         setTemp(2, temp2);
     }
 
     const LDefinition* temp0() {
@@ -1780,16 +1932,17 @@ class LCreateArgumentsObject : public LC
 
 // Get argument from arguments object.
 class LGetArgumentsObjectArg : public LInstructionHelper<BOX_PIECES, 1, 1>
 {
   public:
     LIR_HEADER(GetArgumentsObjectArg)
 
     LGetArgumentsObjectArg(const LAllocation& argsObj, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, argsObj);
         setTemp(0, temp);
     }
 
     const LAllocation* getArgsObject() {
         return getOperand(0);
     }
@@ -1802,16 +1955,17 @@ class LGetArgumentsObjectArg : public LI
 // Set argument on arguments object.
 class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(SetArgumentsObjectArg)
 
     LSetArgumentsObjectArg(const LAllocation& argsObj, const LBoxAllocation& value,
                            const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, argsObj);
         setBoxOperand(ValueIndex, value);
         setTemp(0, temp);
     }
 
     const LAllocation* getArgsObject() {
         return getOperand(0);
@@ -1827,16 +1981,17 @@ class LSetArgumentsObjectArg : public LI
 // If the Value is an Object, return unbox(Value).
 // Otherwise, return the other Object.
 class LReturnFromCtor : public LInstructionHelper<1, BOX_PIECES + 1, 0>
 {
   public:
     LIR_HEADER(ReturnFromCtor)
 
     LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object)
+      : LInstructionHelper(classOpcode)
     {
         setBoxOperand(ValueIndex, value);
         setOperand(ObjectIndex, object);
     }
 
     const LAllocation* getObject() {
         return getOperand(ObjectIndex);
     }
@@ -1847,17 +2002,19 @@ class LReturnFromCtor : public LInstruct
 
 class LComputeThis : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(ComputeThis)
 
     static const size_t ValueIndex = 0;
 
-    explicit LComputeThis(const LBoxAllocation& value) {
+    explicit LComputeThis(const LBoxAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(ValueIndex, value);
     }
 
     const LDefinition* output() {
         return getDef(0);
     }
 
     MComputeThis* mir() const {
@@ -1865,17 +2022,19 @@ class LComputeThis : public LInstruction
     }
 };
 
 class LImplicitThis : public LCallInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(ImplicitThis)
 
-    explicit LImplicitThis(const LAllocation& env) {
+    explicit LImplicitThis(const LAllocation& env)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, env);
     }
 
     const LAllocation* env() {
         return getOperand(0);
     }
 
     MImplicitThis* mir() const {
@@ -1888,17 +2047,18 @@ class LStackArgT : public LInstructionHe
 {
     uint32_t argslot_; // Index into frame-scope argument vector.
     MIRType type_;
 
   public:
     LIR_HEADER(StackArgT)
 
     LStackArgT(uint32_t argslot, MIRType type, const LAllocation& arg)
-      : argslot_(argslot),
+      : LInstructionHelper(classOpcode),
+        argslot_(argslot),
         type_(type)
     {
         setOperand(0, arg);
     }
     uint32_t argslot() const {
         return argslot_;
     }
     MIRType type() const {
@@ -1913,30 +2073,36 @@ class LStackArgT : public LInstructionHe
 class LStackArgV : public LInstructionHelper<0, BOX_PIECES, 0>
 {
     uint32_t argslot_; // Index into frame-scope argument vector.
 
   public:
     LIR_HEADER(StackArgV)
 
     LStackArgV(uint32_t argslot, const LBoxAllocation& value)
-      : argslot_(argslot)
+      : LInstructionHelper(classOpcode),
+        argslot_(argslot)
     {
         setBoxOperand(0, value);
     }
 
     uint32_t argslot() const {
         return argslot_;
     }
 };
 
 // Common code for LIR descended from MCall.
 template <size_t Defs, size_t Operands, size_t Temps>
 class LJSCallInstructionHelper : public LCallInstructionHelper<Defs, Operands, Temps>
 {
+  protected:
+    explicit LJSCallInstructionHelper(LNode::Opcode opcode)
+      : LCallInstructionHelper<Defs, Operands, Temps>(opcode)
+    {}
+
   public:
     uint32_t argslot() const {
         if (JitStackValueAlignment > 1)
             return AlignBytes(mir()->numStackArgs(), JitStackValueAlignment);
         return mir()->numStackArgs();
     }
     MCall* mir() const {
         return this->mir_->toCall();
@@ -1966,16 +2132,17 @@ class LJSCallInstructionHelper : public 
 // unknown and anticipated to vary.
 class LCallGeneric : public LJSCallInstructionHelper<BOX_PIECES, 1, 2>
 {
   public:
     LIR_HEADER(CallGeneric)
 
     LCallGeneric(const LAllocation& func, const LDefinition& nargsreg,
                  const LDefinition& tmpobjreg)
+      : LJSCallInstructionHelper(classOpcode)
     {
         setOperand(0, func);
         setTemp(0, nargsreg);
         setTemp(1, tmpobjreg);
     }
 
     const LAllocation* getFunction() {
         return getOperand(0);
@@ -1990,16 +2157,17 @@ class LCallGeneric : public LJSCallInstr
 
 // Generates a hardcoded callsite for a known, non-native target.
 class LCallKnown : public LJSCallInstructionHelper<BOX_PIECES, 1, 1>
 {
   public:
     LIR_HEADER(CallKnown)
 
     LCallKnown(const LAllocation& func, const LDefinition& tmpobjreg)
+      : LJSCallInstructionHelper(classOpcode)
     {
         setOperand(0, func);
         setTemp(0, tmpobjreg);
     }
 
     const LAllocation* getFunction() {
         return getOperand(0);
     }
@@ -2011,16 +2179,17 @@ class LCallKnown : public LJSCallInstruc
 // Generates a hardcoded callsite for a known, native target.
 class LCallNative : public LJSCallInstructionHelper<BOX_PIECES, 0, 4>
 {
   public:
     LIR_HEADER(CallNative)
 
     LCallNative(const LDefinition& argContext, const LDefinition& argUintN,
                 const LDefinition& argVp, const LDefinition& tmpreg)
+      : LJSCallInstructionHelper(classOpcode)
     {
         // Registers used for callWithABI().
         setTemp(0, argContext);
         setTemp(1, argUintN);
         setTemp(2, argVp);
 
         // Temporary registers.
         setTemp(3, tmpreg);
@@ -2043,16 +2212,17 @@ class LCallNative : public LJSCallInstru
 // Generates a hardcoded callsite for a known, DOM-native target.
 class LCallDOMNative : public LJSCallInstructionHelper<BOX_PIECES, 0, 4>
 {
   public:
     LIR_HEADER(CallDOMNative)
 
     LCallDOMNative(const LDefinition& argJSContext, const LDefinition& argObj,
                    const LDefinition& argPrivate, const LDefinition& argArgs)
+      : LJSCallInstructionHelper(classOpcode)
     {
         setTemp(0, argJSContext);
         setTemp(1, argObj);
         setTemp(2, argPrivate);
         setTemp(3, argArgs);
     }
 
     const LDefinition* getArgJSContext() {
@@ -2068,36 +2238,50 @@ class LCallDOMNative : public LJSCallIns
         return getTemp(3);
     }
 };
 
 class LBail : public LInstructionHelper<0, 0, 0>
 {
   public:
     LIR_HEADER(Bail)
+
+    LBail()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 class LUnreachable : public LControlInstructionHelper<0, 0, 0>
 {
   public:
     LIR_HEADER(Unreachable)
+
+    LUnreachable()
+      : LControlInstructionHelper(classOpcode)
+    {}
 };
 
 class LEncodeSnapshot : public LInstructionHelper<0, 0, 0>
 {
   public:
     LIR_HEADER(EncodeSnapshot)
+
+    LEncodeSnapshot()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 template <size_t defs, size_t ops>
 class LDOMPropertyInstructionHelper : public LCallInstructionHelper<defs, 1 + ops, 3>
 {
   protected:
-    LDOMPropertyInstructionHelper(const LDefinition& JSContextReg, const LAllocation& ObjectReg,
-                                  const LDefinition& PrivReg, const LDefinition& ValueReg)
+    LDOMPropertyInstructionHelper(LNode::Opcode opcode, const LDefinition& JSContextReg,
+                                  const LAllocation& ObjectReg, const LDefinition& PrivReg,
+                                  const LDefinition& ValueReg)
+      : LCallInstructionHelper<defs, 1 + ops, 3>(opcode)
     {
         this->setOperand(0, ObjectReg);
         this->setTemp(0, JSContextReg);
         this->setTemp(1, PrivReg);
         this->setTemp(2, ValueReg);
     }
 
   public:
@@ -2118,47 +2302,51 @@ class LDOMPropertyInstructionHelper : pu
 
 class LGetDOMProperty : public LDOMPropertyInstructionHelper<BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(GetDOMProperty)
 
     LGetDOMProperty(const LDefinition& JSContextReg, const LAllocation& ObjectReg,
                     const LDefinition& PrivReg, const LDefinition& ValueReg)
-      : LDOMPropertyInstructionHelper<BOX_PIECES, 0>(JSContextReg, ObjectReg,
+      : LDOMPropertyInstructionHelper<BOX_PIECES, 0>(classOpcode, JSContextReg, ObjectReg,
                                                      PrivReg, ValueReg)
     { }
 
     MGetDOMProperty* mir() const {
         return mir_->toGetDOMProperty();
     }
 };
 
 class LGetDOMMemberV : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(GetDOMMemberV);
-    explicit LGetDOMMemberV(const LAllocation& object) {
+    explicit LGetDOMMemberV(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
 
     MGetDOMMember* mir() const {
         return mir_->toGetDOMMember();
     }
 };
 
 class LGetDOMMemberT : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(GetDOMMemberT);
-    explicit LGetDOMMemberT(const LAllocation& object) {
+    explicit LGetDOMMemberT(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
 
     MGetDOMMember* mir() const {
@@ -2169,17 +2357,17 @@ class LGetDOMMemberT : public LInstructi
 class LSetDOMProperty : public LDOMPropertyInstructionHelper<0, BOX_PIECES>
 {
   public:
     LIR_HEADER(SetDOMProperty)
 
     LSetDOMProperty(const LDefinition& JSContextReg, const LAllocation& ObjectReg,
                     const LBoxAllocation& value, const LDefinition& PrivReg,
                     const LDefinition& ValueReg)
-      : LDOMPropertyInstructionHelper<0, BOX_PIECES>(JSContextReg, ObjectReg,
+      : LDOMPropertyInstructionHelper<0, BOX_PIECES>(classOpcode, JSContextReg, ObjectReg,
                                                      PrivReg, ValueReg)
     {
         setBoxOperand(Value, value);
     }
 
     static const size_t Value = 1;
 
     MSetDOMProperty* mir() const {
@@ -2192,16 +2380,17 @@ class LSetDOMProperty : public LDOMPrope
 class LApplyArgsGeneric : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2>
 {
   public:
     LIR_HEADER(ApplyArgsGeneric)
 
     LApplyArgsGeneric(const LAllocation& func, const LAllocation& argc,
                       const LBoxAllocation& thisv, const LDefinition& tmpobjreg,
                       const LDefinition& tmpcopy)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, func);
         setOperand(1, argc);
         setBoxOperand(ThisIndex, thisv);
         setTemp(0, tmpobjreg);
         setTemp(1, tmpcopy);
     }
 
@@ -2235,16 +2424,17 @@ class LApplyArgsGeneric : public LCallIn
 class LApplyArrayGeneric : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2>
 {
   public:
     LIR_HEADER(ApplyArrayGeneric)
 
     LApplyArrayGeneric(const LAllocation& func, const LAllocation& elements,
                        const LBoxAllocation& thisv, const LDefinition& tmpobjreg,
                        const LDefinition& tmpcopy)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, func);
         setOperand(1, elements);
         setBoxOperand(ThisIndex, thisv);
         setTemp(0, tmpobjreg);
         setTemp(1, tmpcopy);
     }
 
@@ -2282,16 +2472,17 @@ class LApplyArrayGeneric : public LCallI
 
 class LGetDynamicName : public LCallInstructionHelper<BOX_PIECES, 2, 3>
 {
   public:
     LIR_HEADER(GetDynamicName)
 
     LGetDynamicName(const LAllocation& envChain, const LAllocation& name,
                     const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, envChain);
         setOperand(1, name);
         setTemp(0, temp1);
         setTemp(1, temp2);
         setTemp(2, temp3);
     }
 
@@ -2319,16 +2510,17 @@ class LGetDynamicName : public LCallInst
 
 class LCallDirectEval : public LCallInstructionHelper<BOX_PIECES, 2 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallDirectEval)
 
     LCallDirectEval(const LAllocation& envChain, const LAllocation& string,
                     const LBoxAllocation& newTarget)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, envChain);
         setOperand(1, string);
         setBoxOperand(NewTarget, newTarget);
     }
 
     static const size_t NewTarget = 2;
 
@@ -2346,16 +2538,17 @@ class LCallDirectEval : public LCallInst
 
 // Takes in either an integer or boolean input and tests it for truthiness.
 class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0>
 {
   public:
     LIR_HEADER(TestIAndBranch)
 
     LTestIAndBranch(const LAllocation& in, MBasicBlock* ifTrue, MBasicBlock* ifFalse)
+      : LControlInstructionHelper(classOpcode)
     {
         setOperand(0, in);
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
     }
 
     MBasicBlock* ifTrue() const {
         return getSuccessor(0);
@@ -2367,16 +2560,17 @@ class LTestIAndBranch : public LControlI
 
 // Takes in an int64 input and tests it for truthiness.
 class LTestI64AndBranch : public LControlInstructionHelper<2, INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(TestI64AndBranch)
 
     LTestI64AndBranch(const LInt64Allocation& in, MBasicBlock* ifTrue, MBasicBlock* ifFalse)
+      : LControlInstructionHelper(classOpcode)
     {
         setInt64Operand(0, in);
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
     }
 
     MBasicBlock* ifTrue() const {
         return getSuccessor(0);
@@ -2388,16 +2582,17 @@ class LTestI64AndBranch : public LContro
 
 // Takes in either an integer or boolean input and tests it for truthiness.
 class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0>
 {
   public:
     LIR_HEADER(TestDAndBranch)
 
     LTestDAndBranch(const LAllocation& in, MBasicBlock* ifTrue, MBasicBlock* ifFalse)
+      : LControlInstructionHelper(classOpcode)
     {
         setOperand(0, in);
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
     }
 
     MBasicBlock* ifTrue() const {
         return getSuccessor(0);
@@ -2409,16 +2604,17 @@ class LTestDAndBranch : public LControlI
 
 // Takes in either an integer or boolean input and tests it for truthiness.
 class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0>
 {
   public:
     LIR_HEADER(TestFAndBranch)
 
     LTestFAndBranch(const LAllocation& in, MBasicBlock* ifTrue, MBasicBlock* ifFalse)
+      : LControlInstructionHelper(classOpcode)
     {
         setOperand(0, in);
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
     }
 
     MBasicBlock* ifTrue() const {
         return getSuccessor(0);
@@ -2432,16 +2628,17 @@ class LTestFAndBranch : public LControlI
 // emulates |undefined|; see js::EmulatesUndefined.
 class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1>
 {
   public:
     LIR_HEADER(TestOAndBranch)
 
     LTestOAndBranch(const LAllocation& input, MBasicBlock* ifTruthy, MBasicBlock* ifFalsy,
                     const LDefinition& temp)
+      : LControlInstructionHelper(classOpcode)
     {
         setOperand(0, input);
         setSuccessor(0, ifTruthy);
         setSuccessor(1, ifFalsy);
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
@@ -2463,16 +2660,17 @@ class LTestOAndBranch : public LControlI
 // Takes in a boxed value and tests it for truthiness.
 class LTestVAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 3>
 {
   public:
     LIR_HEADER(TestVAndBranch)
 
     LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LBoxAllocation& input,
                     const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2)
+      : LControlInstructionHelper(classOpcode)
     {
         setSuccessor(0, ifTruthy);
         setSuccessor(1, ifFalsy);
         setBoxOperand(Input, input);
         setTemp(0, temp0);
         setTemp(1, temp1);
         setTemp(2, temp2);
     }
@@ -2512,17 +2710,19 @@ class LTestVAndBranch : public LControlI
 class LFunctionDispatch : public LInstructionHelper<0, 1, 0>
 {
     // Dispatch is performed based on a function -> block map
     // stored in the MIR.
 
   public:
     LIR_HEADER(FunctionDispatch);
 
-    explicit LFunctionDispatch(const LAllocation& in) {
+    explicit LFunctionDispatch(const LAllocation& in)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
     }
 
     MFunctionDispatch* mir() const {
         return mir_->toFunctionDispatch();
     }
 };
 
@@ -2533,17 +2733,19 @@ class LObjectGroupDispatch : public LIns
 
   public:
     LIR_HEADER(ObjectGroupDispatch);
 
     const char* extraName() const {
         return mir()->hasFallback() ? "HasFallback" : "NoFallback";
     }
 
-    LObjectGroupDispatch(const LAllocation& in, const LDefinition& temp) {
+    LObjectGroupDispatch(const LAllocation& in, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
@@ -2556,17 +2758,18 @@ class LObjectGroupDispatch : public LIns
 // For objects, both operands are in registers.
 class LCompare : public LInstructionHelper<1, 2, 0>
 {
     JSOp jsop_;
 
   public:
     LIR_HEADER(Compare)
     LCompare(JSOp jsop, const LAllocation& left, const LAllocation& right)
-      : jsop_(jsop)
+      : LInstructionHelper(classOpcode),
+        jsop_(jsop)
     {
         setOperand(0, left);
         setOperand(1, right);
     }
 
     JSOp jsop() const {
         return jsop_;
     }
@@ -2590,17 +2793,18 @@ class LCompareI64 : public LInstructionH
 
   public:
     LIR_HEADER(CompareI64)
 
     static const size_t Lhs = 0;
     static const size_t Rhs = INT64_PIECES;
 
     LCompareI64(JSOp jsop, const LInt64Allocation& left, const LInt64Allocation& right)
-      : jsop_(jsop)
+      : LInstructionHelper(classOpcode),
+        jsop_(jsop)
     {
         setInt64Operand(Lhs, left);
         setInt64Operand(Rhs, right);
     }
 
     JSOp jsop() const {
         return jsop_;
     }
@@ -2621,17 +2825,19 @@ class LCompareI64AndBranch : public LCon
     LIR_HEADER(CompareI64AndBranch)
 
     static const size_t Lhs = 0;
     static const size_t Rhs = INT64_PIECES;
 
     LCompareI64AndBranch(MCompare* cmpMir, JSOp jsop,
                          const LInt64Allocation& left, const LInt64Allocation& right,
                          MBasicBlock* ifTrue, MBasicBlock* ifFalse)
-      : cmpMir_(cmpMir), jsop_(jsop)
+      : LControlInstructionHelper(classOpcode),
+        cmpMir_(cmpMir),
+        jsop_(jsop)
     {
         setInt64Operand(Lhs, left);
         setInt64Operand(Rhs, right);
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
     }
 
     JSOp jsop() const {
@@ -2661,17 +2867,19 @@ class LCompareAndBranch : public LContro
     MCompare* cmpMir_;
     JSOp jsop_;
 
   public:
     LIR_HEADER(CompareAndBranch)
     LCompareAndBranch(MCompare* cmpMir, JSOp jsop,
                       const LAllocation& left, const LAllocation& right,
                       MBasicBlock* ifTrue, MBasicBlock* ifFalse)
-      : cmpMir_(cmpMir), jsop_(jsop)
+      : LControlInstructionHelper(classOpcode),
+        cmpMir_(cmpMir),
+        jsop_(jsop)
     {
         setOperand(0, left);
         setOperand(1, right);
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
     }
 
     JSOp jsop() const {
@@ -2699,17 +2907,19 @@ class LCompareAndBranch : public LContro
         return CodeName[jsop_];
     }
 };
 
 class LCompareD : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(CompareD)
-    LCompareD(const LAllocation& left, const LAllocation& right) {
+    LCompareD(const LAllocation& left, const LAllocation& right)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, left);
         setOperand(1, right);
     }
 
     const LAllocation* left() {
         return getOperand(0);
     }
     const LAllocation* right() {
@@ -2719,17 +2929,20 @@ class LCompareD : public LInstructionHel
         return mir_->toCompare();
     }
 };
 
 class LCompareF : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(CompareF)
-    LCompareF(const LAllocation& left, const LAllocation& right) {
+
+    LCompareF(const LAllocation& left, const LAllocation& right)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, left);
         setOperand(1, right);
     }
 
     const LAllocation* left() {
         return getOperand(0);
     }
     const LAllocation* right() {
@@ -2741,19 +2954,21 @@ class LCompareF : public LInstructionHel
 };
 
 class LCompareDAndBranch : public LControlInstructionHelper<2, 2, 0>
 {
     MCompare* cmpMir_;
 
   public:
     LIR_HEADER(CompareDAndBranch)
+
     LCompareDAndBranch(MCompare* cmpMir, const LAllocation& left, const LAllocation& right,
                        MBasicBlock* ifTrue, MBasicBlock* ifFalse)
-      : cmpMir_(cmpMir)
+      : LControlInstructionHelper(classOpcode),
+        cmpMir_(cmpMir)
     {
         setOperand(0, left);
         setOperand(1, right);
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
     }
 
     MBasicBlock* ifTrue() const {
@@ -2779,17 +2994,18 @@ class LCompareDAndBranch : public LContr
 class LCompareFAndBranch : public LControlInstructionHelper<2, 2, 0>
 {
     MCompare* cmpMir_;
 
   public:
     LIR_HEADER(CompareFAndBranch)
     LCompareFAndBranch(MCompare* cmpMir, const LAllocation& left, const LAllocation& right,
                        MBasicBlock* ifTrue, MBasicBlock* ifFalse)
-      : cmpMir_(cmpMir)
+      : LControlInstructionHelper(classOpcode),
+        cmpMir_(cmpMir)
     {
         setOperand(0, left);
         setOperand(1, right);
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
     }
 
     MBasicBlock* ifTrue() const {
@@ -2811,17 +3027,20 @@ class LCompareFAndBranch : public LContr
         return cmpMir_;
     }
 };
 
 class LCompareS : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(CompareS)
-    LCompareS(const LAllocation& left, const LAllocation& right) {
+
+    LCompareS(const LAllocation& left, const LAllocation& right)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, left);
         setOperand(1, right);
     }
 
     const LAllocation* left() {
         return getOperand(0);
     }
     const LAllocation* right() {
@@ -2832,17 +3051,20 @@ class LCompareS : public LInstructionHel
     }
 };
 
 // strict-equality between value and string.
 class LCompareStrictS : public LInstructionHelper<1, BOX_PIECES + 1, 1>
 {
   public:
     LIR_HEADER(CompareStrictS)
-    LCompareStrictS(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
+
+    LCompareStrictS(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Lhs, lhs);
         setOperand(BOX_PIECES, rhs);
         setTemp(0, temp);
     }
 
     static const size_t Lhs = 0;
 
     const LAllocation* right() {
@@ -2859,17 +3081,19 @@ class LCompareStrictS : public LInstruct
 // Used for strict-equality comparisons where one side is a boolean
 // and the other is a value. Note that CompareI is used to compare
 // two booleans.
 class LCompareB : public LInstructionHelper<1, BOX_PIECES + 1, 0>
 {
   public:
     LIR_HEADER(CompareB)
 
-    LCompareB(const LBoxAllocation& lhs, const LAllocation& rhs) {
+    LCompareB(const LBoxAllocation& lhs, const LAllocation& rhs)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Lhs, lhs);
         setOperand(BOX_PIECES, rhs);
     }
 
     static const size_t Lhs = 0;
 
     const LAllocation* rhs() {
         return getOperand(BOX_PIECES);
@@ -2884,17 +3108,18 @@ class LCompareBAndBranch : public LContr
 {
     MCompare* cmpMir_;
 
   public:
     LIR_HEADER(CompareBAndBranch)
 
     LCompareBAndBranch(MCompare* cmpMir, const LBoxAllocation& lhs, const LAllocation& rhs,
                        MBasicBlock* ifTrue, MBasicBlock* ifFalse)
-      : cmpMir_(cmpMir)
+      : LControlInstructionHelper(classOpcode),
+        cmpMir_(cmpMir)
     {
         setBoxOperand(Lhs, lhs);
         setOperand(BOX_PIECES, rhs);
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
     }
 
     static const size_t Lhs = 0;
@@ -2920,17 +3145,19 @@ class LCompareBAndBranch : public LContr
 class LCompareBitwise : public LInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CompareBitwise)
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 
-    LCompareBitwise(const LBoxAllocation& lhs, const LBoxAllocation& rhs) {
+    LCompareBitwise(const LBoxAllocation& lhs, const LBoxAllocation& rhs)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(LhsInput, lhs);
         setBoxOperand(RhsInput, rhs);
     }
 
     MCompare* mir() const {
         return mir_->toCompare();
     }
 };
@@ -2942,17 +3169,18 @@ class LCompareBitwiseAndBranch : public 
   public:
     LIR_HEADER(CompareBitwiseAndBranch)
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 
     LCompareBitwiseAndBranch(MCompare* cmpMir, MBasicBlock* ifTrue, MBasicBlock* ifFalse,
                              const LBoxAllocation& lhs, const LBoxAllocation& rhs)
-      : cmpMir_(cmpMir)
+      : LControlInstructionHelper(classOpcode),
+        cmpMir_(cmpMir)
     {
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
         setBoxOperand(LhsInput, lhs);
         setBoxOperand(RhsInput, rhs);
     }
 
     MBasicBlock* ifTrue() const {
@@ -2972,34 +3200,37 @@ class LCompareBitwiseAndBranch : public 
 class LCompareVM : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CompareVM)
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 
-    LCompareVM(const LBoxAllocation& lhs, const LBoxAllocation& rhs) {
+    LCompareVM(const LBoxAllocation& lhs, const LBoxAllocation& rhs)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(LhsInput, lhs);
         setBoxOperand(RhsInput, rhs);
     }
 
     MCompare* mir() const {
         return mir_->toCompare();
     }
 };
 
 class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0>
 {
     Assembler::Condition cond_;
   public:
     LIR_HEADER(BitAndAndBranch)
     LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse,
                      Assembler::Condition cond = Assembler::NonZero)
-        : cond_(cond)
+      : LControlInstructionHelper(classOpcode),
+        cond_(cond)
     {
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
     }
 
     MBasicBlock* ifTrue() const {
         return getSuccessor(0);
     }
@@ -3023,16 +3254,17 @@ class LBitAndAndBranch : public LControl
 // flag on unwrapped objects.  See also js::EmulatesUndefined.
 class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, BOX_PIECES, 2>
 {
   public:
     LIR_HEADER(IsNullOrLikeUndefinedV)
 
     LIsNullOrLikeUndefinedV(const LBoxAllocation& value, const LDefinition& temp,
                             const LDefinition& tempToUnbox)
+      : LInstructionHelper(classOpcode)
     {
         setBoxOperand(Value, value);
         setTemp(0, temp);
         setTemp(1, tempToUnbox);
     }
 
     static const size_t Value = 0;
 
@@ -3052,16 +3284,17 @@ class LIsNullOrLikeUndefinedV : public L
 // Takes an object or object-or-null pointer and tests whether it is null or is
 // an object that emulates |undefined|, as above.
 class LIsNullOrLikeUndefinedT : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(IsNullOrLikeUndefinedT)
 
     explicit LIsNullOrLikeUndefinedT(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, input);
     }
 
     MCompare* mir() {
         return mir_->toCompare();
     }
 };
@@ -3071,17 +3304,18 @@ class LIsNullOrLikeUndefinedAndBranchV :
     MCompare* cmpMir_;
 
   public:
     LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)
 
     LIsNullOrLikeUndefinedAndBranchV(MCompare* cmpMir, MBasicBlock* ifTrue, MBasicBlock* ifFalse,
                                      const LBoxAllocation& value, const LDefinition& temp,
                                      const LDefinition& tempToUnbox)
-      : cmpMir_(cmpMir)
+      : LControlInstructionHelper(classOpcode),
+        cmpMir_(cmpMir)
     {
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
         setBoxOperand(Value, value);
         setTemp(0, temp);
         setTemp(1, tempToUnbox);
     }
 
@@ -3112,17 +3346,18 @@ class LIsNullOrLikeUndefinedAndBranchT :
     MCompare* cmpMir_;
 
   public:
     LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)
 
     LIsNullOrLikeUndefinedAndBranchT(MCompare* cmpMir, const LAllocation& input,
                                      MBasicBlock* ifTrue, MBasicBlock* ifFalse,
                                      const LDefinition& temp)
-      : cmpMir_(cmpMir)
+      : LControlInstructionHelper(classOpcode),
+        cmpMir_(cmpMir)
     {
         setOperand(0, input);
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
         setTemp(0, temp);
     }
 
     MBasicBlock* ifTrue() const {
@@ -3141,17 +3376,19 @@ class LIsNullOrLikeUndefinedAndBranchT :
         return getTemp(0);
     }
 };
 
 class LSameValueD : public LInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(SameValueD)
-    LSameValueD(const LAllocation& left, const LAllocation& right, const LDefinition& temp) {
+    LSameValueD(const LAllocation& left, const LAllocation& right, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, left);
         setOperand(1, right);
         setTemp(0, temp);
     }
 
     const LAllocation* left() {
         return getOperand(0);
     }
@@ -3167,16 +3404,17 @@ class LSameValueV : public LInstructionH
 {
   public:
     LIR_HEADER(SameValueV)
 
     static const size_t LhsInput = 0;
 
     LSameValueV(const LBoxAllocation& left, const LAllocation& right, const LDefinition& temp1,
                 const LDefinition& temp2)
+      : LInstructionHelper(classOpcode)
     {
         setBoxOperand(LhsInput, left);
         setOperand(BOX_PIECES, right);
         setTemp(0, temp1);
         setTemp(1, temp2);
     }
 
     const LAllocation* right() {
@@ -3193,81 +3431,92 @@ class LSameValueV : public LInstructionH
 class LSameValueVM : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(SameValueVM)
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 
-    LSameValueVM(const LBoxAllocation& left, const LBoxAllocation& right) {
+    LSameValueVM(const LBoxAllocation& left, const LBoxAllocation& right)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(LhsInput, left);
         setBoxOperand(RhsInput, right);
     }
 };
 
 // Not operation on an integer.
 class LNotI : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NotI)
 
-    explicit LNotI(const LAllocation& input) {
+    explicit LNotI(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 // Not operation on an int64.
 class LNotI64 : public LInstructionHelper<1, INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(NotI64)
 
-    explicit LNotI64(const LInt64Allocation& input) {
+    explicit LNotI64(const LInt64Allocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setInt64Operand(0, input);
     }
 };
 
 // Not operation on a double.
 class LNotD : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NotD)
 
-    explicit LNotD(const LAllocation& input) {
+    explicit LNotD(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 
     MNot* mir() {
         return mir_->toNot();
     }
 };
 
 // Not operation on a float32.
 class LNotF : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NotF)
 
-    explicit LNotF(const LAllocation& input) {
+    explicit LNotF(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 
     MNot* mir() {
         return mir_->toNot();
     }
 };
 
 // Boolean complement operation on an object.
 class LNotO : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NotO)
 
     explicit LNotO(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, input);
     }
 
     MNot* mir() {
         return mir_->toNot();
     }
 };
@@ -3276,16 +3525,17 @@ class LNotO : public LInstructionHelper<
 class LNotV : public LInstructionHelper<1, BOX_PIECES, 3>
 {
   public:
     LIR_HEADER(NotV)
 
     static const size_t Input = 0;
     LNotV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1,
           const LDefinition& temp2)
+      : LInstructionHelper(classOpcode)
     {
         setBoxOperand(Input, input);
         setTemp(0, temp0);
         setTemp(1, temp1);
         setTemp(2, temp2);
     }
 
     const LDefinition* tempFloat() {
@@ -3306,42 +3556,49 @@ class LNotV : public LInstructionHelper<
 };
 
 // Bitwise not operation, takes a 32-bit integer as input and returning
 // a 32-bit integer result as an output.
 class LBitNotI : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(BitNotI)
+
+    LBitNotI()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 // Call a VM function to perform a BITNOT operation.
 class LBitNotV : public LCallInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(BitNotV)
 
     static const size_t Input = 0;
 
-    explicit LBitNotV(const LBoxAllocation& input) {
+    explicit LBitNotV(const LBoxAllocation& input)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
     }
 };
 
 // Binary bitwise operation, taking two 32-bit integers as inputs and returning
 // a 32-bit integer result as an output.
 class LBitOpI : public LInstructionHelper<1, 2, 0>
 {
     JSOp op_;
 
   public:
     LIR_HEADER(BitOpI)
 
     explicit LBitOpI(JSOp op)
-      : op_(op)
+      : LInstructionHelper(classOpcode),
+        op_(op)
     { }
 
     const char* extraName() const {
         if (bitop() == JSOP_URSH && mir_->toUrsh()->bailoutsDisabled())
             return "ursh:BailoutsDisabled";
         return CodeName[op_];
     }
 
@@ -3356,17 +3613,18 @@ class LBitOpI64 : public LInstructionHel
 
   public:
     LIR_HEADER(BitOpI64)
 
     static const size_t Lhs = 0;
     static const size_t Rhs = INT64_PIECES;
 
     explicit LBitOpI64(JSOp op)
-      : op_(op)
+      : LInstructionHelper(classOpcode),
+        op_(op)
     { }
 
     const char* extraName() const {
         return CodeName[op_];
     }
 
     JSOp bitop() const {
         return op_;
@@ -3377,17 +3635,18 @@ class LBitOpI64 : public LInstructionHel
 class LBitOpV : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
     JSOp jsop_;
 
   public:
     LIR_HEADER(BitOpV)
 
     LBitOpV(JSOp jsop, const LBoxAllocation& lhs, const LBoxAllocation& rhs)
-      : jsop_(jsop)
+      : LCallInstructionHelper(classOpcode),
+        jsop_(jsop)
     {
         setBoxOperand(LhsInput, lhs);
         setBoxOperand(RhsInput, rhs);
     }
 
     JSOp jsop() const {
         return jsop_;
     }
@@ -3405,17 +3664,18 @@ class LBitOpV : public LCallInstructionH
 class LShiftI : public LBinaryMath<0>
 {
     JSOp op_;
 
   public:
     LIR_HEADER(ShiftI)
 
     explicit LShiftI(JSOp op)
-      : op_(op)
+      : LBinaryMath(classOpcode),
+        op_(op)
     { }
 
     JSOp bitop() {
         return op_;
     }
 
     MInstruction* mir() {
         return mir_->toInstruction();
@@ -3429,17 +3689,18 @@ class LShiftI : public LBinaryMath<0>
 class LShiftI64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES + 1, 0>
 {
     JSOp op_;
 
   public:
     LIR_HEADER(ShiftI64)
 
     explicit LShiftI64(JSOp op)
-      : op_(op)
+      : LInstructionHelper(classOpcode),
+        op_(op)
     { }
 
     static const size_t Lhs = 0;
     static const size_t Rhs = INT64_PIECES;
 
     JSOp bitop() {
         return op_;
     }
@@ -3455,79 +3716,93 @@ class LShiftI64 : public LInstructionHel
 
 // Sign extension
 class LSignExtendInt32 : public LInstructionHelper<1, 1, 0>
 {
     MSignExtendInt32::Mode mode_;
 
   public:
     LIR_HEADER(SignExtendInt32);
+
     explicit LSignExtendInt32(const LAllocation& num, MSignExtendInt32::Mode mode)
-      : mode_(mode)
+      : LInstructionHelper(classOpcode),
+        mode_(mode)
     {
         setOperand(0, num);
     }
 
     MSignExtendInt32::Mode mode() { return mode_; }
 };
 
 class LSignExtendInt64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(SignExtendInt64)
-    explicit LSignExtendInt64(const LInt64Allocation& input) {
+
+    explicit LSignExtendInt64(const LInt64Allocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setInt64Operand(0, input);
     }
 
     const MSignExtendInt64* mir() const {
         return mir_->toSignExtendInt64();
     }
 
     MSignExtendInt64::Mode mode() const { return mir()->mode(); }
 };
 
 class LUrshD : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(UrshD)
 
-    LUrshD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
+    LUrshD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
+      : LBinaryMath(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
     const LDefinition* temp() {
         return getTemp(0);
     }
 };
 
 // Returns from the function being compiled (not used in inlined frames). The
 // input must be a box.
 class LReturn : public LInstructionHelper<0, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(Return)
+
+    LReturn()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 class LThrow : public LCallInstructionHelper<0, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(Throw)
 
     static const size_t Value = 0;
 
-    explicit LThrow(const LBoxAllocation& value) {
+    explicit LThrow(const LBoxAllocation& value)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(Value, value);
     }
 };
 
 class LMinMaxBase : public LInstructionHelper<1, 2, 0>
 {
   protected:
-    LMinMaxBase(const LAllocation& first, const LAllocation& second)
+    LMinMaxBase(LNode::Opcode opcode, const LAllocation& first, const LAllocation& second)
+      : LInstructionHelper(opcode)
     {
         setOperand(0, first);
         setOperand(1, second);
     }
 
   public:
     const LAllocation* first() {
         return this->getOperand(0);
@@ -3545,174 +3820,203 @@ class LMinMaxBase : public LInstructionH
         return mir()->isMax() ? "Max" : "Min";
     }
 };
 
 class LMinMaxI : public LMinMaxBase
 {
   public:
     LIR_HEADER(MinMaxI)
-    LMinMaxI(const LAllocation& first, const LAllocation& second) : LMinMaxBase(first, second)
+    LMinMaxI(const LAllocation& first, const LAllocation& second)
+      : LMinMaxBase(classOpcode, first, second)
     {}
 };
 
 class LMinMaxD : public LMinMaxBase
 {
   public:
     LIR_HEADER(MinMaxD)
-    LMinMaxD(const LAllocation& first, const LAllocation& second) : LMinMaxBase(first, second)
+    LMinMaxD(const LAllocation& first, const LAllocation& second)
+      : LMinMaxBase(classOpcode, first, second)
     {}
 };
 
 class LMinMaxF : public LMinMaxBase
 {
   public:
     LIR_HEADER(MinMaxF)
-    LMinMaxF(const LAllocation& first, const LAllocation& second) : LMinMaxBase(first, second)
+    LMinMaxF(const LAllocation& first, const LAllocation& second)
+      : LMinMaxBase(classOpcode, first, second)
     {}
 };
 
 // Negative of an integer
 class LNegI : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NegI);
-    explicit LNegI(const LAllocation& num) {
+    explicit LNegI(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 // Negative of a double.
 class LNegD : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NegD)
-    explicit LNegD(const LAllocation& num) {
+    explicit LNegD(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 // Negative of a float32.
 class LNegF : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NegF)
-    explicit LNegF(const LAllocation& num) {
+    explicit LNegF(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 // Absolute value of an integer.
 class LAbsI : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(AbsI)
-    explicit LAbsI(const LAllocation& num) {
+    explicit LAbsI(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 // Absolute value of a double.
 class LAbsD : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(AbsD)
-    explicit LAbsD(const LAllocation& num) {
+    explicit LAbsD(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 // Absolute value of a float32.
 class LAbsF : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(AbsF)
-    explicit LAbsF(const LAllocation& num) {
+    explicit LAbsF(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 // Copysign for doubles.
 class LCopySignD : public LInstructionHelper<1, 2, 2>
 {
   public:
     LIR_HEADER(CopySignD)
-    explicit LCopySignD() {}
+    explicit LCopySignD()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 // Copysign for float32.
 class LCopySignF : public LInstructionHelper<1, 2, 2>
 {
   public:
     LIR_HEADER(CopySignF)
-    explicit LCopySignF() {}
+    explicit LCopySignF()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 // Count leading zeroes on an int32.
 class LClzI : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(ClzI)
-    explicit LClzI(const LAllocation& num) {
+    explicit LClzI(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 
     MClz* mir() const {
         return mir_->toClz();
     }
 };
 
 // Count leading zeroes on an int64.
 class LClzI64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(ClzI64)
-    explicit LClzI64(const LInt64Allocation& num) {
+    explicit LClzI64(const LInt64Allocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setInt64Operand(0, num);
     }
 
     MClz* mir() const {
         return mir_->toClz();
     }
 };
 
 // Count trailing zeroes on an int32.
 class LCtzI : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(CtzI)
-    explicit LCtzI(const LAllocation& num) {
+    explicit LCtzI(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 
     MCtz* mir() const {
         return mir_->toCtz();
     }
 };
 
 // Count trailing zeroes on an int64.
 class LCtzI64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(CtzI64)
-    explicit LCtzI64(const LInt64Allocation& num) {
+    explicit LCtzI64(const LInt64Allocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setInt64Operand(0, num);
     }
 
     MCtz* mir() const {
         return mir_->toCtz();
     }
 };
 
 // Count population on an int32.
 class LPopcntI : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(PopcntI)
-    explicit LPopcntI(const LAllocation& num, const LDefinition& temp) {
+    explicit LPopcntI(const LAllocation& num, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
         setTemp(0, temp);
     }
 
     MPopcnt* mir() const {
         return mir_->toPopcnt();
     }
 
@@ -3721,51 +4025,59 @@ class LPopcntI : public LInstructionHelp
     }
 };
 
 // Count population on an int64.
 class LPopcntI64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES, 1>
 {
   public:
     LIR_HEADER(PopcntI64)
-    explicit LPopcntI64(const LInt64Allocation& num, const LDefinition& temp) {
+    explicit LPopcntI64(const LInt64Allocation& num, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setInt64Operand(0, num);
         setTemp(0, temp);
     }
 
     MPopcnt* mir() const {
         return mir_->toPopcnt();
     }
 };
 
 // Square root of a double.
 class LSqrtD : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(SqrtD)
-    explicit LSqrtD(const LAllocation& num) {
+    explicit LSqrtD(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 // Square root of a float32.
 class LSqrtF : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(SqrtF)
-    explicit LSqrtF(const LAllocation& num) {
+    explicit LSqrtF(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 class LAtan2D : public LCallInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(Atan2D)
-    LAtan2D(const LAllocation& y, const LAllocation& x, const LDefinition& temp) {
+    LAtan2D(const LAllocation& y, const LAllocation& x, const LDefinition& temp)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, y);
         setOperand(1, x);
         setTemp(0, temp);
     }
 
     const LAllocation* y() {
         return getOperand(0);
     }
@@ -3784,34 +4096,37 @@ class LAtan2D : public LCallInstructionH
 };
 
 class LHypot : public LCallInstructionHelper<1, 4, 1>
 {
     uint32_t numOperands_;
   public:
     LIR_HEADER(Hypot)
     LHypot(const LAllocation& x, const LAllocation& y, const LDefinition& temp)
-      : numOperands_(2)
+      : LCallInstructionHelper(classOpcode),
+        numOperands_(2)
     {
         setOperand(0, x);
         setOperand(1, y);
         setTemp(0, temp);
     }
 
     LHypot(const LAllocation& x, const LAllocation& y, const LAllocation& z, const LDefinition& temp)
-      : numOperands_(3)
+      : LCallInstructionHelper(classOpcode),
+        numOperands_(3)
     {
         setOperand(0, x);
         setOperand(1, y);
         setOperand(2, z);
         setTemp(0, temp);
     }
 
     LHypot(const LAllocation& x, const LAllocation& y, const LAllocation& z, const LAllocation& w, const LDefinition& temp)
-      : numOperands_(4)
+      : LCallInstructionHelper(classOpcode),
+        numOperands_(4)
     {
         setOperand(0, x);
         setOperand(1, y);
         setOperand(2, z);
         setOperand(3, w);
         setTemp(0, temp);
     }
 
@@ -3834,17 +4149,19 @@ class LHypot : public LCallInstructionHe
     }
 };
 
 // Double raised to an integer power.
 class LPowI : public LCallInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(PowI)
-    LPowI(const LAllocation& value, const LAllocation& power, const LDefinition& temp) {
+    LPowI(const LAllocation& value, const LAllocation& power, const LDefinition& temp)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, value);
         setOperand(1, power);
         setTemp(0, temp);
     }
 
     const LAllocation* value() {
         return getOperand(0);
     }
@@ -3856,17 +4173,19 @@ class LPowI : public LCallInstructionHel
     }
 };
 
 // Double raised to a double power.
 class LPowD : public LCallInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(PowD)
-    LPowD(const LAllocation& value, const LAllocation& power, const LDefinition& temp) {
+    LPowD(const LAllocation& value, const LAllocation& power, const LDefinition& temp)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, value);
         setOperand(1, power);
         setTemp(0, temp);
     }
 
     const LAllocation* value() {
         return getOperand(0);
     }
@@ -3878,30 +4197,34 @@ class LPowD : public LCallInstructionHel
     }
 };
 
 class LPowV : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(PowV)
 
-    LPowV(const LBoxAllocation& value, const LBoxAllocation& power) {
+    LPowV(const LBoxAllocation& value, const LBoxAllocation& power)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(ValueInput, value);
         setBoxOperand(PowerInput, power);
     }
 
     static const size_t ValueInput = 0;
     static const size_t PowerInput = BOX_PIECES;
 };
 
 class LMathFunctionD : public LCallInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(MathFunctionD)
-    LMathFunctionD(const LAllocation& input, const LDefinition& temp) {
+    LMathFunctionD(const LAllocation& input, const LDefinition& temp)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
     MMathFunction* mir() const {
@@ -3911,17 +4234,19 @@ class LMathFunctionD : public LCallInstr
         return MMathFunction::FunctionName(mir()->function());
     }
 };
 
 class LMathFunctionF : public LCallInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(MathFunctionF)
-    LMathFunctionF(const LAllocation& input, const LDefinition& temp) {
+    LMathFunctionF(const LAllocation& input, const LDefinition& temp)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
     MMathFunction* mir() const {
@@ -3936,17 +4261,18 @@ class LMathFunctionF : public LCallInstr
 class LAddI : public LBinaryMath<0>
 {
     bool recoversInput_;
 
   public:
     LIR_HEADER(AddI)
 
     LAddI()
-      : recoversInput_(false)
+      : LBinaryMath(classOpcode),
+        recoversInput_(false)
     { }
 
     const char* extraName() const {
         return snapshot() ? "OverflowCheck" : nullptr;
     }
 
     bool recoversInput() const {
         return recoversInput_;
@@ -3960,30 +4286,35 @@ class LAddI : public LBinaryMath<0>
     }
 };
 
 class LAddI64 : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(AddI64)
 
+    LAddI64()
+      : LInstructionHelper(classOpcode)
+    {}
+
     static const size_t Lhs = 0;
     static const size_t Rhs = INT64_PIECES;
 };
 
 // Subtracts two integers, returning an integer value.
 class LSubI : public LBinaryMath<0>
 {
     bool recoversInput_;
 
   public:
     LIR_HEADER(SubI)
 
     LSubI()
-      : recoversInput_(false)
+      : LBinaryMath(classOpcode),
+        recoversInput_(false)
     { }
 
     const char* extraName() const {
         return snapshot() ? "OverflowCheck" : nullptr;
     }
 
     bool recoversInput() const {
         return recoversInput_;
@@ -4011,24 +4342,29 @@ LNode::recoversInput() const
 
 class LSubI64 : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(SubI64)
 
     static const size_t Lhs = 0;
     static const size_t Rhs = INT64_PIECES;
+
+    LSubI64()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 class LMulI64 : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 1>
 {
   public:
     LIR_HEADER(MulI64)
 
     explicit LMulI64()
+      : LInstructionHelper(classOpcode)
     {
         setTemp(0, LDefinition());
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
@@ -4040,17 +4376,18 @@ class LMulI64 : public LInstructionHelpe
 class LMathD : public LBinaryMath<0>
 {
     JSOp jsop_;
 
   public:
     LIR_HEADER(MathD)
 
     explicit LMathD(JSOp jsop)
-      : jsop_(jsop)
+      : LBinaryMath(classOpcode),
+        jsop_(jsop)
     { }
 
     JSOp jsop() const {
         return jsop_;
     }
 
     const char* extraName() const {
         return CodeName[jsop_];
@@ -4061,34 +4398,37 @@ class LMathD : public LBinaryMath<0>
 class LMathF: public LBinaryMath<0>
 {
     JSOp jsop_;
 
   public:
     LIR_HEADER(MathF)
 
     explicit LMathF(JSOp jsop)
-      : jsop_(jsop)
+      : LBinaryMath(classOpcode),
+        jsop_(jsop)
     { }
 
     JSOp jsop() const {
         return jsop_;
     }
 
     const char* extraName() const {
         return CodeName[jsop_];
     }
 };
 
 class LModD : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(ModD)
 
-    LModD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
+    LModD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
+      : LBinaryMath(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
         setIsCall();
     }
     const LDefinition* temp() {
         return getTemp(0);
     }
@@ -4101,17 +4441,18 @@ class LModD : public LBinaryMath<1>
 class LBinaryV : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
     JSOp jsop_;
 
   public:
     LIR_HEADER(BinaryV)
 
     LBinaryV(JSOp jsop, const LBoxAllocation& lhs, const LBoxAllocation& rhs)
-      : jsop_(jsop)
+      : LCallInstructionHelper(classOpcode),
+        jsop_(jsop)
     {
         setBoxOperand(LhsInput, lhs);
         setBoxOperand(RhsInput, rhs);
     }
 
     JSOp jsop() const {
         return jsop_;
     }
@@ -4128,16 +4469,17 @@ class LBinaryV : public LCallInstruction
 class LConcat : public LInstructionHelper<1, 2, 5>
 {
   public:
     LIR_HEADER(Concat)
 
     LConcat(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp1,
             const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4,
             const LDefinition& temp5)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp1);
         setTemp(1, temp2);
         setTemp(2, temp3);
         setTemp(3, temp4);
         setTemp(4, temp5);
@@ -4167,17 +4509,19 @@ class LConcat : public LInstructionHelpe
 };
 
 // Get uint16 character code from a string.
 class LCharCodeAt : public LInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(CharCodeAt)
 
-    LCharCodeAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp) {
+    LCharCodeAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, str);
         setOperand(1, index);
         setTemp(0, temp);
     }
 
     const LAllocation* str() {
         return this->getOperand(0);
     }
@@ -4190,33 +4534,36 @@ class LCharCodeAt : public LInstructionH
 };
 
 // Convert uint16 character code to a string.
 class LFromCharCode : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(FromCharCode)
 
-    explicit LFromCharCode(const LAllocation& code) {
+    explicit LFromCharCode(const LAllocation& code)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, code);
     }
 
     const LAllocation* code() {
         return this->getOperand(0);
     }
 };
 
 // Convert uint32 code point to a string.
 class LFromCodePoint : public LInstructionHelper<1, 1, 2>
 {
   public:
     LIR_HEADER(FromCodePoint)
 
     explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp1,
                             const LDefinition& temp2)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, codePoint);
         setTemp(0, temp1);
         setTemp(1, temp2);
     }
 
     const LAllocation* codePoint() {
         return this->getOperand(0);
@@ -4233,16 +4580,17 @@ class LFromCodePoint : public LInstructi
 
 // Calls the ToLowerCase or ToUpperCase case conversion function.
 class LStringConvertCase : public LCallInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(StringConvertCase)
 
     explicit LStringConvertCase(const LAllocation& string)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, string);
     }
 
     const MStringConvertCase* mir() const {
         return mir_->toStringConvertCase();
     }
 
@@ -4253,16 +4601,17 @@ class LStringConvertCase : public LCallI
 
 // Calculates sincos(x) and returns two values (sin/cos).
 class LSinCos : public LCallInstructionHelper<2, 1, 2>
 {
   public:
     LIR_HEADER(SinCos)
 
     LSinCos(const LAllocation &input, const LDefinition &temp, const LDefinition &temp2)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, input);
         setTemp(0, temp);
         setTemp(1, temp2);
     }
     const LAllocation *input() {
         return getOperand(0);
     }
@@ -4283,17 +4632,19 @@ class LSinCos : public LCallInstructionH
     }
 };
 
 class LStringSplit : public LCallInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(StringSplit)
 
-    LStringSplit(const LAllocation& string, const LAllocation& separator) {
+    LStringSplit(const LAllocation& string, const LAllocation& separator)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, string);
         setOperand(1, separator);
     }
     const LAllocation* string() {
         return getOperand(0);
     }
     const LAllocation* separator() {
         return getOperand(1);
@@ -4305,16 +4656,17 @@ class LStringSplit : public LCallInstruc
 
 class LSubstr : public LInstructionHelper<1, 3, 3>
 {
   public:
     LIR_HEADER(Substr)
 
     LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length,
             const LDefinition& temp, const LDefinition& temp2, const LDefinition& temp3)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, string);
         setOperand(1, begin);
         setOperand(2, length);
         setTemp(0, temp);
         setTemp(1, temp2);
         setTemp(2, temp3);
     }
@@ -4342,78 +4694,90 @@ class LSubstr : public LInstructionHelpe
 };
 
 // Convert a 32-bit integer to a double.
 class LInt32ToDouble : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(Int32ToDouble)
 
-    explicit LInt32ToDouble(const LAllocation& input) {
+    explicit LInt32ToDouble(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 // Convert a 32-bit float to a double.
 class LFloat32ToDouble : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(Float32ToDouble)
 
-    explicit LFloat32ToDouble(const LAllocation& input) {
+    explicit LFloat32ToDouble(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 // Convert a double to a 32-bit float.
 class LDoubleToFloat32 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(DoubleToFloat32)
 
-    explicit LDoubleToFloat32(const LAllocation& input) {
+    explicit LDoubleToFloat32(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 // Convert a 32-bit integer to a float32.
 class LInt32ToFloat32 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(Int32ToFloat32)
 
-    explicit LInt32ToFloat32(const LAllocation& input) {
+    explicit LInt32ToFloat32(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 // Convert a value to a double.
 class LValueToDouble : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(ValueToDouble)
     static const size_t Input = 0;
 
-    explicit LValueToDouble(const LBoxAllocation& input) {
+    explicit LValueToDouble(const LBoxAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
     }
 
     MToDouble* mir() {
         return mir_->toToDouble();
     }
 };
 
 // Convert a value to a float32.
 class LValueToFloat32 : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(ValueToFloat32)
     static const size_t Input = 0;
 
-    explicit LValueToFloat32(const LBoxAllocation& input) {
+    explicit LValueToFloat32(const LBoxAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
     }
 
     MToFloat32* mir() {
         return mir_->toToFloat32();
     }
 };
 
@@ -4435,17 +4799,18 @@ class LValueToInt32 : public LInstructio
   private:
     Mode mode_;
 
   public:
     LIR_HEADER(ValueToInt32)
 
     LValueToInt32(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1,
                   Mode mode)
-      : mode_(mode)
+      : LInstructionHelper(classOpcode),
+        mode_(mode)
     {
         setBoxOperand(Input, input);
         setTemp(0, temp0);
         setTemp(1, temp1);
     }
 
     const char* extraName() const {
         return mode() == NORMAL ? "Normal" : "Truncate";
@@ -4479,17 +4844,19 @@ class LValueToInt32 : public LInstructio
 //   Input: floating-point register
 //   Output: 32-bit integer
 //   Bailout: if the double cannot be converted to an integer.
 class LDoubleToInt32 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(DoubleToInt32)
 
-    explicit LDoubleToInt32(const LAllocation& in) {
+    explicit LDoubleToInt32(const LAllocation& in)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
     }
 
     MToNumberInt32* mir() const {
         return mir_->toToNumberInt32();
     }
 };
 
@@ -4497,34 +4864,38 @@ class LDoubleToInt32 : public LInstructi
 //   Input: floating-point register
 //   Output: 32-bit integer
 //   Bailout: if the float32 cannot be converted to an integer.
 class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(Float32ToInt32)
 
-    explicit LFloat32ToInt32(const LAllocation& in) {
+    explicit LFloat32ToInt32(const LAllocation& in)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
     }
 
     MToNumberInt32* mir() const {
         return mir_->toToNumberInt32();
     }
 };
 
 // Convert a double to a truncated int32.
 //   Input: floating-point register
 //   Output: 32-bit integer
 class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(TruncateDToInt32)
 
-    LTruncateDToInt32(const LAllocation& in, const LDefinition& temp) {
+    LTruncateDToInt32(const LAllocation& in, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
         setTemp(0, temp);
     }
 
     const LDefinition* tempFloat() {
         return getTemp(0);
     }
 
@@ -4536,17 +4907,19 @@ class LTruncateDToInt32 : public LInstru
 // Convert a float32 to a truncated int32.
 //   Input: floating-point register
 //   Output: 32-bit integer
 class LTruncateFToInt32 : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(TruncateFToInt32)
 
-    LTruncateFToInt32(const LAllocation& in, const LDefinition& temp) {
+    LTruncateFToInt32(const LAllocation& in, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
         setTemp(0, temp);
     }
 
     const LDefinition* tempFloat() {
         return getTemp(0);
     }
 
@@ -4555,92 +4928,104 @@ class LTruncateFToInt32 : public LInstru
     }
 };
 
 class LWasmTruncateToInt32 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(WasmTruncateToInt32)
 
-    explicit LWasmTruncateToInt32(const LAllocation& in) {
+    explicit LWasmTruncateToInt32(const LAllocation& in)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
     }
 
     MWasmTruncateToInt32* mir() const {
         return mir_->toWasmTruncateToInt32();
     }
 };
 
 class LWrapInt64ToInt32 : public LInstructionHelper<1, INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(WrapInt64ToInt32)
 
     static const size_t Input = 0;
 
-    explicit LWrapInt64ToInt32(const LInt64Allocation& input) {
+    explicit LWrapInt64ToInt32(const LInt64Allocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setInt64Operand(Input, input);
     }
 
     const MWrapInt64ToInt32* mir() {
         return mir_->toWrapInt64ToInt32();
     }
 };
 
 class LExtendInt32ToInt64 : public LInstructionHelper<INT64_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(ExtendInt32ToInt64)
 
-    explicit LExtendInt32ToInt64(const LAllocation& input) {
+    explicit LExtendInt32ToInt64(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 
     const MExtendInt32ToInt64* mir() {
         return mir_->toExtendInt32ToInt64();
     }
 };
 
 // Convert a boolean value to a string.
 class LBooleanToString : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(BooleanToString)
 
-    explicit LBooleanToString(const LAllocation& input) {
+    explicit LBooleanToString(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 
     const MToString* mir() {
         return mir_->toToString();
     }
 };
 
 // Convert an integer hosted on one definition to a string with a function call.
 class LIntToString : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(IntToString)
 
-    explicit LIntToString(const LAllocation& input) {
+    explicit LIntToString(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 
     const MToString* mir() {
         return mir_->toToString();
     }
 };
 
 // Convert a double hosted on one definition to a string with a function call.
 class LDoubleToString : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(DoubleToString)
 
-    LDoubleToString(const LAllocation& input, const LDefinition& temp) {
+    LDoubleToString(const LAllocation& input, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
         setTemp(0, temp);
     }
 
     const LDefinition* tempInt() {
         return getTemp(0);
     }
     const MToString* mir() {
@@ -4650,16 +5035,17 @@ class LDoubleToString : public LInstruct
 
 // Convert a primitive to a string with a function call.
 class LValueToString : public LInstructionHelper<1, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(ValueToString)
 
     LValueToString(const LBoxAllocation& input, const LDefinition& tempToUnbox)
+      : LInstructionHelper(classOpcode)
     {
         setBoxOperand(Input, input);
         setTemp(0, tempToUnbox);
     }
 
     static const size_t Input = 0;
 
     const MToString* mir() {
@@ -4672,54 +5058,62 @@ class LValueToString : public LInstructi
 };
 
 // Convert a value to an object.
 class LValueToObject : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(ValueToObject)
 
-    explicit LValueToObject(const LBoxAllocation& input) {
+    explicit LValueToObject(const LBoxAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
     }
 
     static const size_t Input = 0;
 };
 
 // Convert a value to an object or null pointer.
 class LValueToObjectOrNull : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(ValueToObjectOrNull)
 
-    explicit LValueToObjectOrNull(const LBoxAllocation& input) {
+    explicit LValueToObjectOrNull(const LBoxAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
     }
 
     static const size_t Input = 0;
 
     const MToObjectOrNull* mir() {
         return mir_->toToObjectOrNull();
     }
 };
 
 class LInt32x4ToFloat32x4 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(Int32x4ToFloat32x4);
-    explicit LInt32x4ToFloat32x4(const LAllocation& input) {
+    explicit LInt32x4ToFloat32x4(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 class LFloat32x4ToInt32x4 : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(Float32x4ToInt32x4);
-    explicit LFloat32x4ToInt32x4(const LAllocation& input, const LDefinition& temp) {
+    explicit LFloat32x4ToInt32x4(const LAllocation& input, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
         setTemp(0, temp);
     }
     const LDefinition* temp() {
         return getTemp(0);
     }
     const MSimdConvert* mir() const {
         return mir_->toSimdConvert();
@@ -4728,16 +5122,17 @@ class LFloat32x4ToInt32x4 : public LInst
 
 // Float32x4 to Uint32x4 needs one GPR temp and one FloatReg temp.
 class LFloat32x4ToUint32x4 : public LInstructionHelper<1, 1, 2>
 {
   public:
     LIR_HEADER(Float32x4ToUint32x4);
     explicit LFloat32x4ToUint32x4(const LAllocation& input, const LDefinition& tempR,
                                   const LDefinition& tempF)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, input);
         setTemp(0, tempR);
         setTemp(1, tempF);
     }
     const LDefinition* tempR() {
         return getTemp(0);
     }
@@ -4749,17 +5144,19 @@ class LFloat32x4ToUint32x4 : public LIns
     }
 };
 
 // Double raised to a half power.
 class LPowHalfD : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(PowHalfD);
-    explicit LPowHalfD(const LAllocation& input) {
+    explicit LPowHalfD(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 
     const LAllocation* input() {
         return getOperand(0);
     }
     const LDefinition* output() {
         return getDef(0);
@@ -4771,24 +5168,30 @@ class LPowHalfD : public LInstructionHel
 
 // No-op instruction that is used to hold the entry snapshot. This simplifies
 // register allocation as it doesn't need to sniff the snapshot out of the
 // LIRGraph.
 class LStart : public LInstructionHelper<0, 0, 0>
 {
   public:
     LIR_HEADER(Start)
+
+    LStart()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 class LNaNToZero : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(NaNToZero)
 
-    explicit LNaNToZero(const LAllocation& input, const LDefinition& tempDouble) {
+    explicit LNaNToZero(const LAllocation& input, const LDefinition& tempDouble)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
         setTemp(0, tempDouble);
     }
 
     const MNaNToZero* mir() {
         return mir_->toNaNToZero();
     }
     const LAllocation* input() {
@@ -4809,17 +5212,18 @@ class LOsrEntry : public LInstructionHel
   protected:
     Label label_;
     uint32_t frameDepth_;
 
   public:
     LIR_HEADER(OsrEntry)
 
     explicit LOsrEntry(const LDefinition& temp)
-      : frameDepth_(0)
+      : LInstructionHelper(classOpcode),
+        frameDepth_(0)
     {
         setTemp(0, temp);
     }
 
     void setFrameDepth(uint32_t depth) {
         frameDepth_ = depth;
     }
     uint32_t getFrameDepth() {
@@ -4835,79 +5239,85 @@ class LOsrEntry : public LInstructionHel
 
 // Materialize a Value stored in an interpreter frame for OSR.
 class LOsrValue : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(OsrValue)
 
     explicit LOsrValue(const LAllocation& entry)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, entry);
     }
 
     const MOsrValue* mir() {
         return mir_->toOsrValue();
     }
 };
 
 // Materialize a JSObject env chain stored in an interpreter frame for OSR.
 class LOsrEnvironmentChain : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(OsrEnvironmentChain)
 
     explicit LOsrEnvironmentChain(const LAllocation& entry)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, entry);
     }
 
     const MOsrEnvironmentChain* mir() {
         return mir_->toOsrEnvironmentChain();
     }
 };
 
 // Materialize a JSObject env chain stored in an interpreter frame for OSR.
 class LOsrReturnValue : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(OsrReturnValue)
 
     explicit LOsrReturnValue(const LAllocation& entry)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, entry);
     }
 
     const MOsrReturnValue* mir() {
         return mir_->toOsrReturnValue();
     }
 };
 
 // Materialize a JSObject ArgumentsObject stored in an interpreter frame for OSR.
 class LOsrArgumentsObject : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(OsrArgumentsObject)
 
     explicit LOsrArgumentsObject(const LAllocation& entry)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, entry);
     }
 
     const MOsrArgumentsObject* mir() {
         return mir_->toOsrArgumentsObject();
     }
 };
 
 class LRegExp : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(RegExp)
 
-    explicit LRegExp(const LDefinition& temp) {
+    explicit LRegExp(const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, temp);
     }
     const LDefinition* temp() {
         return getTemp(0);
     }
     const MRegExp* mir() const {
         return mir_->toRegExp();
     }
@@ -4915,16 +5325,17 @@ class LRegExp : public LInstructionHelpe
 
 class LRegExpMatcher : public LCallInstructionHelper<BOX_PIECES, 3, 0>
 {
   public:
     LIR_HEADER(RegExpMatcher)
 
     LRegExpMatcher(const LAllocation& regexp, const LAllocation& string,
                    const LAllocation& lastIndex)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, regexp);
         setOperand(1, string);
         setOperand(2, lastIndex);
     }
 
     const LAllocation* regexp() {
         return getOperand(0);
@@ -4943,16 +5354,17 @@ class LRegExpMatcher : public LCallInstr
 
 class LRegExpSearcher : public LCallInstructionHelper<1, 3, 0>
 {
   public:
     LIR_HEADER(RegExpSearcher)
 
     LRegExpSearcher(const LAllocation& regexp, const LAllocation& string,
                     const LAllocation& lastIndex)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, regexp);
         setOperand(1, string);
         setOperand(2, lastIndex);
     }
 
     const LAllocation* regexp() {
         return getOperand(0);
@@ -4971,16 +5383,17 @@ class LRegExpSearcher : public LCallInst
 
 class LRegExpTester : public LCallInstructionHelper<1, 3, 0>
 {
   public:
     LIR_HEADER(RegExpTester)
 
     LRegExpTester(const LAllocation& regexp, const LAllocation& string,
                   const LAllocation& lastIndex)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, regexp);
         setOperand(1, string);
         setOperand(2, lastIndex);
     }
 
     const LAllocation* regexp() {
         return getOperand(0);
@@ -4996,17 +5409,19 @@ class LRegExpTester : public LCallInstru
         return mir_->toRegExpTester();
     }
 };
 
 class LRegExpPrototypeOptimizable : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(RegExpPrototypeOptimizable);
-    explicit LRegExpPrototypeOptimizable(const LAllocation& object, const LDefinition& temp) {
+    LRegExpPrototypeOptimizable(const LAllocation& object, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setTemp(0, temp);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
     const LDefinition* temp() {
@@ -5016,18 +5431,20 @@ class LRegExpPrototypeOptimizable : publ
         return mir_->toRegExpPrototypeOptimizable();
     }
 };
 
 class LRegExpInstanceOptimizable : public LInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(RegExpInstanceOptimizable);
-    explicit LRegExpInstanceOptimizable(const LAllocation& object, const LAllocation& proto,
-                                        const LDefinition& temp) {
+    LRegExpInstanceOptimizable(const LAllocation& object, const LAllocation& proto,
+                               const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setOperand(1, proto);
         setTemp(0, temp);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
@@ -5041,18 +5458,20 @@ class LRegExpInstanceOptimizable : publi
         return mir_->toRegExpInstanceOptimizable();
     }
 };
 
 class LGetFirstDollarIndex : public LInstructionHelper<1, 1, 3>
 {
   public:
     LIR_HEADER(GetFirstDollarIndex);
-    explicit LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0,
-                                  const LDefinition& temp1, const LDefinition& temp2) {
+    LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0,
+                         const LDefinition& temp1, const LDefinition& temp2)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, str);
         setTemp(0, temp0);
         setTemp(1, temp1);
         setTemp(2, temp2);
     }
 
     const LAllocation* str() {
         return getOperand(0);
@@ -5070,16 +5489,17 @@ class LGetFirstDollarIndex : public LIns
 
 class LStringReplace: public LCallInstructionHelper<1, 3, 0>
 {
   public:
     LIR_HEADER(StringReplace);
 
     LStringReplace(const LAllocation& string, const LAllocation& pattern,
                    const LAllocation& replacement)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, string);
         setOperand(1, pattern);
         setOperand(2, replacement);
     }
 
     const MStringReplace* mir() const {
         return mir_->toStringReplace();
@@ -5096,17 +5516,19 @@ class LStringReplace: public LCallInstru
     }
 };
 
 class LBinarySharedStub : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(BinarySharedStub)
 
-    LBinarySharedStub(const LBoxAllocation& lhs, const LBoxAllocation& rhs) {
+    LBinarySharedStub(const LBoxAllocation& lhs, const LBoxAllocation& rhs)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(LhsInput, lhs);
         setBoxOperand(RhsInput, rhs);
     }
 
     const MBinarySharedStub* mir() const {
         return mir_->toBinarySharedStub();
     }
 
@@ -5114,17 +5536,19 @@ class LBinarySharedStub : public LCallIn
     static const size_t RhsInput = BOX_PIECES;
 };
 
 class LUnarySharedStub : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(UnarySharedStub)
 
-    explicit LUnarySharedStub(const LBoxAllocation& input) {
+    explicit LUnarySharedStub(const LBoxAllocation& input)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
     }
 
     const MUnarySharedStub* mir() const {
         return mir_->toUnarySharedStub();
     }
 
     static const size_t Input = 0;
@@ -5133,51 +5557,62 @@ class LUnarySharedStub : public LCallIns
 class LNullarySharedStub : public LCallInstructionHelper<BOX_PIECES, 0, 0>
 {
   public:
     LIR_HEADER(NullarySharedStub)
 
     const MNullarySharedStub* mir() const {
         return mir_->toNullarySharedStub();
     }
+
+    LNullarySharedStub()
+      : LCallInstructionHelper(classOpcode)
+    {}
 };
 
 class LClassConstructor : public LCallInstructionHelper<1, 0, 0>
 {
   public:
     LIR_HEADER(ClassConstructor)
 
     const MClassConstructor* mir() const {
         return mir_->toClassConstructor();
     }
+
+    LClassConstructor()
+      : LCallInstructionHelper(classOpcode)
+    {}
 };
 
 class LLambdaForSingleton : public LCallInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(LambdaForSingleton)
 
     explicit LLambdaForSingleton(const LAllocation& envChain)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, envChain);
     }
     const LAllocation* environmentChain() {
         return getOperand(0);
     }
     const MLambda* mir() const {
         return mir_->toLambda();
     }
 };
 
 class LLambda : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(Lambda)
 
-    LLambda(const LAllocation& envChain, const LDefinition& temp) {
+    LLambda(const LAllocation& envChain, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, envChain);
         setTemp(0, temp);
     }
     const LAllocation* environmentChain() {
         return getOperand(0);
     }
     const LDefinition* temp() {
         return getTemp(0);
@@ -5189,17 +5624,19 @@ class LLambda : public LInstructionHelpe
 
 class LLambdaArrow : public LInstructionHelper<1, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(LambdaArrow)
 
     static const size_t NewTargetValue = 1;
 
-    LLambdaArrow(const LAllocation& envChain, const LBoxAllocation& newTarget) {
+    LLambdaArrow(const LAllocation& envChain, const LBoxAllocation& newTarget)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, envChain);
         setBoxOperand(NewTargetValue, newTarget);
     }
     const LAllocation* environmentChain() {
         return getOperand(0);
     }
     const MLambdaArrow* mir() const {
         return mir_->toLambdaArrow();
@@ -5208,68 +5645,76 @@ class LLambdaArrow : public LInstruction
 
 class LSetFunName : public LCallInstructionHelper<1, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(SetFunName)
 
     static const size_t NameValue = 1;
 
-    LSetFunName(const LAllocation& fun, const LBoxAllocation& name) {
+    LSetFunName(const LAllocation& fun, const LBoxAllocation& name)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, fun);
         setBoxOperand(NameValue, name);
     }
     const LAllocation* fun() {
         return getOperand(0);
     }
     const MSetFunName* mir() const {
         return mir_->toSetFunName();
     }
 };
 
 class LKeepAliveObject : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(KeepAliveObject)
 
-    explicit LKeepAliveObject(const LAllocation& object) {
+    explicit LKeepAliveObject(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
 };
 
 // Load the "slots" member out of a JSObject.
 //   Input: JSObject pointer
 //   Output: slots pointer
 class LSlots : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(Slots)
 
-    explicit LSlots(const LAllocation& object) {
+    explicit LSlots(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
 };
 
 // Load the "elements" member out of a JSObject.
 //   Input: JSObject pointer
 //   Output: elements pointer
 class LElements : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(Elements)
 
-    explicit LElements(const LAllocation& object) {
+    explicit LElements(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
 
     const MElements* mir() const {
@@ -5278,34 +5723,38 @@ class LElements : public LInstructionHel
 };
 
 // If necessary, convert any int32 elements in a vector into doubles.
 class LConvertElementsToDoubles : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(ConvertElementsToDoubles)
 
-    explicit LConvertElementsToDoubles(const LAllocation& elements) {
+    explicit LConvertElementsToDoubles(const LAllocation& elements)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
     }
 
     const LAllocation* elements() {
         return getOperand(0);
     }
 };
 
 // If |elements| has the CONVERT_DOUBLE_ELEMENTS flag, convert int32 value to
 // double. Else return the original value.
 class LMaybeToDoubleElement : public LInstructionHelper<BOX_PIECES, 2, 1>
 {
   public:
     LIR_HEADER(MaybeToDoubleElement)
 
     LMaybeToDoubleElement(const LAllocation& elements, const LAllocation& value,
-                          const LDefinition& tempFloat) {
+                          const LDefinition& tempFloat)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, value);
         setTemp(0, tempFloat);
     }
 
     const LAllocation* elements() {
         return getOperand(0);
     }
@@ -5318,17 +5767,19 @@ class LMaybeToDoubleElement : public LIn
 };
 
 // If necessary, copy the elements in an object so they may be written to.
 class LMaybeCopyElementsForWrite : public LInstructionHelper<0, 1, 1>
 {
   public:
     LIR_HEADER(MaybeCopyElementsForWrite)
 
-    explicit LMaybeCopyElementsForWrite(const LAllocation& obj, const LDefinition& temp) {
+    explicit LMaybeCopyElementsForWrite(const LAllocation& obj, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setTemp(0, temp);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
 
@@ -5342,33 +5793,37 @@ class LMaybeCopyElementsForWrite : publi
 };
 
 // Load the initialized length from an elements header.
 class LInitializedLength : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(InitializedLength)
 
-    explicit LInitializedLength(const LAllocation& elements) {
+    explicit LInitializedLength(const LAllocation& elements)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
     }
 
     const LAllocation* elements() {
         return getOperand(0);
     }
 };
 
 // Store to the initialized length in an elements header. Note the input is an
 // *index*, one less than the desired initialized length.
 class LSetInitializedLength : public LInstructionHelper<0, 2, 0>
 {
   public:
     LIR_HEADER(SetInitializedLength)
 
-    LSetInitializedLength(const LAllocation& elements, const LAllocation& index) {
+    LSetInitializedLength(const LAllocation& elements, const LAllocation& index)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
     }
 
     const LAllocation* elements() {
         return getOperand(0);
     }
     const LAllocation* index() {
@@ -5377,33 +5832,37 @@ class LSetInitializedLength : public LIn
 };
 
 // Load the length from an elements header.
 class LArrayLength : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(ArrayLength)
 
-    explicit LArrayLength(const LAllocation& elements) {
+    explicit LArrayLength(const LAllocation& elements)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
     }
 
     const LAllocation* elements() {
         return getOperand(0);
     }
 };
 
 // Store to the length in an elements header. Note the input is an *index*,
 // one less than the desired length.
 class LSetArrayLength : public LInstructionHelper<0, 2, 0>
 {
   public:
     LIR_HEADER(SetArrayLength)
 
-    LSetArrayLength(const LAllocation& elements, const LAllocation& index) {
+    LSetArrayLength(const LAllocation& elements, const LAllocation& index)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
     }
 
     const LAllocation* elements() {
         return getOperand(0);
     }
     const LAllocation* index() {
@@ -5414,16 +5873,17 @@ class LSetArrayLength : public LInstruct
 class LGetNextEntryForIterator : public LInstructionHelper<1, 2, 3>
 {
   public:
     LIR_HEADER(GetNextEntryForIterator)
 
     explicit LGetNextEntryForIterator(const LAllocation& iter, const LAllocation& result,
                                       const LDefinition& temp0, const LDefinition& temp1,
                                       const LDefinition& temp2)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, iter);
         setOperand(1, result);
         setTemp(0, temp0);
         setTemp(1, temp1);
         setTemp(2, temp2);
     }
 
@@ -5448,32 +5908,36 @@ class LGetNextEntryForIterator : public 
 };
 
 // Read the length of a typed array.
 class LTypedArrayLength : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(TypedArrayLength)
 
-    explicit LTypedArrayLength(const LAllocation& obj) {
+    explicit LTypedArrayLength(const LAllocation& obj)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
 };
 
 // Load a typed array's elements vector.
 class LTypedArrayElements : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(TypedArrayElements)
 
-    explicit LTypedArrayElements(const LAllocation& object) {
+    explicit LTypedArrayElements(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
 };
 
 // Assign
@@ -5484,16 +5948,17 @@ class LTypedArrayElements : public LInst
 // memory.
 class LSetDisjointTypedElements : public LCallInstructionHelper<0, 3, 1>
 {
   public:
     LIR_HEADER(SetDisjointTypedElements)
 
     explicit LSetDisjointTypedElements(const LAllocation& target, const LAllocation& targetOffset,
                                        const LAllocation& source, const LDefinition& temp)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, target);
         setOperand(1, targetOffset);
         setOperand(2, source);
         setTemp(0, temp);
     }
 
     const LAllocation* target() {
@@ -5514,31 +5979,35 @@ class LSetDisjointTypedElements : public
 };
 
 // Load a typed object's descriptor.
 class LTypedObjectDescr : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(TypedObjectDescr)
 
-    explicit LTypedObjectDescr(const LAllocation& object) {
+    explicit LTypedObjectDescr(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
 };
 
 // Load a typed object's elements vector.
 class LTypedObjectElements : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(TypedObjectElements)
 
-    explicit LTypedObjectElements(const LAllocation& object) {
+    explicit LTypedObjectElements(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
     const MTypedObjectElements* mir() const {
         return mir_->toTypedObjectElements();
     }
@@ -5549,16 +6018,17 @@ class LSetTypedObjectOffset : public LIn
 {
   public:
     LIR_HEADER(SetTypedObjectOffset)
 
     LSetTypedObjectOffset(const LAllocation& object,
                           const LAllocation& offset,
                           const LDefinition& temp0,
                           const LDefinition& temp1)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, object);
         setOperand(1, offset);
         setTemp(0, temp0);
         setTemp(1, temp1);
     }
     const LAllocation* object() {
         return getOperand(0);
@@ -5575,17 +6045,19 @@ class LSetTypedObjectOffset : public LIn
 };
 
 // Bailout if index >= length.
 class LBoundsCheck : public LInstructionHelper<0, 2, 0>
 {
   public:
     LIR_HEADER(BoundsCheck)
 
-    LBoundsCheck(const LAllocation& index, const LAllocation& length) {
+    LBoundsCheck(const LAllocation& index, const LAllocation& length)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, index);
         setOperand(1, length);
     }
     const MBoundsCheck* mir() const {
         return mir_->toBoundsCheck();
     }
     const LAllocation* index() {
         return getOperand(0);
@@ -5598,16 +6070,17 @@ class LBoundsCheck : public LInstruction
 // Bailout if index + minimum < 0 or index + maximum >= length.
 class LBoundsCheckRange : public LInstructionHelper<0, 2, 1>
 {
   public:
     LIR_HEADER(BoundsCheckRange)
 
     LBoundsCheckRange(const LAllocation& index, const LAllocation& length,
                       const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, index);
         setOperand(1, length);
         setTemp(0, temp);
     }
     const MBoundsCheck* mir() const {
         return mir_->toBoundsCheck();
     }
@@ -5621,33 +6094,36 @@ class LBoundsCheckRange : public LInstru
 
 // Bailout if index < minimum.
 class LBoundsCheckLower : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(BoundsCheckLower)
 
     explicit LBoundsCheckLower(const LAllocation& index)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, index);
     }
     MBoundsCheckLower* mir() const {
         return mir_->toBoundsCheckLower();
     }
     const LAllocation* index() {
         return getOperand(0);
     }
 };
 
 class LSpectreMaskIndex : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(SpectreMaskIndex)
 
-    LSpectreMaskIndex(const LAllocation& index, const LAllocation& length) {
+    LSpectreMaskIndex(const LAllocation& index, const LAllocation& length)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, index);
         setOperand(1, length);
     }
     const LAllocation* index() {
         return getOperand(0);
     }
     const LAllocation* length() {
         return getOperand(1);
@@ -5655,17 +6131,19 @@ class LSpectreMaskIndex : public LInstru
 };
 
 // Load a value from a dense array's elements vector. Bail out if it's the hole value.
 class LLoadElementV : public LInstructionHelper<BOX_PIECES, 2, 0>
 {
   public:
     LIR_HEADER(LoadElementV)
 
-    LLoadElementV(const LAllocation& elements, const LAllocation& index) {
+    LLoadElementV(const LAllocation& elements, const LAllocation& index)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
     }
 
     const char* extraName() const {
         return mir()->needsHoleCheck() ? "HoleCheck" : nullptr;
     }
 
@@ -5682,16 +6160,17 @@ class LLoadElementV : public LInstructio
 
 class LInArray : public LInstructionHelper<1, 4, 0>
 {
   public:
     LIR_HEADER(InArray)
 
     LInArray(const LAllocation& elements, const LAllocation& index,
              const LAllocation& initLength, const LAllocation& object)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, initLength);
         setOperand(3, object);
     }
     const MInArray* mir() const {
         return mir_->toInArray();
@@ -5713,17 +6192,19 @@ class LInArray : public LInstructionHelp
 
 // Load a value from an array's elements vector, loading |undefined| if we hit a hole.
 // Bail out if we get a negative index.
 class LLoadElementHole : public LInstructionHelper<BOX_PIECES, 3, 0>
 {
   public:
     LIR_HEADER(LoadElementHole)
 
-    LLoadElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) {
+    LLoadElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, initLength);
     }
 
     const char* extraName() const {
         return mir()->needsHoleCheck() ? "HoleCheck" : nullptr;
     }
@@ -5746,17 +6227,19 @@ class LLoadElementHole : public LInstruc
 // known to be packed, so that we don't have to check for the hole value.
 // This instruction does not load the type tag and can directly load into a
 // FP register.
 class LLoadElementT : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(LoadElementT)
 
-    LLoadElementT(const LAllocation& elements, const LAllocation& index) {
+    LLoadElementT(const LAllocation& elements, const LAllocation& index)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
     }
 
     const char* extraName() const {
         return mir()->needsHoleCheck() ? "HoleCheck"
                                        : (mir()->loadDoubles() ? "Doubles" : nullptr);
     }
@@ -5772,17 +6255,19 @@ class LLoadElementT : public LInstructio
     }
 };
 
 class LLoadUnboxedPointerV : public LInstructionHelper<BOX_PIECES, 2, 0>
 {
   public:
     LIR_HEADER(LoadUnboxedPointerV)
 
-    LLoadUnboxedPointerV(const LAllocation& elements, const LAllocation& index) {
+    LLoadUnboxedPointerV(const LAllocation& elements, const LAllocation& index)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
     }
 
     const MLoadUnboxedObjectOrNull* mir() const {
         return mir_->toLoadUnboxedObjectOrNull();
     }
     const LAllocation* elements() {
@@ -5793,17 +6278,19 @@ class LLoadUnboxedPointerV : public LIns
     }
 };
 
 class LLoadUnboxedPointerT : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(LoadUnboxedPointerT)
 
-    LLoadUnboxedPointerT(const LAllocation& elements, const LAllocation& index) {
+    LLoadUnboxedPointerT(const LAllocation& elements, const LAllocation& index)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
     }
 
     MDefinition* mir() {
         MOZ_ASSERT(mir_->isLoadUnboxedObjectOrNull() || mir_->isLoadUnboxedString());
         return mir_;
     }
@@ -5816,16 +6303,17 @@ class LLoadUnboxedPointerT : public LIns
 };
 
 class LUnboxObjectOrNull : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(UnboxObjectOrNull);
 
     explicit LUnboxObjectOrNull(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, input);
     }
 
     MUnbox* mir() const {
         return mir_->toUnbox();
     }
     const LAllocation* input() {
@@ -5841,19 +6329,19 @@ class LUnboxObjectOrNull : public LInstr
 // Each element is represented with BOX_PIECES allocations, even if 1 (typed
 // register) or 0 (constants) is enough. In such case, the unused allocations
 // would be bogus.
 class LLoadElementFromStateV : public LVariadicInstruction<BOX_PIECES, 3>
 {
   public:
     LIR_HEADER(LoadElementFromStateV)
 
-    LLoadElementFromStateV(const LDefinition& temp0, const LDefinition& temp1,
-                           const LDefinition& tempD, uint32_t numOperands)
-      : LVariadicInstruction<BOX_PIECES, 3>(numOperands)
+    LLoadElementFromStateV(uint32_t numOperands, const LDefinition& temp0,
+                           const LDefinition& temp1, const LDefinition& tempD)
+      : LVariadicInstruction<BOX_PIECES, 3>(classOpcode, numOperands)
     {
         setTemp(0, temp0);
         setTemp(1, temp1);
         setTemp(2, tempD);
     }
 
     const MLoadElementFromState* mir() const {
         return mir_->toLoadElementFromState();
@@ -5877,17 +6365,19 @@ class LLoadElementFromStateV : public LV
 
 // Store a boxed value to a dense array's element vector.
 class LStoreElementV : public LInstructionHelper<0, 2 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(StoreElementV)
 
     LStoreElementV(const LAllocation& elements, const LAllocation& index,
-                   const LBoxAllocation& value) {
+                   const LBoxAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
         setBoxOperand(Value, value);
     }
 
     const char* extraName() const {
         return mir()->needsHoleCheck() ? "HoleCheck" : nullptr;
     }
@@ -5909,17 +6399,19 @@ class LStoreElementV : public LInstructi
 // LStoreElementV, this instruction can store doubles and constants directly,
 // and does not store the type tag if the array is monomorphic and known to
 // be packed.
 class LStoreElementT : public LInstructionHelper<0, 3, 0>
 {
   public:
     LIR_HEADER(StoreElementT)
 
-    LStoreElementT(const LAllocation& elements, const LAllocation& index, const LAllocation& value) {
+    LStoreElementT(const LAllocation& elements, const LAllocation& index, const LAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, value);
     }
 
     const char* extraName() const {
         return mir()->needsHoleCheck() ? "HoleCheck" : nullptr;
     }
@@ -5940,17 +6432,19 @@ class LStoreElementT : public LInstructi
 
 // Like LStoreElementV, but supports indexes >= initialized length.
 class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(StoreElementHoleV)
 
     LStoreElementHoleV(const LAllocation& object, const LAllocation& elements,
-                       const LAllocation& index, const LBoxAllocation& value) {
+                       const LAllocation& index, const LBoxAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setOperand(1, elements);
         setOperand(2, index);
         setBoxOperand(Value, value);
     }
 
     static const size_t Value = 3;
 
@@ -5970,17 +6464,19 @@ class LStoreElementHoleV : public LInstr
 
 // Like LStoreElementT, but supports indexes >= initialized length.
 class LStoreElementHoleT : public LInstructionHelper<0, 4, 0>
 {
   public:
     LIR_HEADER(StoreElementHoleT)
 
     LStoreElementHoleT(const LAllocation& object, const LAllocation& elements,
-                       const LAllocation& index, const LAllocation& value) {
+                       const LAllocation& index, const LAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setOperand(1, elements);
         setOperand(2, index);
         setOperand(3, value);
     }
 
     const MStoreElementHole* mir() const {
         return mir_->toStoreElementHole();
@@ -6001,17 +6497,19 @@ class LStoreElementHoleT : public LInstr
 
 // Like LStoreElementV, but can just ignore assignment (for eg. frozen objects)
 class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(FallibleStoreElementV)
 
     LFallibleStoreElementV(const LAllocation& object, const LAllocation& elements,
-                           const LAllocation& index, const LBoxAllocation& value) {
+                           const LAllocation& index, const LBoxAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setOperand(1, elements);
         setOperand(2, index);
         setBoxOperand(Value, value);
     }
 
     static const size_t Value = 3;
 
@@ -6031,17 +6529,19 @@ class LFallibleStoreElementV : public LI
 
 // Like LStoreElementT, but can just ignore assignment (for eg. frozen objects)
 class LFallibleStoreElementT : public LInstructionHelper<0, 4, 0>
 {
   public:
     LIR_HEADER(FallibleStoreElementT)
 
     LFallibleStoreElementT(const LAllocation& object, const LAllocation& elements,
-                           const LAllocation& index, const LAllocation& value) {
+                           const LAllocation& index, const LAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setOperand(1, elements);
         setOperand(2, index);
         setOperand(3, value);
     }
 
     const MFallibleStoreElement* mir() const {
         return mir_->toFallibleStoreElement();
@@ -6060,17 +6560,19 @@ class LFallibleStoreElementT : public LI
     }
 };
 
 class LStoreUnboxedPointer : public LInstructionHelper<0, 3, 0>
 {
   public:
     LIR_HEADER(StoreUnboxedPointer)
 
-    LStoreUnboxedPointer(LAllocation elements, LAllocation index, LAllocation value) {
+    LStoreUnboxedPointer(LAllocation elements, LAllocation index, LAllocation value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, value);
     }
 
     MDefinition* mir() {
         MOZ_ASSERT(mir_->isStoreUnboxedObjectOrNull() || mir_->isStoreUnboxedString());
         return mir_;
@@ -6089,31 +6591,35 @@ class LStoreUnboxedPointer : public LIns
 
 // If necessary, convert an unboxed object in a particular group to its native
 // representation.
 class LConvertUnboxedObjectToNative : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(ConvertUnboxedObjectToNative)
 
-    explicit LConvertUnboxedObjectToNative(const LAllocation& object) {
+    explicit LConvertUnboxedObjectToNative(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
 
     MConvertUnboxedObjectToNative* mir() {
         return mir_->toConvertUnboxedObjectToNative();
     }
 };
 
 class LArrayPopShiftV : public LInstructionHelper<BOX_PIECES, 1, 2>
 {
   public:
     LIR_HEADER(ArrayPopShiftV)
 
-    LArrayPopShiftV(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1) {
+    LArrayPopShiftV(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setTemp(0, temp0);
         setTemp(1, temp1);
     }
 
     const char* extraName() const {
         return mir()->mode() == MArrayPopShift::Pop ? "Pop" : "Shift";
     }
@@ -6132,17 +6638,19 @@ class LArrayPopShiftV : public LInstruct
     }
 };
 
 class LArrayPopShiftT : public LInstructionHelper<1, 1, 2>
 {
   public:
     LIR_HEADER(ArrayPopShiftT)
 
-    LArrayPopShiftT(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1) {
+    LArrayPopShiftT(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setTemp(0, temp0);
         setTemp(1, temp1);
     }
 
     const char* extraName() const {
         return mir()->mode() == MArrayPopShift::Pop ? "Pop" : "Shift";
     }
@@ -6161,17 +6669,19 @@ class LArrayPopShiftT : public LInstruct
     }
 };
 
 class LArrayPushV : public LInstructionHelper<1, 1 + BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(ArrayPushV)
 
-    LArrayPushV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp) {
+    LArrayPushV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setBoxOperand(Value, value);
         setTemp(0, temp);
     }
 
     static const size_t Value = 1;
 
     const MArrayPush* mir() const {
@@ -6185,17 +6695,19 @@ class LArrayPushV : public LInstructionH
     }
 };
 
 class LArrayPushT : public LInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(ArrayPushT)
 
-    LArrayPushT(const LAllocation& object, const LAllocation& value, const LDefinition& temp) {
+    LArrayPushT(const LAllocation& object, const LAllocation& value, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setOperand(1, value);
         setTemp(0, temp);
     }
 
     const MArrayPush* mir() const {
         return mir_->toArrayPush();
     }
@@ -6211,17 +6723,19 @@ class LArrayPushT : public LInstructionH
 };
 
 class LArraySlice : public LCallInstructionHelper<1, 3, 2>
 {
   public:
     LIR_HEADER(ArraySlice)
 
     LArraySlice(const LAllocation& obj, const LAllocation& begin, const LAllocation& end,
-                const LDefinition& temp1, const LDefinition& temp2) {
+                const LDefinition& temp1, const LDefinition& temp2)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setOperand(1, begin);
         setOperand(2, end);
         setTemp(0, temp1);
         setTemp(1, temp2);
     }
     const MArraySlice* mir() const {
         return mir_->toArraySlice();
@@ -6245,16 +6759,17 @@ class LArraySlice : public LCallInstruct
 
 class LArrayJoin : public LCallInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(ArrayJoin)
 
     LArrayJoin(const LAllocation& array, const LAllocation& sep,
                const LDefinition& temp)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, array);
         setOperand(1, sep);
         setTemp(0, temp);
     }
 
     const MArrayJoin* mir() const {
         return mir_->toArrayJoin();
@@ -6274,17 +6789,19 @@ class LArrayJoin : public LCallInstructi
 };
 
 class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 1>
 {
   public:
     LIR_HEADER(LoadUnboxedScalar)
 
     LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index,
-                       const LDefinition& temp) {
+                       const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
         setTemp(0, temp);
     }
     const MLoadUnboxedScalar* mir() const {
         return mir_->toLoadUnboxedScalar();
     }
     const LAllocation* elements() {
@@ -6299,17 +6816,19 @@ class LLoadUnboxedScalar : public LInstr
 };
 
 class LLoadTypedArrayElementHole : public LInstructionHelper<BOX_PIECES, 2, 1>
 {
   public:
     LIR_HEADER(LoadTypedArrayElementHole)
 
     LLoadTypedArrayElementHole(const LAllocation& object, const LAllocation& index,
-                               const LDefinition& temp) {
+                               const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setOperand(1, index);
         setTemp(0, temp);
     }
     const MLoadTypedArrayElementHole* mir() const {
         return mir_->toLoadTypedArrayElementHole();
     }
     const LAllocation* object() {
@@ -6322,34 +6841,38 @@ class LLoadTypedArrayElementHole : publi
         return getTemp(0);
     }
 };
 
 class LLoadTypedArrayElementStatic : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(LoadTypedArrayElementStatic);
-    explicit LLoadTypedArrayElementStatic(const LAllocation& ptr) {
+    explicit LLoadTypedArrayElementStatic(const LAllocation& ptr)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, ptr);
     }
     MLoadTypedArrayElementStatic* mir() const {
         return mir_->toLoadTypedArrayElementStatic();
     }
     const LAllocation* ptr() {
         return getOperand(0);
     }
 };
 
 class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 0>
 {
   public:
     LIR_HEADER(StoreUnboxedScalar)
 
     LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index,
-                        const LAllocation& value) {
+                        const LAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, value);
     }
 
     const MStoreUnboxedScalar* mir() const {
         return mir_->toStoreUnboxedScalar();
     }
@@ -6366,16 +6889,17 @@ class LStoreUnboxedScalar : public LInst
 
 class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 0>
 {
   public:
     LIR_HEADER(StoreTypedArrayElementHole)
 
     LStoreTypedArrayElementHole(const LAllocation& elements, const LAllocation& length,
                                 const LAllocation& index, const LAllocation& value)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, elements);
         setOperand(1, length);
         setOperand(2, index);
         setOperand(3, value);
     }
 
     const MStoreTypedArrayElementHole* mir() const {
@@ -6394,17 +6918,19 @@ class LStoreTypedArrayElementHole : publ
         return getOperand(3);
     }
 };
 
 class LStoreTypedArrayElementStatic : public LInstructionHelper<0, 2, 0>
 {
   public:
     LIR_HEADER(StoreTypedArrayElementStatic);
-    LStoreTypedArrayElementStatic(const LAllocation& ptr, const LAllocation& value) {
+    LStoreTypedArrayElementStatic(const LAllocation& ptr, const LAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, ptr);
         setOperand(1, value);
     }
     MStoreTypedArrayElementStatic* mir() const {
         return mir_->toStoreTypedArrayElementStatic();
     }
     const LAllocation* ptr() {
         return getOperand(0);
@@ -6414,45 +6940,49 @@ class LStoreTypedArrayElementStatic : pu
     }
 };
 
 class LAtomicIsLockFree : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(AtomicIsLockFree)
 
-    explicit LAtomicIsLockFree(const LAllocation& value) {
+    explicit LAtomicIsLockFree(const LAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, value);
     }
     const LAllocation* value() {
         return getOperand(0);
     }
 };
 
 class LCompareExchangeTypedArrayElement : public LInstructionHelper<1, 4, 4>
 {
   public:
     LIR_HEADER(CompareExchangeTypedArrayElement)
 
     // ARM, ARM64, x86, x64
     LCompareExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index,
                                       const LAllocation& oldval, const LAllocation& newval,
                                       const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, oldval);
         setOperand(3, newval);
         setTemp(0, temp);
     }
     // MIPS32, MIPS64
     LCompareExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index,
                                       const LAllocation& oldval, const LAllocation& newval,
                                       const LDefinition& temp, const LDefinition& valueTemp,
                                       const LDefinition& offsetTemp, const LDefinition& maskTemp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, oldval);
         setOperand(3, newval);
         setTemp(0, temp);
         setTemp(1, valueTemp);
         setTemp(2, offsetTemp);
@@ -6494,27 +7024,29 @@ class LCompareExchangeTypedArrayElement 
 class LAtomicExchangeTypedArrayElement : public LInstructionHelper<1, 3, 4>
 {
   public:
     LIR_HEADER(AtomicExchangeTypedArrayElement)
 
     // ARM, ARM64, x86, x64
     LAtomicExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index,
                                      const LAllocation& value, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, value);
         setTemp(0, temp);
     }
     // MIPS32, MIPS64
     LAtomicExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index,
                                      const LAllocation& value, const LDefinition& temp,
                                      const LDefinition& valueTemp, const LDefinition& offsetTemp,
                                      const LDefinition& maskTemp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, value);
         setTemp(0, temp);
         setTemp(1, valueTemp);
         setTemp(2, offsetTemp);
         setTemp(3, maskTemp);
@@ -6555,28 +7087,30 @@ class LAtomicTypedArrayElementBinop : pu
     LIR_HEADER(AtomicTypedArrayElementBinop)
 
     static const int32_t valueOp = 2;
 
     // ARM, ARM64, x86, x64
     LAtomicTypedArrayElementBinop(const LAllocation& elements, const LAllocation& index,
                                   const LAllocation& value, const LDefinition& temp1,
                                   const LDefinition& temp2)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, value);
         setTemp(0, temp1);
         setTemp(1, temp2);
     }
     // MIPS32, MIPS64
     LAtomicTypedArrayElementBinop(const LAllocation& elements, const LAllocation& index,
                                   const LAllocation& value, const LDefinition& temp2,
                                   const LDefinition& valueTemp, const LDefinition& offsetTemp,
                                   const LDefinition& maskTemp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, value);
         setTemp(0, LDefinition::BogusTemp());
         setTemp(1, temp2);
         setTemp(2, valueTemp);
         setTemp(3, offsetTemp);
@@ -6621,26 +7155,28 @@ class LAtomicTypedArrayElementBinopForEf
 {
   public:
     LIR_HEADER(AtomicTypedArrayElementBinopForEffect)
 
     // ARM, ARM64, x86, x64
     LAtomicTypedArrayElementBinopForEffect(const LAllocation& elements, const LAllocation& index,
                                            const LAllocation& value,
                                            const LDefinition& flagTemp = LDefinition::BogusTemp())
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, value);
         setTemp(0, flagTemp);
     }
     // MIPS32, MIPS64
     LAtomicTypedArrayElementBinopForEffect(const LAllocation& elements, const LAllocation& index,
                                            const LAllocation& value, const LDefinition& valueTemp,
                                            const LDefinition& offsetTemp, const LDefinition& maskTemp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, elements);
         setOperand(1, index);
         setOperand(2, value);
         setTemp(0, LDefinition::BogusTemp());
         setTemp(1, valueTemp);
         setTemp(2, offsetTemp);
         setTemp(3, maskTemp);
@@ -6676,17 +7212,19 @@ class LAtomicTypedArrayElementBinopForEf
     }
 };
 
 class LEffectiveAddress : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(EffectiveAddress);
 
-    LEffectiveAddress(const LAllocation& base, const LAllocation& index) {
+    LEffectiveAddress(const LAllocation& base, const LAllocation& index)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, base);
         setOperand(1, index);
     }
     const MEffectiveAddress* mir() const {
         return mir_->toEffectiveAddress();
     }
     const LAllocation* base() {
         return getOperand(0);
@@ -6696,38 +7234,44 @@ class LEffectiveAddress : public LInstru
     }
 };
 
 class LClampIToUint8 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(ClampIToUint8)
 
-    explicit LClampIToUint8(const LAllocation& in) {
+    explicit LClampIToUint8(const LAllocation& in)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
     }
 };
 
 class LClampDToUint8 : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(ClampDToUint8)
 
-    LClampDToUint8(const LAllocation& in, const LDefinition& temp) {
+    LClampDToUint8(const LAllocation& in, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
         setTemp(0, temp);
     }
 };
 
 class LClampVToUint8 : public LInstructionHelper<1, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(ClampVToUint8)
 
-    LClampVToUint8(const LBoxAllocation& input, const LDefinition& tempFloat) {
+    LClampVToUint8(const LBoxAllocation& input, const LDefinition& tempFloat)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
         setTemp(0, tempFloat);
     }
 
     static const size_t Input = 0;
 
     const LDefinition* tempFloat() {
         return getTemp(0);
@@ -6738,59 +7282,67 @@ class LClampVToUint8 : public LInstructi
 };
 
 // Load a boxed value from an object's fixed slot.
 class LLoadFixedSlotV : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(LoadFixedSlotV)
 
-    explicit LLoadFixedSlotV(const LAllocation& object) {
+    explicit LLoadFixedSlotV(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
     const MLoadFixedSlot* mir() const {
         return mir_->toLoadFixedSlot();
     }
 };
 
 // Load a typed value from an object's fixed slot.
 class LLoadFixedSlotT : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(LoadFixedSlotT)
 
-    explicit LLoadFixedSlotT(const LAllocation& object) {
+    explicit LLoadFixedSlotT(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
     const MLoadFixedSlot* mir() const {
         return mir_->toLoadFixedSlot();
     }
 };
 
 class LLoadFixedSlotAndUnbox : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(LoadFixedSlotAndUnbox)
 
-    explicit LLoadFixedSlotAndUnbox(const LAllocation& object) {
+    explicit LLoadFixedSlotAndUnbox(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
 
     const MLoadFixedSlotAndUnbox* mir() const {
         return mir_->toLoadFixedSlotAndUnbox();
     }
 };
 
 // Store a boxed value to an object's fixed slot.
 class LStoreFixedSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(StoreFixedSlotV)
 
-    LStoreFixedSlotV(const LAllocation& obj, const LBoxAllocation& value) {
+    LStoreFixedSlotV(const LAllocation& obj, const LBoxAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setBoxOperand(Value, value);
     }
 
     static const size_t Value = 1;
 
     const MStoreFixedSlot* mir() const {
         return mir_->toStoreFixedSlot();
@@ -6802,16 +7354,17 @@ class LStoreFixedSlotV : public LInstruc
 
 // Store a typed value to an object's fixed slot.
 class LStoreFixedSlotT : public LInstructionHelper<0, 2, 0>
 {
   public:
     LIR_HEADER(StoreFixedSlotT)
 
     LStoreFixedSlotT(const LAllocation& obj, const LAllocation& value)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, obj);
         setOperand(1, value);
     }
     const MStoreFixedSlot* mir() const {
         return mir_->toStoreFixedSlot();
     }
     const LAllocation* obj() {
@@ -6823,17 +7376,19 @@ class LStoreFixedSlotT : public LInstruc
 };
 
 // Note, Name ICs always return a Value. There are no V/T variants.
 class LGetNameCache : public LInstructionHelper<BOX_PIECES, 1, 1>
 {
   public:
     LIR_HEADER(GetNameCache)
 
-    LGetNameCache(const LAllocation& envObj, const LDefinition& temp) {
+    LGetNameCache(const LAllocation& envObj, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, envObj);
         setTemp(0, temp);
     }
     const LAllocation* envObj() {
         return getOperand(0);
     }
     const LDefinition* temp() {
         return getTemp(0);
@@ -6846,28 +7401,34 @@ class LGetNameCache : public LInstructio
 class LCallGetIntrinsicValue : public LCallInstructionHelper<BOX_PIECES, 0, 0>
 {
   public:
     LIR_HEADER(CallGetIntrinsicValue)
 
     const MCallGetIntrinsicValue* mir() const {
         return mir_->toCallGetIntrinsicValue();
     }
+
+    LCallGetIntrinsicValue()
+      : LCallInstructionHelper(classOpcode)
+    {}
 };
 
 class LGetPropSuperCacheV : public LInstructionHelper<BOX_PIECES, 1 + 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(GetPropSuperCacheV)
 
     static const size_t Receiver = 1;
     static const size_t Id = Receiver + BOX_PIECES;
 
     LGetPropSuperCacheV(const LAllocation& obj, const LBoxAllocation& receiver,
-                        const LBoxAllocation& id) {
+                        const LBoxAllocation& id)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setBoxOperand(Receiver, receiver);
         setBoxOperand(Id, id);
     }
     const LAllocation* obj() {
         return getOperand(0);
     }
     const MGetPropSuperCache* mir() const {
@@ -6881,17 +7442,19 @@ class LGetPropertyCacheV : public LInstr
 {
   public:
     LIR_HEADER(GetPropertyCacheV)
 
     static const size_t Value = 0;
     static const size_t Id = BOX_PIECES;
 
     LGetPropertyCacheV(const LBoxAllocation& value, const LBoxAllocation& id,
-                       const LDefinition& temp) {
+                       const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Value, value);
         setBoxOperand(Id, id);
         setTemp(0, temp);
     }
     const MGetPropertyCache* mir() const {
         return mir_->toGetPropertyCache();
     }
     const LDefinition* temp() {
@@ -6905,17 +7468,19 @@ class LGetPropertyCacheT : public LInstr
 {
   public:
     LIR_HEADER(GetPropertyCacheT)
 
     static const size_t Value = 0;
     static const size_t Id = BOX_PIECES;
 
     LGetPropertyCacheT(const LBoxAllocation& value, const LBoxAllocation& id,
-                       const LDefinition& temp) {
+                       const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Value, value);
         setBoxOperand(Id, id);
         setTemp(0, temp);
     }
     const MGetPropertyCache* mir() const {
         return mir_->toGetPropertyCache();
     }
     const LDefinition* temp() {
@@ -6925,17 +7490,19 @@ class LGetPropertyCacheT : public LInstr
 
 // Emit code to load a boxed value from an object's slots if its shape matches
 // one of the shapes observed by the baseline IC, else bails out.
 class LGetPropertyPolymorphicV : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(GetPropertyPolymorphicV)
 
-    explicit LGetPropertyPolymorphicV(const LAllocation& obj) {
+    explicit LGetPropertyPolymorphicV(const LAllocation& obj)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
     }
     const LAllocation* obj() {
         return getOperand(0);
     }
     const MGetPropertyPolymorphic* mir() const {
         return mir_->toGetPropertyPolymorphic();
     }
@@ -6946,17 +7513,19 @@ class LGetPropertyPolymorphicV : public 
 
 // Emit code to load a typed value from an object's slots if its shape matches
 // one of the shapes observed by the baseline IC, else bails out.
 class LGetPropertyPolymorphicT : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(GetPropertyPolymorphicT)
 
-    LGetPropertyPolymorphicT(const LAllocation& obj, const LDefinition& temp) {
+    LGetPropertyPolymorphicT(const LAllocation& obj, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setTemp(0, temp);
     }
     const LAllocation* obj() {
         return getOperand(0);
     }
     const LDefinition* temp() {
         return getTemp(0);
@@ -6972,17 +7541,19 @@ class LGetPropertyPolymorphicT : public 
 // Emit code to store a boxed value to an object's slots if its shape matches
 // one of the shapes observed by the baseline IC, else bails out.
 class LSetPropertyPolymorphicV : public LInstructionHelper<0, 1 + BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(SetPropertyPolymorphicV)
 
     LSetPropertyPolymorphicV(const LAllocation& obj, const LBoxAllocation& value,
-                             const LDefinition& temp) {
+                             const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setBoxOperand(Value, value);
         setTemp(0, temp);
     }
 
     static const size_t Value = 1;
 
     const LAllocation* obj() {
@@ -7002,17 +7573,18 @@ class LSetPropertyPolymorphicT : public 
 {
     MIRType valueType_;
 
   public:
     LIR_HEADER(SetPropertyPolymorphicT)
 
     LSetPropertyPolymorphicT(const LAllocation& obj, const LAllocation& value, MIRType valueType,
                              const LDefinition& temp)
-      : valueType_(valueType)
+      : LInstructionHelper(classOpcode),
+        valueType_(valueType)
     {
         setOperand(0, obj);
         setOperand(1, value);
         setTemp(0, temp);
     }
 
     const LAllocation* obj() {
         return getOperand(0);
@@ -7034,17 +7606,19 @@ class LSetPropertyPolymorphicT : public 
     }
 };
 
 class LBindNameCache : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(BindNameCache)
 
-    LBindNameCache(const LAllocation& envChain, const LDefinition& temp) {
+    LBindNameCache(const LAllocation& envChain, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, envChain);
         setTemp(0, temp);
     }
     const LAllocation* environmentChain() {
         return getOperand(0);
     }
     const LDefinition* temp() {
         return getTemp(0);
@@ -7054,50 +7628,56 @@ class LBindNameCache : public LInstructi
     }
 };
 
 class LCallBindVar : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(CallBindVar)
 
-    explicit LCallBindVar(const LAllocation& envChain) {
+    explicit LCallBindVar(const LAllocation& envChain)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, envChain);
     }
     const LAllocation* environmentChain() {
         return getOperand(0);
     }
     const MCallBindVar* mir() const {
         return mir_->toCallBindVar();
     }
 };
 
 // Load a value from an object's dslots or a slots vector.
 class LLoadSlotV : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(LoadSlotV)
 
-    explicit LLoadSlotV(const LAllocation& in) {
+    explicit LLoadSlotV(const LAllocation& in)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
     }
     const MLoadSlot* mir() const {
         return mir_->toLoadSlot();
     }
 };
 
 // Load a typed value from an object's dslots or a slots vector. Unlike
 // LLoadSlotV, this can bypass extracting a type tag, directly retrieving a
 // pointer, integer, or double.
 class LLoadSlotT : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(LoadSlotT)
 
-    explicit LLoadSlotT(const LAllocation& slots) {
+    explicit LLoadSlotT(const LAllocation& slots)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, slots);
     }
     const LAllocation* slots() {
         return getOperand(0);
     }
     const LDefinition* output() {
         return this->getDef(0);
     }
@@ -7107,17 +7687,19 @@ class LLoadSlotT : public LInstructionHe
 };
 
 // Store a value to an object's dslots or a slots vector.
 class LStoreSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(StoreSlotV)
 
-    LStoreSlotV(const LAllocation& slots, const LBoxAllocation& value) {
+    LStoreSlotV(const LAllocation& slots, const LBoxAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, slots);
         setBoxOperand(Value, value);
     }
 
     static const size_t Value = 1;
 
     const MStoreSlot* mir() const {
         return mir_->toStoreSlot();
@@ -7133,17 +7715,19 @@ class LStoreSlotV : public LInstructionH
 //    the value.
 // 2) Better register allocation: we can store constants and FP regs directly
 //    without requiring a second register for the value.
 class LStoreSlotT : public LInstructionHelper<0, 2, 0>
 {
   public:
     LIR_HEADER(StoreSlotT)
 
-    LStoreSlotT(const LAllocation& slots, const LAllocation& value) {
+    LStoreSlotT(const LAllocation& slots, const LAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, slots);
         setOperand(1, value);
     }
     const MStoreSlot* mir() const {
         return mir_->toStoreSlot();
     }
     const LAllocation* slots() {
         return getOperand(0);
@@ -7154,81 +7738,93 @@ class LStoreSlotT : public LInstructionH
 };
 
 // Read length field of a JSString*.
 class LStringLength : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(StringLength)
 
-    explicit LStringLength(const LAllocation& string) {
+    explicit LStringLength(const LAllocation& string)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, string);
     }
 
     const LAllocation* string() {
         return getOperand(0);
     }
 };
 
 // Take the floor of a double precision number and converts it to an int32.
 // Implements Math.floor().
 class LFloor : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(Floor)
 
-    explicit LFloor(const LAllocation& num) {
+    explicit LFloor(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 // Take the floor of a single precision number and converts it to an int32.
 // Implements Math.floor().
 class LFloorF : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(FloorF)
 
-    explicit LFloorF(const LAllocation& num) {
+    explicit LFloorF(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 // Take the ceiling of a double precision number and converts it to an int32.
 // Implements Math.ceil().
 class LCeil : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(Ceil)
 
-    explicit LCeil(const LAllocation& num) {
+    explicit LCeil(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 // Take the ceiling of a single precision number and converts it to an int32.
 // Implements Math.ceil().
 class LCeilF : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(CeilF)
 
-    explicit LCeilF(const LAllocation& num) {
+    explicit LCeilF(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
 };
 
 // Round a double precision number and converts it to an int32.
 // Implements Math.round().
 class LRound : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(Round)
 
-    LRound(const LAllocation& num, const LDefinition& temp) {
+    LRound(const LAllocation& num, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
     MRound* mir() const {
@@ -7238,17 +7834,19 @@ class LRound : public LInstructionHelper
 
 // Round a single precision number and converts it to an int32.
 // Implements Math.round().
 class LRoundF : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(RoundF)
 
-    LRoundF(const LAllocation& num, const LDefinition& temp) {
+    LRoundF(const LAllocation& num, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
     MRound* mir() const {
@@ -7258,88 +7856,99 @@ class LRoundF : public LInstructionHelpe
 
 // Rounds a double precision number accordingly to mir()->roundingMode(),
 // and keeps a double output.
 class LNearbyInt : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NearbyInt)
 
-    explicit LNearbyInt(const LAllocation& num) {
+    explicit LNearbyInt(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
     MNearbyInt* mir() const {
         return mir_->toNearbyInt();
     }
 };
 
 // Rounds a single precision number accordingly to mir()->roundingMode(),
 // and keeps a single output.
 class LNearbyIntF : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NearbyIntF)
 
-    explicit LNearbyIntF(const LAllocation& num) {
+    explicit LNearbyIntF(const LAllocation& num)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, num);
     }
     MNearbyInt* mir() const {
         return mir_->toNearbyInt();
     }
 };
 
 // Load a function's call environment.
 class LFunctionEnvironment : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(FunctionEnvironment)
 
-    explicit LFunctionEnvironment(const LAllocation& function) {
+    explicit LFunctionEnvironment(const LAllocation& function)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, function);
     }
     const LAllocation* function() {
         return getOperand(0);
     }
 };
 
 class LHomeObject : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(HomeObject)
 
-    explicit LHomeObject(const LAllocation& function) {
+    explicit LHomeObject(const LAllocation& function)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, function);
     }
     const LAllocation* function() {
         return getOperand(0);
     }
 };
 
 class LHomeObjectSuperBase : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(HomeObjectSuperBase)
 
     explicit LHomeObjectSuperBase(const LAllocation& homeObject)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, homeObject);
     }
 
     const LAllocation* homeObject() {
         return getOperand(0);
     }
 };
 
 // Allocate a new LexicalEnvironmentObject.
 class LNewLexicalEnvironmentObject : public LCallInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NewLexicalEnvironmentObject)
 
-    explicit LNewLexicalEnvironmentObject(const LAllocation& enclosing) {
+    explicit LNewLexicalEnvironmentObject(const LAllocation& enclosing)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, enclosing);
     }
     const LAllocation* enclosing() {
         return getOperand(0);
     }
 
     MNewLexicalEnvironmentObject* mir() const {
         return mir_->toNewLexicalEnvironmentObject();
@@ -7347,17 +7956,19 @@ class LNewLexicalEnvironmentObject : pub
 };
 
 // Copy a LexicalEnvironmentObject.
 class LCopyLexicalEnvironmentObject : public LCallInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(CopyLexicalEnvironmentObject)
 
-    explicit LCopyLexicalEnvironmentObject(const LAllocation& env) {
+    explicit LCopyLexicalEnvironmentObject(const LAllocation& env)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, env);
     }
     const LAllocation* env() {
         return getOperand(0);
     }
 
     MCopyLexicalEnvironmentObject* mir() const {
         return mir_->toCopyLexicalEnvironmentObject();
@@ -7366,17 +7977,19 @@ class LCopyLexicalEnvironmentObject : pu
 
 class LCallGetProperty : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallGetProperty)
 
     static const size_t Value = 0;
 
-    explicit LCallGetProperty(const LBoxAllocation& val) {
+    explicit LCallGetProperty(const LBoxAllocation& val)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(Value, val);
     }
 
     MCallGetProperty* mir() const {
         return mir_->toCallGetProperty();
     }
 };
 
@@ -7384,17 +7997,19 @@ class LCallGetProperty : public LCallIns
 class LCallGetElement : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallGetElement)
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 
-    LCallGetElement(const LBoxAllocation& lhs, const LBoxAllocation& rhs) {
+    LCallGetElement(const LBoxAllocation& lhs, const LBoxAllocation& rhs)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(LhsInput, lhs);
         setBoxOperand(RhsInput, rhs);
     }
 
     MCallGetElement* mir() const {
         return mir_->toCallGetElement();
     }
 };
@@ -7404,17 +8019,19 @@ class LCallSetElement : public LCallInst
 {
   public:
     LIR_HEADER(CallSetElement)
 
     static const size_t Index = 1;
     static const size_t Value = 1 + BOX_PIECES;
 
     LCallSetElement(const LAllocation& obj, const LBoxAllocation& index,
-                    const LBoxAllocation& value) {
+                    const LBoxAllocation& value)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setBoxOperand(Index, index);
         setBoxOperand(Value, value);
     }
 
     const MCallSetElement* mir() const {
         return mir_->toCallSetElement();
     }
@@ -7424,17 +8041,19 @@ class LCallSetElement : public LCallInst
 class LCallInitElementArray : public LCallInstructionHelper<0, 2 + BOX_PIECES, 0>
 {
 public:
     LIR_HEADER(CallInitElementArray)
 
     static const size_t Value = 2;
 
     LCallInitElementArray(const LAllocation& obj, const LAllocation& index,
-                          const LBoxAllocation& value) {
+                          const LBoxAllocation& value)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setOperand(1, index);
         setBoxOperand(Value, value);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
     const LAllocation* index() {
@@ -7446,17 +8065,19 @@ public:
 };
 
 // Call a VM function to perform a property or name assignment of a generic value.
 class LCallSetProperty : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallSetProperty)
 
-    LCallSetProperty(const LAllocation& obj, const LBoxAllocation& value) {
+    LCallSetProperty(const LAllocation& obj, const LBoxAllocation& value)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setBoxOperand(Value, value);
     }
 
     static const size_t Value = 1;
 
     const MCallSetProperty* mir() const {
         return mir_->toCallSetProperty();
@@ -7465,34 +8086,38 @@ class LCallSetProperty : public LCallIns
 
 class LCallDeleteProperty : public LCallInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallDeleteProperty)
 
     static const size_t Value = 0;
 
-    explicit LCallDeleteProperty(const LBoxAllocation& value) {
+    explicit LCallDeleteProperty(const LBoxAllocation& value)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(Value, value);
     }
 
     MDeleteProperty* mir() const {
         return mir_->toDeleteProperty();
     }
 };
 
 class LCallDeleteElement : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallDeleteElement)
 
     static const size_t Value = 0;
     static const size_t Index = BOX_PIECES;
 
-    LCallDeleteElement(const LBoxAllocation& value, const LBoxAllocation& index) {
+    LCallDeleteElement(const LBoxAllocation& value, const LBoxAllocation& index)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(Value, value);
         setBoxOperand(Index, index);
     }
 
     MDeleteElement* mir() const {
         return mir_->toDeleteElement();
     }
 };
@@ -7500,17 +8125,19 @@ class LCallDeleteElement : public LCallI
 // Patchable jump to stubs generated for a SetProperty cache.
 class LSetPropertyCache : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3>
 {
   public:
     LIR_HEADER(SetPropertyCache)
 
     LSetPropertyCache(const LAllocation& object, const LBoxAllocation& id,
                       const LBoxAllocation& value, const LDefinition& temp,
-                      const LDefinition& tempDouble, const LDefinition& tempFloat32) {
+                      const LDefinition& tempDouble, const LDefinition& tempFloat32)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
         setBoxOperand(Id, id);
         setBoxOperand(Value, value);
         setTemp(0, temp);
         setTemp(1, tempDouble);
         setTemp(2, tempFloat32);
     }
 
@@ -7538,16 +8165,17 @@ class LGetIteratorCache : public LInstru
 {
   public:
     LIR_HEADER(GetIteratorCache)
 
     static const size_t Value = 0;
 
     LGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp1,
                       const LDefinition& temp2)
+      : LInstructionHelper(classOpcode)
     {
         setBoxOperand(Value, value);
         setTemp(0, temp1);
         setTemp(1, temp2);
     }
     const MGetIteratorCache* mir() const {
         return mir_->toGetIteratorCache();
     }
@@ -7559,17 +8187,19 @@ class LGetIteratorCache : public LInstru
     }
 };
 
 class LIteratorMore : public LInstructionHelper<BOX_PIECES, 1, 1>
 {
   public:
     LIR_HEADER(IteratorMore)
 
-    LIteratorMore(const LAllocation& iterator, const LDefinition& temp) {
+    LIteratorMore(const LAllocation& iterator, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, iterator);
         setTemp(0, temp);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
     const LDefinition* temp() {
         return getTemp(0);
@@ -7579,17 +8209,19 @@ class LIteratorMore : public LInstructio
     }
 };
 
 class LIsNoIterAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(IsNoIterAndBranch)
 
-    LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) {
+    LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input)
+      : LControlInstructionHelper(classOpcode)
+    {
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
         setBoxOperand(Input, input);
     }
 
     static const size_t Input = 0;
 
     MBasicBlock* ifTrue() const {
@@ -7601,17 +8233,19 @@ class LIsNoIterAndBranch : public LContr
 };
 
 class LIteratorEnd : public LInstructionHelper<0, 1, 3>
 {
   public:
     LIR_HEADER(IteratorEnd)
 
     LIteratorEnd(const LAllocation& iterator, const LDefinition& temp1,
-                 const LDefinition& temp2, const LDefinition& temp3) {
+                 const LDefinition& temp2, const LDefinition& temp3)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, iterator);
         setTemp(0, temp1);
         setTemp(1, temp2);
         setTemp(2, temp3);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
@@ -7629,39 +8263,47 @@ class LIteratorEnd : public LInstruction
     }
 };
 
 // Read the number of actual arguments.
 class LArgumentsLength : public LInstructionHelper<1, 0, 0>
 {
   public:
     LIR_HEADER(ArgumentsLength)
+
+    LArgumentsLength()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 // Load a value from the actual arguments.
 class LGetFrameArgument : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(GetFrameArgument)
 
-    explicit LGetFrameArgument(const LAllocation& index) {
+    explicit LGetFrameArgument(const LAllocation& index)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, index);
     }
     const LAllocation* index() {
         return getOperand(0);
     }
 };
 
 // Load a value from the actual arguments.
 class LSetFrameArgumentT : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(SetFrameArgumentT)
 
-    explicit LSetFrameArgumentT(const LAllocation& input) {
+    explicit LSetFrameArgumentT(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
     MSetFrameArgument* mir() const {
         return mir_->toSetFrameArgument();
     }
     const LAllocation* input() {
         return getOperand(0);
     }
@@ -7670,34 +8312,38 @@ class LSetFrameArgumentT : public LInstr
 // Load a value from the actual arguments.
 class LSetFrameArgumentC : public LInstructionHelper<0, 0, 0>
 {
     Value val_;
 
   public:
     LIR_HEADER(SetFrameArgumentC)
 
-    explicit LSetFrameArgumentC(const Value& val) {
+    explicit LSetFrameArgumentC(const Value& val)
+      : LInstructionHelper(classOpcode)
+    {
         val_ = val;
     }
     MSetFrameArgument* mir() const {
         return mir_->toSetFrameArgument();
     }
     const Value& val() const {
         return val_;
     }
 };
 
 // Load a value from the actual arguments.
 class LSetFrameArgumentV : public LInstructionHelper<0, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(SetFrameArgumentV)
 
-    explicit LSetFrameArgumentV(const LBoxAllocation& input) {
+    explicit LSetFrameArgumentV(const LBoxAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
     }
 
     static const size_t Input = 0;
 
     MSetFrameArgument* mir() const {
         return mir_->toSetFrameArgument();
     }
@@ -7706,26 +8352,31 @@ class LSetFrameArgumentV : public LInstr
 class LRunOncePrologue : public LCallInstructionHelper<0, 0, 0>
 {
   public:
     LIR_HEADER(RunOncePrologue)
 
     MRunOncePrologue* mir() const {
         return mir_->toRunOncePrologue();
     }
+
+    LRunOncePrologue()
+      : LCallInstructionHelper(classOpcode)
+    {}
 };
 
 // Create the rest parameter.
 class LRest : public LCallInstructionHelper<1, 1, 3>
 {
   public:
     LIR_HEADER(Rest)
 
     LRest(const LAllocation& numActuals, const LDefinition& temp1, const LDefinition& temp2,
           const LDefinition& temp3)
+      : LCallInstructionHelper(classOpcode)
     {
         setOperand(0, numActuals);
         setTemp(0, temp1);
         setTemp(1, temp2);
         setTemp(2, temp3);
     }
     const LAllocation* numActuals() {
         return getOperand(0);
@@ -7735,17 +8386,19 @@ class LRest : public LCallInstructionHel
     }
 };
 
 class LGuardReceiverPolymorphic : public LInstructionHelper<0, 1, 1>
 {
   public:
     LIR_HEADER(GuardReceiverPolymorphic)
 
-    LGuardReceiverPolymorphic(const LAllocation& in, const LDefinition& temp) {
+    LGuardReceiverPolymorphic(const LAllocation& in, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
         setTemp(0, temp);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
     const LDefinition* temp() {
         return getTemp(0);
@@ -7755,33 +8408,37 @@ class LGuardReceiverPolymorphic : public
     }
 };
 
 class LGuardUnboxedExpando : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(GuardUnboxedExpando)
 
-    explicit LGuardUnboxedExpando(const LAllocation& in) {
+    explicit LGuardUnboxedExpando(const LAllocation& in)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
     const MGuardUnboxedExpando* mir() const {
         return mir_->toGuardUnboxedExpando();
     }
 };
 
 class LLoadUnboxedExpando : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(LoadUnboxedExpando)
 
-    explicit LLoadUnboxedExpando(const LAllocation& in) {
+    explicit LLoadUnboxedExpando(const LAllocation& in)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
     const MLoadUnboxedExpando* mir() const {
         return mir_->toLoadUnboxedExpando();
     }
@@ -7789,17 +8446,19 @@ class LLoadUnboxedExpando : public LInst
 
 // Guard that a value is in a TypeSet.
 class LTypeBarrierV : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 2>
 {
   public:
     LIR_HEADER(TypeBarrierV)
 
     LTypeBarrierV(const LBoxAllocation& input, const LDefinition& unboxTemp,
-                  const LDefinition& objTemp) {
+                  const LDefinition& objTemp)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
         setTemp(0, unboxTemp);
         setTemp(1, objTemp);
     }
 
     static const size_t Input = 0;
 
     const MTypeBarrier* mir() const {
@@ -7814,17 +8473,19 @@ class LTypeBarrierV : public LInstructio
 };
 
 // Guard that a object is in a TypeSet.
 class LTypeBarrierO : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(TypeBarrierO)
 
-    LTypeBarrierO(const LAllocation& obj, const LDefinition& temp) {
+    LTypeBarrierO(const LAllocation& obj, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setTemp(0, temp);
     }
     const MTypeBarrier* mir() const {
         return mir_->toTypeBarrier();
     }
     const LAllocation* object() {
         return getOperand(0);
@@ -7836,17 +8497,19 @@ class LTypeBarrierO : public LInstructio
 
 // Generational write barrier used when writing an object to another object.
 class LPostWriteBarrierO : public LInstructionHelper<0, 2, 1>
 {
   public:
     LIR_HEADER(PostWriteBarrierO)
 
     LPostWriteBarrierO(const LAllocation& obj, const LAllocation& value,
-                       const LDefinition& temp) {
+                       const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setOperand(1, value);
         setTemp(0, temp);
     }
 
     const MPostWriteBarrier* mir() const {
         return mir_->toPostWriteBarrier();
     }
@@ -7863,17 +8526,19 @@ class LPostWriteBarrierO : public LInstr
 
 // Generational write barrier used when writing a string to an object.
 class LPostWriteBarrierS : public LInstructionHelper<0, 2, 1>
 {
   public:
     LIR_HEADER(PostWriteBarrierS)
 
     LPostWriteBarrierS(const LAllocation& obj, const LAllocation& value,
-                       const LDefinition& temp) {
+                       const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setOperand(1, value);
         setTemp(0, temp);
     }
 
     const MPostWriteBarrier* mir() const {
         return mir_->toPostWriteBarrier();
     }
@@ -7890,17 +8555,19 @@ class LPostWriteBarrierS : public LInstr
 
 // Generational write barrier used when writing a value to another object.
 class LPostWriteBarrierV : public LInstructionHelper<0, 1 + BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(PostWriteBarrierV)
 
     LPostWriteBarrierV(const LAllocation& obj, const LBoxAllocation& value,
-                       const LDefinition& temp) {
+                       const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setBoxOperand(Input, value);
         setTemp(0, temp);
     }
 
     static const size_t Input = 1;
 
     const MPostWriteBarrier* mir() const {
@@ -7917,17 +8584,19 @@ class LPostWriteBarrierV : public LInstr
 // Generational write barrier used when writing an object to another object's
 // elements.
 class LPostWriteElementBarrierO : public LInstructionHelper<0, 3, 1>
 {
   public:
     LIR_HEADER(PostWriteElementBarrierO)
 
     LPostWriteElementBarrierO(const LAllocation& obj, const LAllocation& value,
-                              const LAllocation& index, const LDefinition& temp) {
+                              const LAllocation& index, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setOperand(1, value);
         setOperand(2, index);
         setTemp(0, temp);
     }
 
     const MPostWriteElementBarrier* mir() const {
         return mir_->toPostWriteElementBarrier();
@@ -7953,17 +8622,19 @@ class LPostWriteElementBarrierO : public
 // Generational write barrier used when writing a string to an object's
 // elements.
 class LPostWriteElementBarrierS : public LInstructionHelper<0, 3, 1>
 {
   public:
     LIR_HEADER(PostWriteElementBarrierS)
 
     LPostWriteElementBarrierS(const LAllocation& obj, const LAllocation& value,
-                              const LAllocation& index, const LDefinition& temp) {
+                              const LAllocation& index, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setOperand(1, value);
         setOperand(2, index);
         setTemp(0, temp);
     }
 
     const MPostWriteElementBarrier* mir() const {
         return mir_->toPostWriteElementBarrier();
@@ -7989,17 +8660,19 @@ class LPostWriteElementBarrierS : public
 // Generational write barrier used when writing a value to another object's
 // elements.
 class LPostWriteElementBarrierV : public LInstructionHelper<0, 2 + BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(PostWriteElementBarrierV)
 
     LPostWriteElementBarrierV(const LAllocation& obj, const LAllocation& index,
-                              const LBoxAllocation& value, const LDefinition& temp) {
+                              const LBoxAllocation& value, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, obj);
         setOperand(1, index);
         setBoxOperand(Input, value);
         setTemp(0, temp);
     }
 
     static const size_t Input = 2;
 
@@ -8021,17 +8694,19 @@ class LPostWriteElementBarrierV : public
 };
 
 // Guard against an object's identity.
 class LGuardObjectIdentity : public LInstructionHelper<0, 2, 0>
 {
   public:
     LIR_HEADER(GuardObjectIdentity)
 
-    explicit LGuardObjectIdentity(const LAllocation& in, const LAllocation& expected) {
+    LGuardObjectIdentity(const LAllocation& in, const LAllocation& expected)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
         setOperand(1, expected);
     }
     const LAllocation* input() {
         return getOperand(0);
     }
     const LAllocation* expected() {
         return getOperand(1);
@@ -8041,44 +8716,50 @@ class LGuardObjectIdentity : public LIns
     }
 };
 
 class LGuardShape : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(GuardShape)
 
-    explicit LGuardShape(const LAllocation& in) {
+    explicit LGuardShape(const LAllocation& in)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
     }
     const MGuardShape* mir() const {
         return mir_->toGuardShape();
     }
 };
 
 class LGuardObjectGroup : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(GuardObjectGroup)
 
-    explicit LGuardObjectGroup(const LAllocation& in) {
+    explicit LGuardObjectGroup(const LAllocation& in)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
     }
     const MGuardObjectGroup* mir() const {
         return mir_->toGuardObjectGroup();
     }
 };
 
 // Guard against an object's class.
 class LGuardClass : public LInstructionHelper<0, 1, 1>
 {
   public:
     LIR_HEADER(GuardClass)
 
-    LGuardClass(const LAllocation& in, const LDefinition& temp) {
+    LGuardClass(const LAllocation& in, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
         setTemp(0, temp);
     }
     const MGuardClass* mir() const {
         return mir_->toGuardClass();
     }
     const LDefinition* tempInt() {
         return getTemp(0);
@@ -8086,33 +8767,37 @@ class LGuardClass : public LInstructionH
 };
 
 // Guard against the sharedness of a TypedArray's memory.
 class LGuardSharedTypedArray : public LInstructionHelper<0, 1, 1>
 {
   public:
     LIR_HEADER(GuardSharedTypedArray)
 
-    LGuardSharedTypedArray(const LAllocation& in, const LDefinition& temp) {
+    LGuardSharedTypedArray(const LAllocation& in, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
         setTemp(0, temp);
     }
     const MGuardSharedTypedArray* mir() const {
         return mir_->toGuardSharedTypedArray();
     }
     const LDefinition* tempInt() {
         return getTemp(0);
     }
 };
 
 class LInCache : public LInstructionHelper<1, BOX_PIECES+1, 1>
 {
   public:
     LIR_HEADER(InCache)
-    LInCache(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
+    LInCache(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(LHS, lhs);
         setOperand(RHS, rhs);
         setTemp(0, temp);
     }
 
     const LAllocation* lhs() {
         return getOperand(LHS);
     }
@@ -8133,48 +8818,54 @@ class LInCache : public LInstructionHelp
 class LHasOwnCache : public LInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(HasOwnCache)
 
     static const size_t Value = 0;
     static const size_t Id = BOX_PIECES;
 
-    LHasOwnCache(const LBoxAllocation& value, const LBoxAllocation& id) {
+    LHasOwnCache(const LBoxAllocation& value, const LBoxAllocation& id)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Value, value);
         setBoxOperand(Id, id);
     }
 
     const MHasOwnCache* mir() const {
         return mir_->toHasOwnCache();
     }
 };
 
 class LInstanceOfO : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(InstanceOfO)
-    explicit LInstanceOfO(const LAllocation& lhs) {
+    explicit LInstanceOfO(const LAllocation& lhs)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, lhs);
     }
 
     MInstanceOf* mir() const {
         return mir_->toInstanceOf();
     }
 
     const LAllocation* lhs() {
         return getOperand(0);
     }
 };
 
 class LInstanceOfV : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(InstanceOfV)
-    explicit LInstanceOfV(const LBoxAllocation& lhs) {
+    explicit LInstanceOfV(const LBoxAllocation& lhs)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(LHS, lhs);
     }
 
     MInstanceOf* mir() const {
         return mir_->toInstanceOf();
     }
 
     const LAllocation* lhs() {
@@ -8183,17 +8874,19 @@ class LInstanceOfV : public LInstruction
 
     static const size_t LHS = 0;
 };
 
 class LInstanceOfCache : public LInstructionHelper<1, BOX_PIECES+1, 0>
 {
   public:
     LIR_HEADER(InstanceOfCache)
-    LInstanceOfCache(const LBoxAllocation& lhs, const LAllocation& rhs) {
+    LInstanceOfCache(const LBoxAllocation& lhs, const LAllocation& rhs)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(LHS, lhs);
         setOperand(RHS, rhs);
     }
 
     const LDefinition* output() {
         return this->getDef(0);
     }
     const LAllocation* lhs() {
@@ -8206,17 +8899,19 @@ class LInstanceOfCache : public LInstruc
     static const size_t LHS = 0;
     static const size_t RHS = BOX_PIECES;
 };
 
 class LIsCallableO : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(IsCallableO);
-    explicit LIsCallableO(const LAllocation& object) {
+    explicit LIsCallableO(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
     MIsCallable* mir() const {
         return mir_->toIsCallable();
@@ -8224,112 +8919,126 @@ class LIsCallableO : public LInstruction
 };
 
 class LIsCallableV : public LInstructionHelper<1, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(IsCallableV);
     static const size_t Value = 0;
 
-    LIsCallableV(const LBoxAllocation& value, const LDefinition& temp) {
+    LIsCallableV(const LBoxAllocation& value, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(0, value);
         setTemp(0, temp);
     }
     const LDefinition* temp() {
         return getTemp(0);
     }
     MIsCallable* mir() const {
         return mir_->toIsCallable();
     }
 };
 
 class LIsConstructor : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(IsConstructor);
-    explicit LIsConstructor(const LAllocation& object) {
+    explicit LIsConstructor(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
 
     const LAllocation* object() {
         return getOperand(0);
     }
     MIsConstructor* mir() const {
         return mir_->toIsConstructor();
     }
 };
 
 class LIsArrayO : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(IsArrayO);
 
-    explicit LIsArrayO(const LAllocation& object) {
+    explicit LIsArrayO(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
     MIsArray* mir() const {
         return mir_->toIsArray();
     }
 };
 
 class LIsArrayV : public LInstructionHelper<1, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(IsArrayV);
     static const size_t Value = 0;
 
-    explicit LIsArrayV(const LBoxAllocation& value, const LDefinition& temp) {
+    LIsArrayV(const LBoxAllocation& value, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(0, value);
         setTemp(0, temp);
     }
     const LDefinition* temp() {
         return getTemp(0);
     }
     MIsArray* mir() const {
         return mir_->toIsArray();
     }
 };
 
 class LIsTypedArray : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(IsTypedArray);
 
-    explicit LIsTypedArray(const LAllocation& object) {
+    explicit LIsTypedArray(const LAllocation& object)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, object);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
 };
 
 class LIsObject : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(IsObject);
     static const size_t Input = 0;
 
-    explicit LIsObject(const LBoxAllocation& input) {
+    explicit LIsObject(const LBoxAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
     }
 
     MIsObject* mir() const {
         return mir_->toIsObject();
     }
 };
 
 class LIsObjectAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(IsObjectAndBranch)
 
-    LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) {
+    LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input)
+      : LControlInstructionHelper(classOpcode)
+    {
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
         setBoxOperand(Input, input);
     }
 
     static const size_t Input = 0;
 
     MBasicBlock* ifTrue() const {
@@ -8339,66 +9048,76 @@ class LIsObjectAndBranch : public LContr
         return getSuccessor(1);
     }
 };
 
 class LHasClass : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(HasClass);
-    explicit LHasClass(const LAllocation& lhs) {
+    explicit LHasClass(const LAllocation& lhs)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, lhs);
     }
 
     const LAllocation* lhs() {
         return getOperand(0);
     }
     MHasClass* mir() const {
         return mir_->toHasClass();
     }
 };
 
 class LObjectClassToString : public LCallInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(ObjectClassToString);
 
-    explicit LObjectClassToString(const LAllocation& lhs) {
+    explicit LObjectClassToString(const LAllocation& lhs)
+      : LCallInstructionHelper(classOpcode)
+    {
         setOperand(0, lhs);
     }
     const LAllocation* object() {
         return getOperand(0);
     }
     MObjectClassToString* mir() const {
         return mir_->toObjectClassToString();
     }
 };
 
 template<size_t Defs, size_t Ops>
 class LWasmSelectBase : public LInstructionHelper<Defs, Ops, 0>
 {
     typedef LInstructionHelper<Defs, Ops, 0> Base;
-  public:
-
+
+  protected:
+    explicit LWasmSelectBase(LNode::Opcode opcode)
+      : Base(opcode)
+    {}
+
+  public:
     MWasmSelect* mir() const {
         return Base::mir_->toWasmSelect();
     }
 };
 
 class LWasmSelect : public LWasmSelectBase<1, 3>
 {
   public:
     LIR_HEADER(WasmSelect);
 
     static const size_t TrueExprIndex = 0;
     static const size_t FalseExprIndex = 1;
     static const size_t CondIndex = 2;
 
     LWasmSelect(const LAllocation& trueExpr, const LAllocation& falseExpr,
                 const LAllocation& cond)
+      : LWasmSelectBase(classOpcode)
     {
         setOperand(TrueExprIndex, trueExpr);
         setOperand(FalseExprIndex, falseExpr);
         setOperand(CondIndex, cond);
     }
 
     const LAllocation* trueExpr() {
         return getOperand(TrueExprIndex);
@@ -8417,16 +9136,17 @@ class LWasmSelectI64 : public LWasmSelec
     LIR_HEADER(WasmSelectI64);
 
     static const size_t TrueExprIndex = 0;
     static const size_t FalseExprIndex = INT64_PIECES;
     static const size_t CondIndex = INT64_PIECES * 2;
 
     LWasmSelectI64(const LInt64Allocation& trueExpr, const LInt64Allocation& falseExpr,
                    const LAllocation& cond)
+      : LWasmSelectBase(classOpcode)
     {
         setInt64Operand(TrueExprIndex, trueExpr);
         setInt64Operand(FalseExprIndex, falseExpr);
         setOperand(CondIndex, cond);
     }
 
     const LInt64Allocation trueExpr() {
         return getInt64Operand(TrueExprIndex);
@@ -8438,33 +9158,36 @@ class LWasmSelectI64 : public LWasmSelec
         return getOperand(CondIndex);
     }
 };
 
 class LWasmAddOffset : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(WasmAddOffset);
-    explicit LWasmAddOffset(const LAllocation& base) {
+    explicit LWasmAddOffset(const LAllocation& base)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, base);
     }
     MWasmAddOffset* mir() const {
         return mir_->toWasmAddOffset();
     }
     const LAllocation* base() {
         return getOperand(0);
     }
 };
 
 class LWasmBoundsCheck : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(WasmBoundsCheck);
     explicit LWasmBoundsCheck(const LAllocation& ptr,
                               const LAllocation& boundsCheckLimit = LAllocation())
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setOperand(1, boundsCheckLimit);
     }
     MWasmBoundsCheck* mir() const {
         return mir_->toWasmBoundsCheck();
     }
     const LAllocation* ptr() {
@@ -8474,32 +9197,36 @@ class LWasmBoundsCheck : public LInstruc
         return getOperand(1);
     }
 };
 
 class LWasmAlignmentCheck : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(WasmAlignmentCheck);
-    explicit LWasmAlignmentCheck(const LAllocation& ptr) {
+    explicit LWasmAlignmentCheck(const LAllocation& ptr)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, ptr);
     }
     MWasmAlignmentCheck* mir() const {
         return mir_->toWasmAlignmentCheck();
     }
     const LAllocation* ptr() {
         return getOperand(0);
     }
 };
 
 class LWasmLoadTls : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(WasmLoadTls);
-    explicit LWasmLoadTls(const LAllocation& tlsPtr) {
+    explicit LWasmLoadTls(const LAllocation& tlsPtr)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, tlsPtr);
     }
     MWasmLoadTls* mir() const {
         return mir_->toWasmLoadTls();
     }
     const LAllocation* tlsPtr() {
         return getOperand(0);
     }
@@ -8508,17 +9235,20 @@ class LWasmLoadTls : public LInstruction
 namespace details {
 
 // This is a base class for LWasmLoad/LWasmLoadI64.
 template<size_t Defs, size_t Temp>
 class LWasmLoadBase : public LInstructionHelper<Defs, 2, Temp>
 {
   public:
     typedef LInstructionHelper<Defs, 2, Temp> Base;
-    explicit LWasmLoadBase(const LAllocation& ptr, const LAllocation& memoryBase) {
+    explicit LWasmLoadBase(LNode::Opcode opcode, const LAllocation& ptr,
+                           const LAllocation& memoryBase)
+      : Base(opcode)
+    {
         Base::setOperand(0, ptr);
         Base::setOperand(1, memoryBase);
     }
     MWasmLoad* mir() const {
         return Base::mir_->toWasmLoad();
     }
     const LAllocation* ptr() {
         return Base::getOperand(0);
@@ -8529,33 +9259,33 @@ class LWasmLoadBase : public LInstructio
 };
 
 } // namespace details
 
 class LWasmLoad : public details::LWasmLoadBase<1, 1>
 {
   public:
     explicit LWasmLoad(const LAllocation& ptr, const LAllocation& memoryBase = LAllocation())
-      : LWasmLoadBase(ptr, memoryBase)
+      : LWasmLoadBase(classOpcode, ptr, memoryBase)
     {
         setTemp(0, LDefinition::BogusTemp());
     }
 
     const LDefinition* ptrCopy() {
         return Base::getTemp(0);
     }
 
     LIR_HEADER(WasmLoad);
 };
 
 class LWasmLoadI64 : public details::LWasmLoadBase<INT64_PIECES, 1>
 {
   public:
     explicit LWasmLoadI64(const LAllocation& ptr, const LAllocation& memoryBase = LAllocation())
-      : LWasmLoadBase(ptr, memoryBase)
+      : LWasmLoadBase(classOpcode, ptr, memoryBase)
     {
         setTemp(0, LDefinition::BogusTemp());
     }
 
     const LDefinition* ptrCopy() {
         return Base::getTemp(0);
     }
 
@@ -8568,16 +9298,17 @@ class LWasmStore : public LInstructionHe
     LIR_HEADER(WasmStore);
 
     static const size_t PtrIndex = 0;
     static const size_t ValueIndex = 1;
     static const size_t MemoryBaseIndex = 2;
 
     LWasmStore(const LAllocation& ptr, const LAllocation& value,
                const LAllocation& memoryBase = LAllocation())
+      : LInstructionHelper(classOpcode)
     {
         setOperand(PtrIndex, ptr);
         setOperand(ValueIndex, value);
         setOperand(MemoryBaseIndex, memoryBase);
         setTemp(0, LDefinition::BogusTemp());
     }
     MWasmStore* mir() const {
         return mir_->toWasmStore();
@@ -8602,16 +9333,17 @@ class LWasmStoreI64 : public LInstructio
     LIR_HEADER(WasmStoreI64);
 
     static const size_t PtrIndex = 0;
     static const size_t MemoryBaseIndex = 1;
     static const size_t ValueIndex = 2;
 
     LWasmStoreI64(const LAllocation& ptr, const LInt64Allocation& value,
                   const LAllocation& memoryBase = LAllocation())
+      : LInstructionHelper(classOpcode)
     {
         setOperand(PtrIndex, ptr);
         setOperand(MemoryBaseIndex, memoryBase);
         setInt64Operand(ValueIndex, value);
         setTemp(0, LDefinition::BogusTemp());
     }
     MWasmStore* mir() const {
         return mir_->toWasmStore();
@@ -8631,16 +9363,17 @@ class LWasmStoreI64 : public LInstructio
 };
 
 class LAsmJSLoadHeap : public LInstructionHelper<1, 3, 0>
 {
   public:
     LIR_HEADER(AsmJSLoadHeap);
     explicit LAsmJSLoadHeap(const LAllocation& ptr, const LAllocation& boundsCheckLimit = LAllocation(),
                             const LAllocation& memoryBase = LAllocation())
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setOperand(1, boundsCheckLimit);
         setOperand(2, memoryBase);
     }
     MAsmJSLoadHeap* mir() const {
         return mir_->toAsmJSLoadHeap();
     }
@@ -8657,16 +9390,17 @@ class LAsmJSLoadHeap : public LInstructi
 
 class LAsmJSStoreHeap : public LInstructionHelper<0, 4, 0>
 {
   public:
     LIR_HEADER(AsmJSStoreHeap);
     LAsmJSStoreHeap(const LAllocation& ptr, const LAllocation& value,
                     const LAllocation& boundsCheckLimit = LAllocation(),
                     const LAllocation& memoryBase = LAllocation())
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setOperand(1, value);
         setOperand(2, boundsCheckLimit);
         setOperand(3, memoryBase);
     }
     MAsmJSStoreHeap* mir() const {
         return mir_->toAsmJSStoreHeap();
@@ -8688,27 +9422,29 @@ class LAsmJSStoreHeap : public LInstruct
 class LWasmCompareExchangeHeap : public LInstructionHelper<1, 4, 4>
 {
   public:
     LIR_HEADER(WasmCompareExchangeHeap);
 
     // ARM, ARM64, x86, x64
     LWasmCompareExchangeHeap(const LAllocation& ptr, const LAllocation& oldValue,
                              const LAllocation& newValue, const LAllocation& memoryBase = LAllocation())
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setOperand(1, oldValue);
         setOperand(2, newValue);
         setOperand(3, memoryBase);
         setTemp(0, LDefinition::BogusTemp());
     }
     // MIPS32, MIPS64
     LWasmCompareExchangeHeap(const LAllocation& ptr, const LAllocation& oldValue,
                              const LAllocation& newValue, const LDefinition& valueTemp,
                              const LDefinition& offsetTemp, const LDefinition& maskTemp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setOperand(1, oldValue);
         setOperand(2, newValue);
         setOperand(3, LAllocation());
         setTemp(0, LDefinition::BogusTemp());
         setTemp(1, valueTemp);
         setTemp(2, offsetTemp);
@@ -8754,26 +9490,28 @@ class LWasmCompareExchangeHeap : public 
 class LWasmAtomicExchangeHeap : public LInstructionHelper<1, 3, 4>
 {
   public:
     LIR_HEADER(WasmAtomicExchangeHeap);
 
     // ARM, ARM64, x86, x64
     LWasmAtomicExchangeHeap(const LAllocation& ptr, const LAllocation& value,
                             const LAllocation& memoryBase = LAllocation())
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setOperand(1, value);
         setOperand(2, memoryBase);
         setTemp(0, LDefinition::BogusTemp());
     }
     // MIPS32, MIPS64
     LWasmAtomicExchangeHeap(const LAllocation& ptr, const LAllocation& value,
                             const LDefinition& valueTemp, const LDefinition& offsetTemp,
                             const LDefinition& maskTemp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setOperand(1, value);
         setOperand(2, LAllocation());
         setTemp(0, LDefinition::BogusTemp());
         setTemp(1, valueTemp);
         setTemp(2, offsetTemp);
         setTemp(3, maskTemp);
@@ -8819,28 +9557,30 @@ class LWasmAtomicBinopHeap : public LIns
 
     static const int32_t valueOp = 1;
 
     // ARM, ARM64, x86, x64
     LWasmAtomicBinopHeap(const LAllocation& ptr, const LAllocation& value,
                          const LDefinition& temp,
                          const LDefinition& flagTemp = LDefinition::BogusTemp(),
                          const LAllocation& memoryBase = LAllocation())
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setOperand(1, value);
         setOperand(2, memoryBase);
         setTemp(0, temp);
         setTemp(1, LDefinition::BogusTemp());
         setTemp(2, flagTemp);
     }
     // MIPS32, MIPS64
     LWasmAtomicBinopHeap(const LAllocation& ptr, const LAllocation& value,
                          const LDefinition& valueTemp, const LDefinition& offsetTemp,
                          const LDefinition& maskTemp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setOperand(1, value);
         setOperand(2, LAllocation());
         setTemp(0, LDefinition::BogusTemp());
         setTemp(1, LDefinition::BogusTemp());
         setTemp(2, LDefinition::BogusTemp());
         setTemp(3, valueTemp);
@@ -8893,27 +9633,29 @@ class LWasmAtomicBinopHeap : public LIns
 class LWasmAtomicBinopHeapForEffect : public LInstructionHelper<0, 3, 5>
 {
   public:
     LIR_HEADER(WasmAtomicBinopHeapForEffect);
     // ARM, ARM64, x86, x64
     LWasmAtomicBinopHeapForEffect(const LAllocation& ptr, const LAllocation& value,
                                   const LDefinition& flagTemp = LDefinition::BogusTemp(),
                                   const LAllocation& memoryBase = LAllocation())
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setOperand(1, value);
         setOperand(2, memoryBase);
         setTemp(0, LDefinition::BogusTemp());
         setTemp(1, flagTemp);
     }
     // MIPS32, MIPS64
     LWasmAtomicBinopHeapForEffect(const LAllocation& ptr, const LAllocation& value,
                                   const LDefinition& valueTemp, const LDefinition& offsetTemp,
                                   const LDefinition& maskTemp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, ptr);
         setOperand(1, value);
         setOperand(2, LAllocation());
         setTemp(0, LDefinition::BogusTemp());
         setTemp(1, LDefinition::BogusTemp());
         setTemp(2, valueTemp);
         setTemp(3, offsetTemp);
@@ -8956,47 +9698,53 @@ class LWasmAtomicBinopHeapForEffect : pu
         return mir_->toWasmAtomicBinopHeap();
     }
 };
 
 class LWasmLoadGlobalVar : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(WasmLoadGlobalVar);
-    explicit LWasmLoadGlobalVar(const LAllocation& tlsPtr) {
+    explicit LWasmLoadGlobalVar(const LAllocation& tlsPtr)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, tlsPtr);
     }
     MWasmLoadGlobalVar* mir() const {
         return mir_->toWasmLoadGlobalVar();
     }
     const LAllocation* tlsPtr() {
         return getOperand(0);
     }
 };
 
 class LWasmLoadGlobalVarI64 : public LInstructionHelper<INT64_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(WasmLoadGlobalVarI64);
-    explicit LWasmLoadGlobalVarI64(const LAllocation& tlsPtr) {
+    explicit LWasmLoadGlobalVarI64(const LAllocation& tlsPtr)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, tlsPtr);
     }
     MWasmLoadGlobalVar* mir() const {
         return mir_->toWasmLoadGlobalVar();
     }
     const LAllocation* tlsPtr() {
         return getOperand(0);
     }
 };
 
 class LWasmStoreGlobalVar : public LInstructionHelper<0, 2, 0>
 {
   public:
     LIR_HEADER(WasmStoreGlobalVar);
-    explicit LWasmStoreGlobalVar(const LAllocation& value, const LAllocation& tlsPtr) {
+    LWasmStoreGlobalVar(const LAllocation& value, const LAllocation& tlsPtr)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, value);
         setOperand(1, tlsPtr);
     }
     MWasmStoreGlobalVar* mir() const {
         return mir_->toWasmStoreGlobalVar();
     }
     const LAllocation* value() {
         return getOperand(0);
@@ -9005,17 +9753,19 @@ class LWasmStoreGlobalVar : public LInst
         return getOperand(1);
     }
 };
 
 class LWasmStoreGlobalVarI64 : public LInstructionHelper<0, INT64_PIECES + 1, 0>
 {
   public:
     LIR_HEADER(WasmStoreGlobalVarI64);
-    explicit LWasmStoreGlobalVarI64(const LInt64Allocation& value, const LAllocation& tlsPtr) {
+    LWasmStoreGlobalVarI64(const LInt64Allocation& value, const LAllocation& tlsPtr)
+      : LInstructionHelper(classOpcode)
+    {
         setInt64Operand(0, value);
         setOperand(INT64_PIECES, tlsPtr);
     }
     MWasmStoreGlobalVar* mir() const {
         return mir_->toWasmStoreGlobalVar();
     }
     const LInt64Allocation value() {
         return getInt64Operand(0);
@@ -9024,66 +9774,88 @@ class LWasmStoreGlobalVarI64 : public LI
         return getOperand(INT64_PIECES);
     }
 };
 
 class LWasmParameter : public LInstructionHelper<1, 0, 0>
 {
   public:
     LIR_HEADER(WasmParameter);
+
+    LWasmParameter()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 class LWasmParameterI64 : public LInstructionHelper<INT64_PIECES, 0, 0>
 {
   public:
     LIR_HEADER(WasmParameterI64);
+
+    LWasmParameterI64()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 class LWasmReturn : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(WasmReturn);
+
+    LWasmReturn()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 class LWasmReturnI64 : public LInstructionHelper<0, INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(WasmReturnI64)
 
-    explicit LWasmReturnI64(const LInt64Allocation& input) {
+    explicit LWasmReturnI64(const LInt64Allocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setInt64Operand(0, input);
     }
 };
 
 class LWasmReturnVoid : public LInstructionHelper<0, 0, 0>
 {
   public:
     LIR_HEADER(WasmReturnVoid);
+
+    LWasmReturnVoid()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 class LWasmStackArg : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(WasmStackArg);
-    explicit LWasmStackArg(const LAllocation& arg) {
+    explicit LWasmStackArg(const LAllocation& arg)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, arg);
     }
     MWasmStackArg* mir() const {
         return mirRaw()->toWasmStackArg();
     }
     const LAllocation* arg() {
         return getOperand(0);
     }
 };
 
 class LWasmStackArgI64 : public LInstructionHelper<0, INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(WasmStackArgI64);
-    explicit LWasmStackArgI64(const LInt64Allocation& arg) {
+    explicit LWasmStackArgI64(const LInt64Allocation& arg)
+      : LInstructionHelper(classOpcode)
+    {
         setInt64Operand(0, arg);
     }
     MWasmStackArg* mir() const {
         return mirRaw()->toWasmStackArg();
     }
     const LInt64Allocation arg() {
         return getInt64Operand(0);
     }
@@ -9092,18 +9864,18 @@ class LWasmStackArgI64 : public LInstruc
 template <size_t Defs>
 class LWasmCallBase : public LVariadicInstruction<Defs, 0>
 {
     using Base = LVariadicInstruction<Defs, 0>;
 
     bool needsBoundsCheck_;
 
   public:
-    LWasmCallBase(uint32_t numOperands, bool needsBoundsCheck)
-      : Base(numOperands),
+    LWasmCallBase(LNode::Opcode opcode, uint32_t numOperands, bool needsBoundsCheck)
+      : Base(opcode, numOperands),
         needsBoundsCheck_(needsBoundsCheck)
     {
         this->setIsCall();
     }
 
     MWasmCall* mir() const {
         return this->mir_->toWasmCall();
     }
@@ -9123,39 +9895,39 @@ class LWasmCallBase : public LVariadicIn
 };
 
 class LWasmCall : public LWasmCallBase<1>
 {
   public:
     LIR_HEADER(WasmCall);
 
     LWasmCall(uint32_t numOperands, bool needsBoundsCheck)
-      : LWasmCallBase(numOperands, needsBoundsCheck)
+      : LWasmCallBase(classOpcode, numOperands, needsBoundsCheck)
     {
     }
 };
 
 class LWasmCallVoid : public LWasmCallBase<0>
 {
   public:
     LIR_HEADER(WasmCallVoid);
 
     LWasmCallVoid(uint32_t numOperands, bool needsBoundsCheck)
-      : LWasmCallBase(numOperands, needsBoundsCheck)
+      : LWasmCallBase(classOpcode, numOperands, needsBoundsCheck)
     {
     }
 };
 
 class LWasmCallI64 : public LWasmCallBase<INT64_PIECES>
 {
   public:
     LIR_HEADER(WasmCallI64);
 
     LWasmCallI64(uint32_t numOperands, bool needsBoundsCheck)
-      : LWasmCallBase(numOperands, needsBoundsCheck)
+      : LWasmCallBase(classOpcode, numOperands, needsBoundsCheck)
     {
     }
 };
 
 inline bool
 LNode::isCallPreserved(AnyRegister reg) const
 {
     switch (op()) {
@@ -9168,17 +9940,19 @@ LNode::isCallPreserved(AnyRegister reg) 
     }
 }
 
 class LAssertRangeI : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(AssertRangeI)
 
-    explicit LAssertRangeI(const LAllocation& input) {
+    explicit LAssertRangeI(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 
     const LAllocation* input() {
         return getOperand(0);
     }
 
     MAssertRange* mir() {
@@ -9189,17 +9963,19 @@ class LAssertRangeI : public LInstructio
     }
 };
 
 class LAssertRangeD : public LInstructionHelper<0, 1, 1>
 {
   public:
     LIR_HEADER(AssertRangeD)
 
-    LAssertRangeD(const LAllocation& input, const LDefinition& temp) {
+    LAssertRangeD(const LAllocation& input, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
         setTemp(0, temp);
     }
 
     const LAllocation* input() {
         return getOperand(0);
     }
 
@@ -9214,17 +9990,19 @@ class LAssertRangeD : public LInstructio
         return mir()->assertedRange();
     }
 };
 
 class LAssertRangeF : public LInstructionHelper<0, 1, 2>
 {
   public:
     LIR_HEADER(AssertRangeF)
-    LAssertRangeF(const LAllocation& input, const LDefinition& temp, const LDefinition& temp2) {
+    LAssertRangeF(const LAllocation& input, const LDefinition& temp, const LDefinition& temp2)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
         setTemp(0, temp);
         setTemp(1, temp2);
     }
 
     const LAllocation* input() {
         return getOperand(0);
     }
@@ -9245,16 +10023,17 @@ class LAssertRangeF : public LInstructio
 
 class LAssertRangeV : public LInstructionHelper<0, BOX_PIECES, 3>
 {
   public:
     LIR_HEADER(AssertRangeV)
 
     LAssertRangeV(const LBoxAllocation& input, const LDefinition& temp,
                   const LDefinition& floatTemp1, const LDefinition& floatTemp2)
+      : LInstructionHelper(classOpcode)
     {
         setBoxOperand(Input, input);
         setTemp(0, temp);
         setTemp(1, floatTemp1);
         setTemp(2, floatTemp2);
     }
 
     static const size_t Input = 0;
@@ -9277,131 +10056,157 @@ class LAssertRangeV : public LInstructio
     }
 };
 
 class LAssertResultT : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(AssertResultT)
 
-    explicit LAssertResultT(const LAllocation& input) {
+    explicit LAssertResultT(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 
     const LAllocation* input() {
         return getOperand(0);
     }
 };
 
 class LAssertResultV : public LInstructionHelper<0, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(AssertResultV)
 
     static const size_t Input = 0;
 
-    explicit LAssertResultV(const LBoxAllocation& input) {
+    explicit LAssertResultV(const LBoxAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
     }
 };
 
 class LRecompileCheck : public LInstructionHelper<0, 0, 1>
 {
   public:
     LIR_HEADER(RecompileCheck)
 
-    explicit LRecompileCheck(const LDefinition& scratch) {
+    explicit LRecompileCheck(const LDefinition& scratch)
+      : LInstructionHelper(classOpcode)
+    {
         setTemp(0, scratch);
     }
 
     const LDefinition* scratch() {
         return getTemp(0);
     }
     MRecompileCheck* mir() {
         return mir_->toRecompileCheck();
     }
 };
 
 class LLexicalCheck : public LInstructionHelper<0, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(LexicalCheck)
 
-    explicit LLexicalCheck(const LBoxAllocation& input) {
+    explicit LLexicalCheck(const LBoxAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(Input, input);
     }
 
     MLexicalCheck* mir() {
         return mir_->toLexicalCheck();
     }
 
     static const size_t Input = 0;
 };
 
 class LThrowRuntimeLexicalError : public LCallInstructionHelper<0, 0, 0>
 {
   public:
     LIR_HEADER(ThrowRuntimeLexicalError)
 
+    LThrowRuntimeLexicalError()
+      : LCallInstructionHelper(classOpcode)
+    {}
+
     MThrowRuntimeLexicalError* mir() {
         return mir_->toThrowRuntimeLexicalError();
     }
 };
 
 class LGlobalNameConflictsCheck : public LInstructionHelper<0, 0, 0>
 {
   public:
     LIR_HEADER(GlobalNameConflictsCheck)
 
+    LGlobalNameConflictsCheck()
+      : LInstructionHelper(classOpcode)
+    {}
+
     MGlobalNameConflictsCheck* mir() {
         return mir_->toGlobalNameConflictsCheck();
     }
 };
 
 class LMemoryBarrier : public LInstructionHelper<0, 0, 0>
 {
   private:
     const MemoryBarrierBits type_;
 
   public:
     LIR_HEADER(MemoryBarrier)
 
     // The parameter 'type' is a bitwise 'or' of the barrier types needed,
     // see AtomicOp.h.
-    explicit LMemoryBarrier(MemoryBarrierBits type) : type_(type)
+    explicit LMemoryBarrier(MemoryBarrierBits type)
+      : LInstructionHelper(classOpcode),
+        type_(type)
     {
         MOZ_ASSERT((type_ & ~MembarAllbits) == MembarNobits);
     }
 
     MemoryBarrierBits type() const {
         return type_;
     }
 };
 
 class LDebugger : public LCallInstructionHelper<0, 0, 2>
 {
   public:
     LIR_HEADER(Debugger)
 
-    LDebugger(const LDefinition& temp1, const LDefinition& temp2) {
+    LDebugger(const LDefinition& temp1, const LDefinition& temp2)
+      : LCallInstructionHelper(classOpcode)
+    {
         setTemp(0, temp1);
         setTemp(1, temp2);
     }
 };
 
 class LNewTarget : public LInstructionHelper<BOX_PIECES, 0, 0>
 {
   public:
     LIR_HEADER(NewTarget)
+
+    LNewTarget()
+      : LInstructionHelper(classOpcode)
+    {}
 };
 
 class LArrowNewTarget : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
-    explicit LArrowNewTarget(const LAllocation& callee) {
+    explicit LArrowNewTarget(const LAllocation& callee)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, callee);
     }
 
     LIR_HEADER(ArrowNewTarget)
 
     const LAllocation* callee() {
         return getOperand(0);
     }
@@ -9419,16 +10224,17 @@ class LRandom : public LInstructionHelpe
   public:
     LIR_HEADER(Random)
     LRandom(const LDefinition &temp0, const LDefinition &temp1,
             const LDefinition &temp2
 #ifndef JS_PUNBOX64
             , const LDefinition &temp3, const LDefinition &temp4
 #endif
             )
+      : LInstructionHelper(classOpcode)
     {
         setTemp(0, temp0);
         setTemp(1, temp1);
         setTemp(2, temp2);
 #ifndef JS_PUNBOX64
         setTemp(3, temp3);
         setTemp(4, temp4);
 #endif
@@ -9456,49 +10262,55 @@ class LRandom : public LInstructionHelpe
     }
 };
 
 class LCheckReturn : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CheckReturn)
 
-    LCheckReturn(const LBoxAllocation& retVal, const LBoxAllocation& thisVal) {
+    LCheckReturn(const LBoxAllocation& retVal, const LBoxAllocation& thisVal)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(ReturnValue, retVal);
         setBoxOperand(ThisValue, thisVal);
     }
 
     static const size_t ReturnValue = 0;
     static const size_t ThisValue = BOX_PIECES;
 };
 
 class LCheckIsObj : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CheckIsObj)
 
     static const size_t CheckValue = 0;
 
-    explicit LCheckIsObj(const LBoxAllocation& value) {
+    explicit LCheckIsObj(const LBoxAllocation& value)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(CheckValue, value);
     }
 
     MCheckIsObj* mir() const {
         return mir_->toCheckIsObj();
     }
 };
 
 class LCheckIsCallable : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(CheckIsCallable)
 
     static const size_t CheckValue = 0;
 
-    LCheckIsCallable(const LBoxAllocation& value, const LDefinition& temp) {
+    LCheckIsCallable(const LBoxAllocation& value, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setBoxOperand(CheckValue, value);
         setTemp(0, temp);
     }
 
     const LDefinition* temp() {
         return getTemp(0);
     }
 
@@ -9509,41 +10321,46 @@ class LCheckIsCallable : public LInstruc
 
 class LCheckObjCoercible : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CheckObjCoercible)
 
     static const size_t CheckValue = 0;
 
-    explicit LCheckObjCoercible(const LBoxAllocation& value) {
+    explicit LCheckObjCoercible(const LBoxAllocation& value)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(CheckValue, value);
     }
 };
 
 class LDebugCheckSelfHosted : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(DebugCheckSelfHosted)
 
     static const size_t CheckValue = 0;
 
-    explicit LDebugCheckSelfHosted(const LBoxAllocation& value) {
+    explicit LDebugCheckSelfHosted(const LBoxAllocation& value)
+      : LCallInstructionHelper(classOpcode)
+    {
         setBoxOperand(CheckValue, value);
     }
 };
 
 class LFinishBoundFunctionInit : public LInstructionHelper<0, 3, 2>
 {
   public:
     LIR_HEADER(FinishBoundFunctionInit)
 
     LFinishBoundFunctionInit(const LAllocation& bound, const LAllocation& target,
                              const LAllocation& argCount, const LDefinition& temp1,
                              const LDefinition& temp2)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, bound);
         setOperand(1, target);
         setOperand(2, argCount);
         setTemp(0, temp1);
         setTemp(1, temp2);
     }
 
@@ -9565,16 +10382,17 @@ class LFinishBoundFunctionInit : public 
 };
 
 class LIsPackedArray : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(IsPackedArray)
 
     LIsPackedArray(const LAllocation& array, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, array);
         setTemp(0, temp);
     }
 
     const LAllocation* array() {
         return getOperand(0);
     }
@@ -9584,16 +10402,17 @@ class LIsPackedArray : public LInstructi
 };
 
 class LGetPrototypeOf : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(GetPrototypeOf)
 
     explicit LGetPrototypeOf(const LAllocation& target)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, target);
     }
 
     const LAllocation* target() {
         return getOperand(0);
     }
 };
--- a/js/src/jit/shared/Lowering-shared-inl.h
+++ b/js/src/jit/shared/Lowering-shared-inl.h
@@ -465,16 +465,36 @@ void
 LIRGeneratorShared::ensureDefined(MDefinition* mir)
 {
     if (mir->isEmittedAtUses()) {
         mir->toInstruction()->accept(this);
         MOZ_ASSERT(mir->isLowered());
     }
 }
 
+template <typename LClass, typename... Args>
+LClass*
+LIRGeneratorShared::allocateVariadic(uint32_t numOperands, Args&&... args)
+{
+    size_t numBytes = sizeof(LClass) + numOperands * sizeof(LAllocation);
+    void* buf = alloc().allocate(numBytes);
+    if (!buf)
+        return nullptr;
+
+    LClass* ins = static_cast<LClass*>(buf);
+    new(ins) LClass(numOperands, mozilla::Forward<Args>(args)...);
+
+    ins->initOperandsOffset(sizeof(LClass));
+
+    for (uint32_t i = 0; i < numOperands; i++)
+        ins->setOperand(i, LAllocation());
+
+    return ins;
+}
+
 LUse
 LIRGeneratorShared::useRegister(MDefinition* mir)
 {
     return use(mir, LUse(LUse::REGISTER));
 }
 
 LUse
 LIRGeneratorShared::useRegisterAtStart(MDefinition* mir)
--- a/js/src/jit/shared/Lowering-shared.h
+++ b/js/src/jit/shared/Lowering-shared.h
@@ -226,16 +226,19 @@ class LIRGeneratorShared : public MDefin
 
     // Rather than defining a new virtual register, sets |ins| to have the same
     // virtual register as |as|.
     inline void redefine(MDefinition* ins, MDefinition* as);
 
     // Redefine a sin/cos call to sincos.
     inline void redefine(MDefinition* def, MDefinition* as, MMathFunction::Function func);
 
+    template <typename LClass, typename... Args>
+    inline LClass* allocateVariadic(uint32_t numOperands, Args&&... args);
+
     TempAllocator& alloc() const {
         return graph.alloc();
     }
 
     uint32_t getVirtualRegister() {
         uint32_t vreg = lirGraph_.getVirtualRegister();
 
         // If we run out of virtual registers, mark code generation as having
--- a/js/src/jit/x64/LIR-x64.h
+++ b/js/src/jit/x64/LIR-x64.h
@@ -10,48 +10,50 @@
 namespace js {
 namespace jit {
 
 // Given an untyped input, guards on whether it's a specific type and returns
 // the unboxed payload.
 class LUnboxBase : public LInstructionHelper<1, 1, 0>
 {
   public:
-    explicit LUnboxBase(const LAllocation& input) {
+    LUnboxBase(LNode::Opcode op, const LAllocation& input)
+      : LInstructionHelper<1, 1, 0>(op)
+    {
         setOperand(0, input);
     }
 
     static const size_t Input = 0;
 
     MUnbox* mir() const {
         return mir_->toUnbox();
     }
 };
 
 class LUnbox : public LUnboxBase {
   public:
     LIR_HEADER(Unbox)
 
     explicit LUnbox(const LAllocation& input)
-      : LUnboxBase(input)
+      : LUnboxBase(classOpcode, input)
     { }
 
     const char* extraName() const {
         return StringFromMIRType(mir()->type());
     }
 };
 
 class LUnboxFloatingPoint : public LUnboxBase {
     MIRType type_;
 
   public:
     LIR_HEADER(UnboxFloatingPoint)
 
     LUnboxFloatingPoint(const LAllocation& input, MIRType type)
-      : LUnboxBase(input),
+      : LUnboxBase(classOpcode, input),
         type_(type)
     { }
 
     MIRType type() const {
         return type_;
     }
     const char* extraName() const {
         return StringFromMIRType(type_);
@@ -59,38 +61,44 @@ class LUnboxFloatingPoint : public LUnbo
 };
 
 // Convert a 32-bit unsigned integer to a double.
 class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(WasmUint32ToDouble)
 
-    explicit LWasmUint32ToDouble(const LAllocation& input) {
+    explicit LWasmUint32ToDouble(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 // Convert a 32-bit unsigned integer to a float32.
 class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(WasmUint32ToFloat32)
 
-    explicit LWasmUint32ToFloat32(const LAllocation& input) {
+    explicit LWasmUint32ToFloat32(const LAllocation& input)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
     }
 };
 
 class LDivOrModI64 : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(DivOrModI64)
 
-    LDivOrModI64(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
+    LDivOrModI64(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
+      : LBinaryMath(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
 
     const LDefinition* remainder() {
         return getTemp(0);
     }
@@ -120,17 +128,19 @@ class LDivOrModI64 : public LBinaryMath<
 // This class performs a simple x86 'div', yielding either a quotient or
 // remainder depending on whether this instruction is defined to output
 // rax (quotient) or rdx (remainder).
 class LUDivOrModI64 : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(UDivOrModI64);
 
-    LUDivOrModI64(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
+    LUDivOrModI64(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
+      : LBinaryMath(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
 
     const LDefinition* remainder() {
         return getTemp(0);
     }
@@ -158,17 +168,19 @@ class LUDivOrModI64 : public LBinaryMath
     }
 };
 
 class LWasmTruncateToInt64 : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(WasmTruncateToInt64);
 
-    LWasmTruncateToInt64(const LAllocation& in, const LDefinition& temp) {
+    LWasmTruncateToInt64(const LAllocation& in, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, in);
         setTemp(0, temp);
     }
 
     MWasmTruncateToInt64* mir() const {
         return mir_->toWasmTruncateToInt64();
     }
 
--- a/js/src/jit/x86-shared/LIR-x86-shared.h
+++ b/js/src/jit/x86-shared/LIR-x86-shared.h
@@ -10,17 +10,19 @@
 namespace js {
 namespace jit {
 
 class LDivI : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(DivI)
 
-    LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
+    LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
+      : LBinaryMath(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
 
     const char* extraName() const {
         if (mir()->isTruncated()) {
             if (mir()->canBeNegativeZero()) {
@@ -48,17 +50,19 @@ class LDivPowTwoI : public LBinaryMath<0
 {
     const int32_t shift_;
     const bool negativeDivisor_;
 
   public:
     LIR_HEADER(DivPowTwoI)
 
     LDivPowTwoI(const LAllocation& lhs, const LAllocation& lhsCopy, int32_t shift, bool negativeDivisor)
-      : shift_(shift), negativeDivisor_(negativeDivisor)
+      : LBinaryMath(classOpcode),
+        shift_(shift),
+        negativeDivisor_(negativeDivisor)
     {
         setOperand(0, lhs);
         setOperand(1, lhsCopy);
     }
 
     const LAllocation* numerator() {
         return getOperand(0);
     }
@@ -79,17 +83,18 @@ class LDivPowTwoI : public LBinaryMath<0
 class LDivOrModConstantI : public LInstructionHelper<1, 1, 1>
 {
     const int32_t denominator_;
 
   public:
     LIR_HEADER(DivOrModConstantI)
 
     LDivOrModConstantI(const LAllocation& lhs, int32_t denominator, const LDefinition& temp)
-    : denominator_(denominator)
+      : LInstructionHelper(classOpcode),
+        denominator_(denominator)
     {
         setOperand(0, lhs);
         setTemp(0, temp);
     }
 
     const LAllocation* numerator() {
         return getOperand(0);
     }
@@ -107,17 +112,19 @@ class LDivOrModConstantI : public LInstr
     }
 };
 
 class LModI : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(ModI)
 
-    LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
+    LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
+      : LBinaryMath(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
 
     const char* extraName() const {
         return mir()->isTruncated() ? "Truncated" : nullptr;
     }
@@ -132,17 +139,19 @@ class LModI : public LBinaryMath<1>
 
 // This class performs a simple x86 'div', yielding either a quotient or remainder depending on
 // whether this instruction is defined to output eax (quotient) or edx (remainder).
 class LUDivOrMod : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(UDivOrMod);
 
-    LUDivOrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
+    LUDivOrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
+      : LBinaryMath(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp);
     }
 
     const LDefinition* remainder() {
         return getTemp(0);
     }
@@ -178,17 +187,18 @@ class LUDivOrMod : public LBinaryMath<1>
 class LUDivOrModConstant : public LInstructionHelper<1, 1, 1>
 {
     const uint32_t denominator_;
 
   public:
     LIR_HEADER(UDivOrModConstant)
 
     LUDivOrModConstant(const LAllocation &lhs, uint32_t denominator, const LDefinition& temp)
-      : denominator_(denominator)
+      : LInstructionHelper(classOpcode),
+        denominator_(denominator)
     {
         setOperand(0, lhs);
         setTemp(0, temp);
     }
 
     const LAllocation* numerator() {
         return getOperand(0);
     }
@@ -219,17 +229,18 @@ class LUDivOrModConstant : public LInstr
 class LModPowTwoI : public LInstructionHelper<1,1,0>
 {
     const int32_t shift_;
 
   public:
     LIR_HEADER(ModPowTwoI)
 
     LModPowTwoI(const LAllocation& lhs, int32_t shift)
-      : shift_(shift)
+      : LInstructionHelper(classOpcode),
+        shift_(shift)
     {
         setOperand(0, lhs);
     }
 
     int32_t shift() const {
         return shift_;
     }
     const LDefinition* remainder() {
@@ -243,16 +254,17 @@ class LModPowTwoI : public LInstructionH
 // Takes a tableswitch with an integer to decide
 class LTableSwitch : public LInstructionHelper<0, 1, 2>
 {
   public:
     LIR_HEADER(TableSwitch)
 
     LTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
                  const LDefinition& jumpTablePointer, MTableSwitch* ins)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, in);
         setTemp(0, inputCopy);
         setTemp(1, jumpTablePointer);
         setMir(ins);
     }
 
     MTableSwitch* mir() const {
@@ -274,16 +286,17 @@ class LTableSwitch : public LInstruction
 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3>
 {
   public:
     LIR_HEADER(TableSwitchV)
 
     LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
                   const LDefinition& floatCopy, const LDefinition& jumpTablePointer,
                   MTableSwitch* ins)
+      : LInstructionHelper(classOpcode)
     {
         setBoxOperand(InputValue, input);
         setTemp(0, inputCopy);
         setTemp(1, floatCopy);
         setTemp(2, jumpTablePointer);
         setMir(ins);
     }
 
@@ -304,17 +317,19 @@ class LTableSwitchV : public LInstructio
     }
 };
 
 class LMulI : public LBinaryMath<0, 1>
 {
   public:
     LIR_HEADER(MulI)
 
-    LMulI(const LAllocation& lhs, const LAllocation& rhs, const LAllocation& lhsCopy) {
+    LMulI(const LAllocation& lhs, const LAllocation& rhs, const LAllocation& lhsCopy)
+      : LBinaryMath(classOpcode)
+    {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setOperand(2, lhsCopy);
     }
 
     const char* extraName() const {
         return (mir()->mode() == MMul::Integer)
                ? "Integer"
@@ -331,16 +346,17 @@ class LMulI : public LBinaryMath<0, 1>
 
 // Constructs an int32x4 SIMD value.
 class LSimdValueInt32x4 : public LInstructionHelper<1, 4, 0>
 {
   public:
     LIR_HEADER(SimdValueInt32x4)
     LSimdValueInt32x4(const LAllocation& x, const LAllocation& y,
                       const LAllocation& z, const LAllocation& w)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, x);
         setOperand(1, y);
         setOperand(2, z);
         setOperand(3, w);
     }
 
     MSimdValueX4* mir() const {
@@ -351,16 +367,17 @@ class LSimdValueInt32x4 : public LInstru
 // Constructs a float32x4 SIMD value, optimized for x86 family
 class LSimdValueFloat32x4 : public LInstructionHelper<1, 4, 1>
 {
   public:
     LIR_HEADER(SimdValueFloat32x4)
     LSimdValueFloat32x4(const LAllocation& x, const LAllocation& y,
                         const LAllocation& z, const LAllocation& w,
                         const LDefinition& copyY)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, x);
         setOperand(1, y);
         setOperand(2, z);
         setOperand(3, w);
 
         setTemp(0, copyY);
     }
@@ -370,17 +387,19 @@ class LSimdValueFloat32x4 : public LInst
     }
 };
 
 class LInt64ToFloatingPoint : public LInstructionHelper<1, INT64_PIECES, 1>
 {
   public:
     LIR_HEADER(Int64ToFloatingPoint);
 
-    explicit LInt64ToFloatingPoint(const LInt64Allocation& in, const LDefinition& temp) {
+    LInt64ToFloatingPoint(const LInt64Allocation& in, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setInt64Operand(0, in);
         setTemp(0, temp);
     }
 
     MInt64ToFloatingPoint* mir() const {
         return mir_->toInt64ToFloatingPoint();
     }
 
--- a/js/src/jit/x86-shared/Lowering-x86-shared.cpp
+++ b/js/src/jit/x86-shared/Lowering-x86-shared.cpp
@@ -930,24 +930,24 @@ LIRGeneratorX86Shared::visitSimdGeneralS
         LDefinition t;
         if (ins->type() == MIRType::Int8x16)
             t = tempFixed(ebx);
         else
             t = temp();
 #else
         LDefinition t = temp();
 #endif
-        lir = new (alloc()) LSimdGeneralShuffleI(t, numOperands);
+        lir = allocateVariadic<LSimdGeneralShuffleI>(numOperands, t);
     } else if (ins->type() == MIRType::Float32x4) {
-        lir = new (alloc()) LSimdGeneralShuffleF(temp(), numOperands);
+        lir = allocateVariadic<LSimdGeneralShuffleF>(numOperands, temp());
     } else {
         MOZ_CRASH("Unknown SIMD kind when doing a shuffle");
     }
 
-    if (!lir->init(alloc()))
+    if (!lir)
         return;
 
     for (unsigned i = 0; i < ins->numVectors(); i++) {
         MOZ_ASSERT(IsSimdType(ins->vector(i)->type()));
         lir->setOperand(i, useRegister(ins->vector(i)));
     }
 
     for (unsigned i = 0; i < ins->numLanes(); i++) {
--- a/js/src/jit/x86/LIR-x86.h
+++ b/js/src/jit/x86/LIR-x86.h
@@ -13,17 +13,18 @@ namespace jit {
 class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1>
 {
     MIRType type_;
 
   public:
     LIR_HEADER(BoxFloatingPoint);
 
     LBoxFloatingPoint(const LAllocation& in, const LDefinition& temp, MIRType type)
-      : type_(type)
+      : LInstructionHelper(classOpcode),
+        type_(type)
     {
         MOZ_ASSERT(IsFloatingPointType(type));
         setOperand(0, in);
         setTemp(0, temp);
     }
 
     MIRType type() const {
         return type_;
@@ -33,16 +34,20 @@ class LBoxFloatingPoint : public LInstru
     }
 };
 
 class LUnbox : public LInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(Unbox);
 
+    LUnbox()
+      : LInstructionHelper(classOpcode)
+    {}
+
     MUnbox* mir() const {
         return mir_->toUnbox();
     }
     const LAllocation* payload() {
         return getOperand(0);
     }
     const LAllocation* type() {
         return getOperand(1);
@@ -57,17 +62,18 @@ class LUnboxFloatingPoint : public LInst
     MIRType type_;
 
   public:
     LIR_HEADER(UnboxFloatingPoint);
 
     static const size_t Input = 0;
 
     LUnboxFloatingPoint(const LBoxAllocation& input, MIRType type)
-      : type_(type)
+      : LInstructionHelper(classOpcode),
+        type_(type)
     {
         setBoxOperand(Input, input);
     }
 
     MUnbox* mir() const {
         return mir_->toUnbox();
     }
 
@@ -80,32 +86,36 @@ class LUnboxFloatingPoint : public LInst
 };
 
 // Convert a 32-bit unsigned integer to a double.
 class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(WasmUint32ToDouble)
 
-    LWasmUint32ToDouble(const LAllocation& input, const LDefinition& temp) {
+    LWasmUint32ToDouble(const LAllocation& input, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
         setTemp(0, temp);
     }
     const LDefinition* temp() {
         return getTemp(0);
     }
 };
 
 // Convert a 32-bit unsigned integer to a float32.
 class LWasmUint32ToFloat32: public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(WasmUint32ToFloat32)
 
-    LWasmUint32ToFloat32(const LAllocation& input, const LDefinition& temp) {
+    LWasmUint32ToFloat32(const LAllocation& input, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
+    {
         setOperand(0, input);
         setTemp(0, temp);
     }
     const LDefinition* temp() {
         return getTemp(0);
     }
 };
 
@@ -113,16 +123,17 @@ class LDivOrModI64 : public LCallInstruc
 {
   public:
     LIR_HEADER(DivOrModI64)
 
     static const size_t Lhs = 0;
     static const size_t Rhs = INT64_PIECES;
 
     LDivOrModI64(const LInt64Allocation& lhs, const LInt64Allocation& rhs, const LDefinition& temp)
+      : LCallInstructionHelper(classOpcode)
     {
         setInt64Operand(Lhs, lhs);
         setInt64Operand(Rhs, rhs);
         setTemp(0, temp);
     }
 
     MBinaryArithInstruction* mir() const {
         MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
@@ -153,16 +164,17 @@ class LUDivOrModI64 : public LCallInstru
 {
   public:
     LIR_HEADER(UDivOrModI64)
 
     static const size_t Lhs = 0;
     static const size_t Rhs = INT64_PIECES;
 
     LUDivOrModI64(const LInt64Allocation& lhs, const LInt64Allocation& rhs, const LDefinition& temp)
+      : LCallInstructionHelper(classOpcode)
     {
         setInt64Operand(Lhs, lhs);
         setInt64Operand(Rhs, rhs);
         setTemp(0, temp);
     }
 
     MBinaryArithInstruction* mir() const {
         MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
@@ -190,16 +202,17 @@ class LUDivOrModI64 : public LCallInstru
 };
 
 class LWasmTruncateToInt64 : public LInstructionHelper<INT64_PIECES, 1, 1>
 {
   public:
     LIR_HEADER(WasmTruncateToInt64);
 
     LWasmTruncateToInt64(const LAllocation& in, const LDefinition& temp)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, in);
         setTemp(0, temp);
     }
 
     MWasmTruncateToInt64* mir() const {
         return mir_->toWasmTruncateToInt64();
     }
@@ -211,16 +224,17 @@ class LWasmTruncateToInt64 : public LIns
 
 class LWasmAtomicLoadI64 : public LInstructionHelper<INT64_PIECES, 2, 2>
 {
   public:
     LIR_HEADER(WasmAtomicLoadI64);
 
     LWasmAtomicLoadI64(const LAllocation& memoryBase, const LAllocation& ptr, const LDefinition& t1,
                        const LDefinition& t2)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, memoryBase);
         setOperand(1, ptr);
         setTemp(0, t1);
         setTemp(1, t2);
     }
 
     MWasmLoad* mir() const {
@@ -243,16 +257,17 @@ class LWasmAtomicLoadI64 : public LInstr
 class LWasmAtomicStoreI64 : public LInstructionHelper<0, 2 + INT64_PIECES, 2>
 {
   public:
     LIR_HEADER(WasmAtomicStoreI64);
 
     LWasmAtomicStoreI64(const LAllocation& memoryBase, const LAllocation& ptr,
                         const LInt64Allocation& value, const LDefinition& t1,
                         const LDefinition& t2)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, memoryBase);
         setOperand(1, ptr);
         setInt64Operand(2, value);
         setTemp(0, t1);
         setTemp(1, t2);
     }
 
@@ -278,16 +293,17 @@ class LWasmAtomicStoreI64 : public LInst
 
 class LWasmCompareExchangeI64 : public LInstructionHelper<INT64_PIECES, 2 + 2*INT64_PIECES, 0>
 {
   public:
     LIR_HEADER(WasmCompareExchangeI64);
 
     LWasmCompareExchangeI64(const LAllocation& memoryBase, const LAllocation& ptr,
                             const LInt64Allocation& expected, const LInt64Allocation& replacement)
+      : LInstructionHelper(classOpcode)
     {
         setOperand(0, memoryBase);
         setOperand(1, ptr);
         setInt64Operand(2, expected);
         setInt64Operand(2 + INT64_PIECES, replacement);
     }
 
     MWasmCompareExchangeHeap* mir() const {
@@ -311,17 +327,18 @@ class LWasmAtomicExchangeI64 : public LI
 {
     const wasm::MemoryAccessDesc& access_;
 
   public:
     LIR_HEADER(WasmAtomicExchangeI64);
 
     LWasmAtomicExchangeI64(const LAllocation& memoryBase, const LAllocation& ptr,
                            const LInt64Allocation& value, const wasm::MemoryAccessDesc& access)
-      : access_(access)
+      : LInstructionHelper(classOpcode),
+        access_(access)
     {
         setOperand(0, memoryBase);
         setOperand(1, ptr);
         setInt64Operand(2, value);
     }
 
     const LAllocation* memoryBase() {
         return getOperand(0);
@@ -343,17 +360,18 @@ class LWasmAtomicBinopI64 : public LInst
     AtomicOp op_;
 
   public:
     LIR_HEADER(WasmAtomicBinopI64);
 
     LWasmAtomicBinopI64(const LAllocation& memoryBase, const LAllocation& ptr,
                         const LInt64Allocation& value, const wasm::MemoryAccessDesc& access,
                         AtomicOp op)
-      : access_(access),
+      : LInstructionHelper(classOpcode),
+        access_(access),
         op_(op)
     {
         setOperand(0, memoryBase);
         setOperand(1, ptr);
         setInt64Operand(2, value);
     }
 
     const LAllocation* memoryBase() {
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -49,28 +49,16 @@ using mozilla::Some;
 
 namespace js {
 
 /**
  * Maximum number of saved frames returned for an async stack.
  */
 const uint32_t ASYNC_STACK_MAX_FRAME_COUNT = 60;
 
-/* static */ Maybe<LiveSavedFrameCache::FramePtr>
-LiveSavedFrameCache::getFramePtr(const FrameIter& iter)
-{
-    if (iter.hasUsableAbstractFramePtr())
-        return Some(FramePtr(iter.abstractFramePtr()));
-
-    if (iter.isPhysicalIonFrame())
-        return Some(FramePtr(iter.physicalIonFrame()));
-
-    return Nothing();
-}
-
 void
 LiveSavedFrameCache::trace(JSTracer* trc)
 {
     if (!initialized())
         return;
 
     for (auto* entry = frames->begin(); entry < frames->end(); entry++) {
         TraceEdge(trc,
@@ -78,51 +66,43 @@ LiveSavedFrameCache::trace(JSTracer* trc
                   "LiveSavedFrameCache::frames SavedFrame");
     }
 }
 
 bool
 LiveSavedFrameCache::insert(JSContext* cx, FramePtr& framePtr, const jsbytecode* pc,
                             HandleSavedFrame savedFrame)
 {
+    MOZ_ASSERT(savedFrame);
     MOZ_ASSERT(initialized());
 
     if (!frames->emplaceBack(framePtr, pc, savedFrame)) {
         ReportOutOfMemory(cx);
         return false;
     }
 
-    // Safe to dereference the cache key because the stack frames are still
-    // live. After this point, they should never be dereferenced again.
-    if (framePtr.is<AbstractFramePtr>())
-        framePtr.as<AbstractFramePtr>().setHasCachedSavedFrame();
-    else
-        framePtr.as<jit::CommonFrameLayout*>()->setHasCachedSavedFrame();
+    framePtr.setHasCachedSavedFrame();
 
     return true;
 }
 
 void
-LiveSavedFrameCache::find(JSContext* cx, FrameIter& frameIter, MutableHandleSavedFrame frame) const
+LiveSavedFrameCache::find(JSContext* cx, FramePtr& framePtr, const jsbytecode* pc,
+                          MutableHandleSavedFrame frame) const
 {
     MOZ_ASSERT(initialized());
-    MOZ_ASSERT(!frameIter.done());
-    MOZ_ASSERT(frameIter.hasCachedSavedFrame());
 
-    Maybe<FramePtr> maybeFramePtr = getFramePtr(frameIter);
-    MOZ_ASSERT(maybeFramePtr.isSome());
-
-    FramePtr framePtr(*maybeFramePtr);
-    const jsbytecode* pc = frameIter.pc();
+    MOZ_ASSERT(framePtr.hasCachedSavedFrame());
+    Key key(framePtr);
     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;
@@ -1316,16 +1296,17 @@ SavedStacks::insertFrames(JSContext* cx,
     // pointers on the first pass, and then we fill in the parent pointers as we
     // return in the second pass.
 
     Activation* asyncActivation = nullptr;
     RootedSavedFrame asyncStack(cx, nullptr);
     RootedString asyncCause(cx, nullptr);
     bool parentIsInCache = false;
     RootedSavedFrame cachedFrame(cx, nullptr);
+    Maybe<LiveSavedFrameCache::FramePtr> framePtr = LiveSavedFrameCache::FramePtr::create(iter);
 
     // Accumulate the vector of Lookup objects in |stackChain|.
     SavedFrame::AutoLookupVector stackChain(cx);
     while (!iter.done()) {
         Activation& activation = *iter.activation();
 
         if (asyncActivation && asyncActivation != &activation) {
             // We found an async stack in the previous activation, and we
@@ -1372,22 +1353,21 @@ SavedStacks::insertFrames(JSContext* cx,
             AutoCompartmentUnchecked ac(cx, iter.compartment());
             if (!cx->compartment()->savedStacks().getLocation(cx, iter, &location))
                 return false;
         }