Merge inbound to mozilla-central. a=merge
authorBrindusan Cristian <cbrindusan@mozilla.com>
Thu, 08 Mar 2018 20:00:36 +0200
changeset 462213 55d91695f4bb951c224005155baef054a786c1f7
parent 462212 28ec88d1b741579f643427a6b96aec6e4f7a44ed (current diff)
parent 462210 0f64845d179b9bf45a6ae38b9b597e3993422fb7 (diff)
child 462214 e18b07e250b1a49de41b3d738d74ea39f5504c0f
child 462233 c5650d15df01218401ce2ae9c57e1db6ae207054
child 462270 1d01aa7f63ade6f7afc41370cd28cfbc35c14f13
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)
reviewersmerge
milestone60.0a1
first release with
nightly linux32
55d91695f4bb / 60.0a1 / 20180308220134 / files
nightly linux64
55d91695f4bb / 60.0a1 / 20180308220134 / files
nightly mac
55d91695f4bb / 60.0a1 / 20180308220134 / files
nightly win32
55d91695f4bb / 60.0a1 / 20180308220134 / files
nightly win64
55d91695f4bb / 60.0a1 / 20180308220134 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
gfx/layers/Layers.cpp
gfx/layers/ipc/CompositorBridgeParent.cpp
--- 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/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/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;
         }
 
         // The bit set means that the next older parent (frame, pc) pair *must*
         // be in the cache.
         if (capture.is<JS::AllFrames>())
-            parentIsInCache = iter.hasCachedSavedFrame();
+            parentIsInCache = framePtr && framePtr->hasCachedSavedFrame();
 
         auto principals = iter.compartment()->principals();
         auto displayAtom = (iter.isWasm() || iter.isFunctionFrame()) ? iter.functionDisplayAtom() : nullptr;
 
-        Maybe<LiveSavedFrameCache::FramePtr> framePtr = LiveSavedFrameCache::getFramePtr(iter);
         MOZ_ASSERT_IF(framePtr && !iter.isWasm(), iter.pc());
 
         if (!stackChain->emplaceBack(location.source(),
                                      location.line(),
                                      location.column(),
                                      displayAtom,
                                      nullptr,
                                      nullptr,
@@ -1403,25 +1383,26 @@ SavedStacks::insertFrames(JSContext* cx,
         if (captureIsSatisfied(cx, principals, location.source(), capture)) {
             // The frame we just saved was the last one we were asked to save.
             // If we had an async stack, ensure we don't use any of its frames.
             asyncStack.set(nullptr);
             break;
         }
 
         ++iter;
+        framePtr = LiveSavedFrameCache::FramePtr::create(iter);
 
         if (parentIsInCache &&
-            !iter.done() &&
-            iter.hasCachedSavedFrame())
+            framePtr &&
+            framePtr->hasCachedSavedFrame())
         {
             auto* cache = activation.getLiveSavedFrameCache(cx);
             if (!cache)
                 return false;
-            cache->find(cx, iter, &cachedFrame);
+            cache->find(cx, *framePtr, iter.pc(), &cachedFrame);
             if (cachedFrame)
                 break