зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. CLOSED TREE
This commit is contained in:
Коммит
67adc3007a
|
@ -2253,6 +2253,10 @@ this.PlacesPanelview = class extends PlacesViewBase {
|
|||
}
|
||||
}
|
||||
|
||||
_isPopupOpen() {
|
||||
return PanelView.forNode(this._viewElt).active;
|
||||
}
|
||||
|
||||
_onPopupHidden(event) {
|
||||
let panelview = event.originalTarget;
|
||||
let placesNode = panelview._placesNode;
|
||||
|
|
|
@ -95,6 +95,7 @@ skip-if = (os == 'win' && ccov) # Bug 1423667
|
|||
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
|
||||
|
|
|
@ -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;
|
||||
});
|
|
@ -83,6 +83,7 @@ const ErrorDocs = {
|
|||
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";
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
#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;
|
||||
|
@ -248,32 +249,63 @@ protected:
|
|||
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.
|
||||
|
|
|
@ -7428,7 +7428,7 @@ nsGlobalWindowInner::PromiseDocumentFlushed(PromiseDocumentFlushedCallback& aCal
|
|||
UniquePtr<PromiseDocumentFlushedResolver> flushResolver(
|
||||
new PromiseDocumentFlushedResolver(resultPromise, aCallback));
|
||||
|
||||
if (!shell->NeedStyleFlush() && !shell->NeedLayoutFlush()) {
|
||||
if (!shell->NeedFlush(FlushType::Style)) {
|
||||
flushResolver->Call();
|
||||
return resultPromise.forget();
|
||||
}
|
||||
|
@ -7523,11 +7523,10 @@ nsGlobalWindowInner::DidRefresh()
|
|||
nsIPresShell* shell = mDoc->GetShell();
|
||||
MOZ_ASSERT(shell);
|
||||
|
||||
if (shell->NeedStyleFlush() || shell->NeedLayoutFlush()) {
|
||||
if (shell->NeedStyleFlush() || shell->HasPendingReflow()) {
|
||||
// By the time our observer fired, something has already invalidated
|
||||
// style or layout - or perhaps we're still in the middle of a flush that
|
||||
// was interrupted. In either case, we'll wait until the next refresh driver
|
||||
// tick instead and try again.
|
||||
// style and maybe layout. We'll wait until the next refresh driver
|
||||
// tick instead.
|
||||
rejectionGuard.release();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -38,82 +38,11 @@ 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),
|
||||
|
@ -127,18 +56,11 @@ nsNodeInfoManager::nsNodeInfoManager()
|
|||
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;
|
||||
|
||||
|
@ -185,8 +107,6 @@ 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?");
|
||||
|
||||
|
@ -207,14 +127,6 @@ nsNodeInfoManager::Init(nsIDocument *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()
|
||||
{
|
||||
|
@ -223,7 +135,9 @@ nsNodeInfoManager::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;
|
||||
|
@ -240,38 +154,30 @@ nsNodeInfoManager::GetNodeInfo(nsAtom *aName, nsAtom *aPrefix,
|
|||
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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -280,6 +186,7 @@ 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);
|
||||
|
@ -289,43 +196,28 @@ nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsAtom *aPrefix,
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -449,17 +341,12 @@ nsNodeInfoManager::RemoveNodeInfo(NodeInfo *aNodeInfo)
|
|||
}
|
||||
}
|
||||
|
||||
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!!!");
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,11 @@
|
|||
#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;
|
||||
|
@ -27,12 +28,6 @@ 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
|
||||
|
@ -155,15 +150,20 @@ protected:
|
|||
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.
|
||||
|
|
|
@ -31,9 +31,7 @@ const gWindowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|||
*/
|
||||
function assertNoFlushesRequired() {
|
||||
Assert.ok(!gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_STYLE),
|
||||
"No style flushes are required.");
|
||||
Assert.ok(!gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_LAYOUT),
|
||||
"No layout flushes are required.");
|
||||
"No flushes are required.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,10 +39,8 @@ function assertNoFlushesRequired() {
|
|||
* are required.
|
||||
*/
|
||||
function assertFlushesRequired() {
|
||||
Assert.ok(gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_STYLE),
|
||||
"Style flush required.");
|
||||
Assert.ok(gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_LAYOUT),
|
||||
"Layout flush required.");
|
||||
"Style and layout flushes are required.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -246,6 +246,17 @@ Event::GetTarget(nsIDOMEventTarget** aTarget)
|
|||
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
|
||||
{
|
||||
|
|
|
@ -171,6 +171,7 @@ public:
|
|||
// void GetType(nsString& aRetval) {}
|
||||
|
||||
EventTarget* GetTarget() const;
|
||||
static bool IsSrcElementEnabled(JSContext* /* unused */, JSObject* /* unused */);
|
||||
EventTarget* GetCurrentTarget() const;
|
||||
|
||||
void ComposedPath(nsTArray<RefPtr<EventTarget>>& aPath);
|
||||
|
|
|
@ -680,6 +680,8 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
|
|||
// 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())) {
|
||||
|
|
|
@ -3,6 +3,19 @@
|
|||
<!--
|
||||
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>
|
||||
|
@ -47,7 +60,6 @@ add_task(async function test_update() {
|
|||
}
|
||||
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.serviceWorkers.idle_timeout", 0],
|
||||
["dom.serviceWorkers.update_delay", 30000],
|
||||
["dom.serviceWorkers.idle_extended_timeout", 299999]]});
|
||||
|
||||
|
@ -60,7 +72,10 @@ add_task(async function test_update() {
|
|||
{ 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
|
||||
|
|
|
@ -10,17 +10,16 @@
|
|||
#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( \
|
||||
|
@ -45,14 +44,6 @@ 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,
|
||||
|
@ -62,26 +53,15 @@ enum SVGTag {
|
|||
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
|
||||
|
@ -90,10 +70,7 @@ SVGElementFactory::Init()
|
|||
void
|
||||
SVGElementFactory::Shutdown()
|
||||
{
|
||||
if (sTagAtomTable) {
|
||||
PL_HashTableDestroy(sTagAtomTable);
|
||||
sTagAtomTable = nullptr;
|
||||
}
|
||||
sTagAtomTable = nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -108,16 +85,8 @@ NS_NewSVGElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& a
|
|||
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();
|
||||
|
|
|
@ -17,6 +17,8 @@ interface Event {
|
|||
readonly attribute DOMString type;
|
||||
[Pure]
|
||||
readonly attribute EventTarget? target;
|
||||
[Pure, BinaryName="target", Func="Event::IsSrcElementEnabled"]
|
||||
readonly attribute EventTarget? srcElement;
|
||||
[Pure]
|
||||
readonly attribute EventTarget? currentTarget;
|
||||
|
||||
|
|
|
@ -1313,7 +1313,7 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS
|
|||
// transform while 2D is expected.
|
||||
idealTransform.ProjectTo2D();
|
||||
}
|
||||
mUseIntermediateSurface = useIntermediateSurface && !GetLocalVisibleRegion().IsEmpty();
|
||||
mUseIntermediateSurface = useIntermediateSurface;
|
||||
if (useIntermediateSurface) {
|
||||
ComputeEffectiveTransformsForChildren(Matrix4x4::From2D(residual));
|
||||
} else {
|
||||
|
|
|
@ -1611,12 +1611,16 @@ CompositorBridgeParent::DeallocPLayerTransactionParent(PLayerTransactionParent*
|
|||
|
||||
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;
|
||||
|
@ -1626,6 +1630,8 @@ void CompositorBridgeParent::AddCompositor(CompositorBridgeParent* compositor, u
|
|||
|
||||
CompositorBridgeParent* CompositorBridgeParent::RemoveCompositor(uint64_t id)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||
|
||||
CompositorMap::iterator it = sCompositorMap->find(id);
|
||||
if (it == sCompositorMap->end()) {
|
||||
return nullptr;
|
||||
|
|
|
@ -1174,7 +1174,8 @@ BacktrackingAllocator::mergeAndQueueRegisters()
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -72,11 +72,6 @@ class BaselineFrame
|
|||
// 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.
|
||||
|
@ -312,13 +307,6 @@ class BaselineFrame
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/ScopeExit.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include "jit/JitSpewer.h"
|
||||
#include "jit/MIR.h"
|
||||
|
@ -480,6 +481,19 @@ 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)
|
||||
{
|
||||
|
@ -488,13 +502,10 @@ LNode::printOperands(GenericPrinter& 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
|
||||
|
@ -516,6 +527,30 @@ LInstruction::assignSnapshot(LSnapshot* snapshot)
|
|||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
|
@ -532,7 +567,7 @@ GetSuccessorHelper(const LControlInstructionHelper<Succs, Operands, Temps>* ins,
|
|||
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");
|
||||
|
@ -573,21 +608,19 @@ LNode::dump(GenericPrinter& out)
|
|||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -689,3 +722,8 @@ LMoveGroup::printOperands(GenericPrinter& out)
|
|||
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
|
||||
|
|
138
js/src/jit/LIR.h
138
js/src/jit/LIR.h
|
@ -665,44 +665,50 @@ class LNode
|
|||
|
||||
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";
|
||||
}
|
||||
|
@ -718,7 +724,9 @@ class LNode
|
|||
public:
|
||||
const char* getExtraName() const;
|
||||
|
||||
virtual Opcode op() const = 0;
|
||||
Opcode op() const {
|
||||
return Opcode(op_);
|
||||
}
|
||||
|
||||
bool isInstruction() const {
|
||||
return op() != LOp_Phi;
|
||||
|
@ -732,9 +740,6 @@ class LNode
|
|||
return numDefs_;
|
||||
}
|
||||
|
||||
// Returns information about operands.
|
||||
virtual LAllocation* getOperand(size_t index) = 0;
|
||||
|
||||
bool isCall() const {
|
||||
return isCall_;
|
||||
}
|
||||
|
@ -777,19 +782,17 @@ class LNode
|
|||
|
||||
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
|
||||
|
@ -810,8 +813,8 @@ class LInstruction
|
|||
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),
|
||||
|
@ -829,10 +832,27 @@ class LInstruction
|
|||
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.
|
||||
|
@ -841,16 +861,6 @@ class LInstruction
|
|||
}
|
||||
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_;
|
||||
}
|
||||
|
@ -948,7 +958,8 @@ class LPhi final : public LNode
|
|||
LIR_HEADER(Phi)
|
||||
|
||||
LPhi(MPhi* ins, LAllocation* inputs)
|
||||
: LNode(/* nonPhiNumOperands = */ 0,
|
||||
: LNode(classOpcode,
|
||||
/* nonPhiNumOperands = */ 0,
|
||||
/* numDefs = */ 1,
|
||||
/* numTemps = */ 0),
|
||||
inputs_(inputs)
|
||||
|
@ -967,7 +978,7 @@ class LPhi final : public LNode
|
|||
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];
|
||||
}
|
||||
|
@ -1085,11 +1096,13 @@ namespace details {
|
|||
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];
|
||||
|
@ -1160,12 +1173,21 @@ class LInstructionHelper : public details::LInstructionFixedDefsTempsHelper<Defs
|
|||
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) {
|
||||
|
@ -1200,29 +1222,18 @@ class LInstructionHelper : public details::LInstructionFixedDefsTempsHelper<Defs
|
|||
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
|
||||
}
|
||||
};
|
||||
|
@ -1230,8 +1241,10 @@ class LVariadicInstruction : public details::LInstructionFixedDefsTempsHelper<De
|
|||
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();
|
||||
}
|
||||
};
|
||||
|
@ -1239,6 +1252,11 @@ class LCallInstructionHelper : public LInstructionHelper<Defs, Operands, Temps>
|
|||
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);
|
||||
|
|
|
@ -3323,18 +3323,19 @@ LIRGenerator::visitLoadElementFromState(MLoadElementFromState* ins)
|
|||
"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()) {
|
||||
|
@ -4692,8 +4693,8 @@ 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;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1>
|
|||
LIR_HEADER(BoxFloatingPoint);
|
||||
|
||||
LBoxFloatingPoint(const LAllocation& in, const LDefinition& temp, MIRType type)
|
||||
: type_(type)
|
||||
: LInstructionHelper(classOpcode),
|
||||
type_(type)
|
||||
{
|
||||
setOperand(0, in);
|
||||
setTemp(0, temp);
|
||||
|
@ -37,6 +38,10 @@ class LUnbox : public LInstructionHelper<1, 2, 0>
|
|||
public:
|
||||
LIR_HEADER(Unbox);
|
||||
|
||||
LUnbox()
|
||||
: LInstructionHelper(classOpcode)
|
||||
{}
|
||||
|
||||
MUnbox* mir() const {
|
||||
return mir_->toUnbox();
|
||||
}
|
||||
|
@ -61,7 +66,8 @@ class LUnboxFloatingPoint : public LInstructionHelper<1, 2, 0>
|
|||
static const size_t Input = 0;
|
||||
|
||||
LUnboxFloatingPoint(const LBoxAllocation& input, MIRType type)
|
||||
: type_(type)
|
||||
: LInstructionHelper(classOpcode),
|
||||
type_(type)
|
||||
{
|
||||
setBoxOperand(Input, input);
|
||||
}
|
||||
|
@ -84,7 +90,9 @@ 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);
|
||||
}
|
||||
};
|
||||
|
@ -95,7 +103,9 @@ 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);
|
||||
}
|
||||
};
|
||||
|
@ -106,7 +116,9 @@ class LDivI : public LBinaryMath<1>
|
|||
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);
|
||||
|
@ -126,6 +138,7 @@ class LDivOrModI64 : public LCallInstructionHelper<INT64_PIECES, INT64_PIECES*2,
|
|||
static const size_t Rhs = INT64_PIECES;
|
||||
|
||||
LDivOrModI64(const LInt64Allocation& lhs, const LInt64Allocation& rhs)
|
||||
: LCallInstructionHelper(classOpcode)
|
||||
{
|
||||
setInt64Operand(Lhs, lhs);
|
||||
setInt64Operand(Rhs, rhs);
|
||||
|
@ -162,6 +175,7 @@ class LUDivOrModI64 : public LCallInstructionHelper<INT64_PIECES, INT64_PIECES*2
|
|||
static const size_t Rhs = INT64_PIECES;
|
||||
|
||||
LUDivOrModI64(const LInt64Allocation& lhs, const LInt64Allocation& rhs)
|
||||
: LCallInstructionHelper(classOpcode)
|
||||
{
|
||||
setInt64Operand(Lhs, lhs);
|
||||
setInt64Operand(Rhs, rhs);
|
||||
|
@ -196,7 +210,9 @@ 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);
|
||||
}
|
||||
|
@ -214,7 +230,8 @@ class LDivPowTwoI : public LInstructionHelper<1, 1, 0>
|
|||
LIR_HEADER(DivPowTwoI)
|
||||
|
||||
LDivPowTwoI(const LAllocation& lhs, int32_t shift)
|
||||
: shift_(shift)
|
||||
: LInstructionHelper(classOpcode),
|
||||
shift_(shift)
|
||||
{
|
||||
setOperand(0, lhs);
|
||||
}
|
||||
|
@ -239,6 +256,7 @@ class LModI : public LBinaryMath<1>
|
|||
|
||||
LModI(const LAllocation& lhs, const LAllocation& rhs,
|
||||
const LDefinition& callTemp)
|
||||
: LBinaryMath(classOpcode)
|
||||
{
|
||||
setOperand(0, lhs);
|
||||
setOperand(1, rhs);
|
||||
|
@ -261,6 +279,7 @@ class LSoftModI : public LBinaryCallInstructionHelper<1, 1>
|
|||
|
||||
LSoftModI(const LAllocation& lhs, const LAllocation& rhs,
|
||||
const LDefinition& temp)
|
||||
: LBinaryCallInstructionHelper(classOpcode)
|
||||
{
|
||||
setOperand(0, lhs);
|
||||
setOperand(1, rhs);
|
||||
|
@ -288,7 +307,8 @@ class LModPowTwoI : public LInstructionHelper<1, 1, 0>
|
|||
}
|
||||
|
||||
LModPowTwoI(const LAllocation& lhs, int32_t shift)
|
||||
: shift_(shift)
|
||||
: LInstructionHelper(classOpcode),
|
||||
shift_(shift)
|
||||
{
|
||||
setOperand(0, lhs);
|
||||
}
|
||||
|
@ -307,7 +327,8 @@ class LModMaskI : public LInstructionHelper<1, 1, 2>
|
|||
|
||||
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);
|
||||
|
@ -329,7 +350,9 @@ 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);
|
||||
|
@ -359,6 +382,7 @@ class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2>
|
|||
|
||||
LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
|
||||
const LDefinition& floatCopy, MTableSwitch* ins)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setBoxOperand(InputValue, input);
|
||||
setTemp(0, inputCopy);
|
||||
|
@ -388,6 +412,10 @@ class LMulI : public LBinaryMath<0>
|
|||
public:
|
||||
LIR_HEADER(MulI);
|
||||
|
||||
LMulI()
|
||||
: LBinaryMath(classOpcode)
|
||||
{}
|
||||
|
||||
MMul* mir() {
|
||||
return mir_->toMul();
|
||||
}
|
||||
|
@ -398,6 +426,10 @@ class LUDiv : public LBinaryMath<0>
|
|||
public:
|
||||
LIR_HEADER(UDiv);
|
||||
|
||||
LUDiv()
|
||||
: LBinaryMath(classOpcode)
|
||||
{}
|
||||
|
||||
MDiv* mir() {
|
||||
return mir_->toDiv();
|
||||
}
|
||||
|
@ -408,6 +440,10 @@ class LUMod : public LBinaryMath<0>
|
|||
public:
|
||||
LIR_HEADER(UMod);
|
||||
|
||||
LUMod()
|
||||
: LBinaryMath(classOpcode)
|
||||
{}
|
||||
|
||||
MMod* mir() {
|
||||
return mir_->toMod();
|
||||
}
|
||||
|
@ -418,7 +454,9 @@ 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);
|
||||
}
|
||||
|
@ -433,7 +471,9 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -447,6 +487,10 @@ class LInt64ToFloatingPointCall: public LCallInstructionHelper<1, INT64_PIECES,
|
|||
public:
|
||||
LIR_HEADER(Int64ToFloatingPointCall);
|
||||
|
||||
LInt64ToFloatingPointCall()
|
||||
: LCallInstructionHelper(classOpcode)
|
||||
{}
|
||||
|
||||
MInt64ToFloatingPoint* mir() const {
|
||||
return mir_->toInt64ToFloatingPoint();
|
||||
}
|
||||
|
@ -460,10 +504,11 @@ 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);
|
||||
|
@ -484,7 +529,7 @@ class LWasmUnalignedLoad : public details::LWasmUnalignedLoadBase<1>
|
|||
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);
|
||||
};
|
||||
|
@ -495,7 +540,7 @@ class LWasmUnalignedLoadI64 : public details::LWasmUnalignedLoadBase<INT64_PIECE
|
|||
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);
|
||||
};
|
||||
|
@ -511,8 +556,9 @@ class LWasmUnalignedStoreBase : public LInstructionHelper<0, NumOps, 2>
|
|||
|
||||
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);
|
||||
|
@ -537,7 +583,7 @@ class LWasmUnalignedStore : public details::LWasmUnalignedStoreBase<2>
|
|||
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);
|
||||
}
|
||||
|
@ -549,7 +595,7 @@ class LWasmUnalignedStoreI64 : public details::LWasmUnalignedStoreBase<1 + INT64
|
|||
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);
|
||||
}
|
||||
|
@ -560,7 +606,9 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -579,6 +627,7 @@ class LWasmAtomicStoreI64 : public LInstructionHelper<0, 1 + INT64_PIECES, 2>
|
|||
|
||||
LWasmAtomicStoreI64(const LAllocation& ptr, const LInt64Allocation& value,
|
||||
const LDefinition& tmpLow, const LDefinition& tmpHigh)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setOperand(0, ptr);
|
||||
setInt64Operand(1, value);
|
||||
|
@ -610,6 +659,7 @@ class LWasmCompareExchangeI64 : public LInstructionHelper<INT64_PIECES, 1 + 2*IN
|
|||
|
||||
LWasmCompareExchangeI64(const LAllocation& ptr, const LInt64Allocation& expected,
|
||||
const LInt64Allocation& replacement)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setOperand(0, ptr);
|
||||
setInt64Operand(1, expected);
|
||||
|
@ -641,7 +691,8 @@ class LWasmAtomicBinopI64 : public LInstructionHelper<INT64_PIECES, 1 + INT64_PI
|
|||
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);
|
||||
|
@ -679,7 +730,8 @@ class LWasmAtomicExchangeI64 : public LInstructionHelper<INT64_PIECES, 1 + INT64
|
|||
|
||||
LWasmAtomicExchangeI64(const LAllocation& ptr, const LInt64Allocation& value,
|
||||
const wasm::MemoryAccessDesc& access)
|
||||
: access_(access)
|
||||
: LInstructionHelper(classOpcode),
|
||||
access_(access)
|
||||
{
|
||||
setOperand(0, ptr);
|
||||
setInt64Operand(1, value);
|
||||
|
|
|
@ -13,7 +13,9 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -29,8 +31,8 @@ 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 {
|
||||
|
@ -46,7 +48,7 @@ class LUnboxFloatingPoint : public LUnboxBase
|
|||
LIR_HEADER(UnboxFloatingPoint);
|
||||
|
||||
LUnboxFloatingPoint(const LAllocation& input, MIRType type)
|
||||
: LUnboxBase(input),
|
||||
: LUnboxBase(classOpcode, input),
|
||||
type_(type)
|
||||
{ }
|
||||
|
||||
|
@ -64,7 +66,9 @@ 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);
|
||||
}
|
||||
};
|
||||
|
@ -75,7 +79,9 @@ 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);
|
||||
}
|
||||
};
|
||||
|
@ -87,6 +93,7 @@ class LDivI : public LBinaryMath<1>
|
|||
|
||||
LDivI(const LAllocation& lhs, const LAllocation& rhs,
|
||||
const LDefinition& temp)
|
||||
: LBinaryMath(classOpcode)
|
||||
{
|
||||
setOperand(0, lhs);
|
||||
setOperand(1, rhs);
|
||||
|
@ -116,7 +123,9 @@ class LSoftDivI : public LBinaryMath<3>
|
|||
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);
|
||||
|
@ -137,7 +146,8 @@ class LDivPowTwoI : public LInstructionHelper<1, 1, 0>
|
|||
LIR_HEADER(DivPowTwoI)
|
||||
|
||||
LDivPowTwoI(const LAllocation& lhs, int32_t shift)
|
||||
: shift_(shift)
|
||||
: LInstructionHelper(classOpcode),
|
||||
shift_(shift)
|
||||
{
|
||||
setOperand(0, lhs);
|
||||
}
|
||||
|
@ -162,6 +172,7 @@ class LModI : public LBinaryMath<1>
|
|||
|
||||
LModI(const LAllocation& lhs, const LAllocation& rhs,
|
||||
const LDefinition& callTemp)
|
||||
: LBinaryMath(classOpcode)
|
||||
{
|
||||
setOperand(0, lhs);
|
||||
setOperand(1, rhs);
|
||||
|
@ -185,6 +196,7 @@ class LSoftModI : public LBinaryMath<4>
|
|||
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);
|
||||
|
@ -215,7 +227,8 @@ class LModPowTwoI : public LInstructionHelper<1, 1, 0>
|
|||
}
|
||||
|
||||
LModPowTwoI(const LAllocation& lhs, int32_t shift)
|
||||
: shift_(shift)
|
||||
: LInstructionHelper(classOpcode),
|
||||
shift_(shift)
|
||||
{
|
||||
setOperand(0, lhs);
|
||||
}
|
||||
|
@ -233,7 +246,8 @@ class LModMaskI : public LInstructionHelper<1, 1, 1>
|
|||
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);
|
||||
|
@ -254,7 +268,9 @@ 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);
|
||||
|
@ -284,6 +300,7 @@ class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2>
|
|||
|
||||
LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
|
||||
const LDefinition& floatCopy, MTableSwitch* ins)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setBoxOperand(InputValue, input);
|
||||
setTemp(0, inputCopy);
|
||||
|
@ -346,7 +363,9 @@ class LSoftUDivOrMod : public LBinaryMath<3>
|
|||
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);
|
||||
|
|
|
@ -46,7 +46,11 @@ class LTableSwitchV : public LInstruction
|
|||
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>
|
||||
|
@ -62,7 +66,9 @@ 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(); }
|
||||
|
@ -70,7 +76,7 @@ class LDivI : public LBinaryMath<1>
|
|||
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(); }
|
||||
|
@ -80,6 +86,7 @@ class LModI : public LBinaryMath<1>
|
|||
public:
|
||||
LModI(const LAllocation&, const LAllocation&,
|
||||
const LDefinition&)
|
||||
: LBinaryMath(LOp_Invalid)
|
||||
{
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
@ -90,14 +97,22 @@ class LModI : public LBinaryMath<1>
|
|||
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(); }
|
||||
};
|
||||
|
||||
|
|
|
@ -372,8 +372,9 @@ class CodeGeneratorShared : public LElementVisitor
|
|||
// 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;
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -470,6 +470,26 @@ LIRGeneratorShared::ensureDefined(MDefinition* mir)
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -231,6 +231,9 @@ class LIRGeneratorShared : public MDefinitionVisitor
|
|||
// 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();
|
||||
}
|
||||
|
|
|
@ -15,7 +15,9 @@ namespace jit {
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -31,7 +33,7 @@ class LUnbox : public LUnboxBase {
|
|||
LIR_HEADER(Unbox)
|
||||
|
||||
explicit LUnbox(const LAllocation& input)
|
||||
: LUnboxBase(input)
|
||||
: LUnboxBase(classOpcode, input)
|
||||
{ }
|
||||
|
||||
const char* extraName() const {
|
||||
|
@ -46,7 +48,7 @@ class LUnboxFloatingPoint : public LUnboxBase {
|
|||
LIR_HEADER(UnboxFloatingPoint)
|
||||
|
||||
LUnboxFloatingPoint(const LAllocation& input, MIRType type)
|
||||
: LUnboxBase(input),
|
||||
: LUnboxBase(classOpcode, input),
|
||||
type_(type)
|
||||
{ }
|
||||
|
||||
|
@ -64,7 +66,9 @@ 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);
|
||||
}
|
||||
};
|
||||
|
@ -75,7 +79,9 @@ 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);
|
||||
}
|
||||
};
|
||||
|
@ -85,7 +91,9 @@ 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);
|
||||
|
@ -125,7 +133,9 @@ 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);
|
||||
|
@ -163,7 +173,9 @@ 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);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,9 @@ 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);
|
||||
|
@ -53,7 +55,9 @@ class LDivPowTwoI : public LBinaryMath<0>
|
|||
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);
|
||||
|
@ -84,7 +88,8 @@ class LDivOrModConstantI : public LInstructionHelper<1, 1, 1>
|
|||
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);
|
||||
|
@ -112,7 +117,9 @@ 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);
|
||||
|
@ -137,7 +144,9 @@ 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);
|
||||
|
@ -183,7 +192,8 @@ class LUDivOrModConstant : public LInstructionHelper<1, 1, 1>
|
|||
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);
|
||||
|
@ -224,7 +234,8 @@ class LModPowTwoI : public LInstructionHelper<1,1,0>
|
|||
LIR_HEADER(ModPowTwoI)
|
||||
|
||||
LModPowTwoI(const LAllocation& lhs, int32_t shift)
|
||||
: shift_(shift)
|
||||
: LInstructionHelper(classOpcode),
|
||||
shift_(shift)
|
||||
{
|
||||
setOperand(0, lhs);
|
||||
}
|
||||
|
@ -248,6 +259,7 @@ class LTableSwitch : public LInstructionHelper<0, 1, 2>
|
|||
|
||||
LTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
|
||||
const LDefinition& jumpTablePointer, MTableSwitch* ins)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setOperand(0, in);
|
||||
setTemp(0, inputCopy);
|
||||
|
@ -279,6 +291,7 @@ class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3>
|
|||
LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
|
||||
const LDefinition& floatCopy, const LDefinition& jumpTablePointer,
|
||||
MTableSwitch* ins)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setBoxOperand(InputValue, input);
|
||||
setTemp(0, inputCopy);
|
||||
|
@ -309,7 +322,9 @@ 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);
|
||||
|
@ -336,6 +351,7 @@ class LSimdValueInt32x4 : public LInstructionHelper<1, 4, 0>
|
|||
LIR_HEADER(SimdValueInt32x4)
|
||||
LSimdValueInt32x4(const LAllocation& x, const LAllocation& y,
|
||||
const LAllocation& z, const LAllocation& w)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setOperand(0, x);
|
||||
setOperand(1, y);
|
||||
|
@ -356,6 +372,7 @@ class LSimdValueFloat32x4 : public LInstructionHelper<1, 4, 1>
|
|||
LSimdValueFloat32x4(const LAllocation& x, const LAllocation& y,
|
||||
const LAllocation& z, const LAllocation& w,
|
||||
const LDefinition& copyY)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setOperand(0, x);
|
||||
setOperand(1, y);
|
||||
|
@ -375,7 +392,9 @@ 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);
|
||||
}
|
||||
|
|
|
@ -935,14 +935,14 @@ LIRGeneratorX86Shared::visitSimdGeneralShuffle(MSimdGeneralShuffle* ins)
|
|||
#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++) {
|
||||
|
|
|
@ -18,7 +18,8 @@ class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1>
|
|||
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);
|
||||
|
@ -38,6 +39,10 @@ class LUnbox : public LInstructionHelper<1, 2, 0>
|
|||
public:
|
||||
LIR_HEADER(Unbox);
|
||||
|
||||
LUnbox()
|
||||
: LInstructionHelper(classOpcode)
|
||||
{}
|
||||
|
||||
MUnbox* mir() const {
|
||||
return mir_->toUnbox();
|
||||
}
|
||||
|
@ -62,7 +67,8 @@ class LUnboxFloatingPoint : public LInstructionHelper<1, 2, 0>
|
|||
static const size_t Input = 0;
|
||||
|
||||
LUnboxFloatingPoint(const LBoxAllocation& input, MIRType type)
|
||||
: type_(type)
|
||||
: LInstructionHelper(classOpcode),
|
||||
type_(type)
|
||||
{
|
||||
setBoxOperand(Input, input);
|
||||
}
|
||||
|
@ -85,7 +91,9 @@ 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);
|
||||
}
|
||||
|
@ -100,7 +108,9 @@ 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);
|
||||
}
|
||||
|
@ -118,6 +128,7 @@ class LDivOrModI64 : public LCallInstructionHelper<INT64_PIECES, INT64_PIECES*2,
|
|||
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);
|
||||
|
@ -158,6 +169,7 @@ class LUDivOrModI64 : public LCallInstructionHelper<INT64_PIECES, INT64_PIECES*2
|
|||
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);
|
||||
|
@ -195,6 +207,7 @@ class LWasmTruncateToInt64 : public LInstructionHelper<INT64_PIECES, 1, 1>
|
|||
LIR_HEADER(WasmTruncateToInt64);
|
||||
|
||||
LWasmTruncateToInt64(const LAllocation& in, const LDefinition& temp)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setOperand(0, in);
|
||||
setTemp(0, temp);
|
||||
|
@ -216,6 +229,7 @@ class LWasmAtomicLoadI64 : public LInstructionHelper<INT64_PIECES, 2, 2>
|
|||
|
||||
LWasmAtomicLoadI64(const LAllocation& memoryBase, const LAllocation& ptr, const LDefinition& t1,
|
||||
const LDefinition& t2)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setOperand(0, memoryBase);
|
||||
setOperand(1, ptr);
|
||||
|
@ -248,6 +262,7 @@ class LWasmAtomicStoreI64 : public LInstructionHelper<0, 2 + INT64_PIECES, 2>
|
|||
LWasmAtomicStoreI64(const LAllocation& memoryBase, const LAllocation& ptr,
|
||||
const LInt64Allocation& value, const LDefinition& t1,
|
||||
const LDefinition& t2)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setOperand(0, memoryBase);
|
||||
setOperand(1, ptr);
|
||||
|
@ -283,6 +298,7 @@ class LWasmCompareExchangeI64 : public LInstructionHelper<INT64_PIECES, 2 + 2*IN
|
|||
|
||||
LWasmCompareExchangeI64(const LAllocation& memoryBase, const LAllocation& ptr,
|
||||
const LInt64Allocation& expected, const LInt64Allocation& replacement)
|
||||
: LInstructionHelper(classOpcode)
|
||||
{
|
||||
setOperand(0, memoryBase);
|
||||
setOperand(1, ptr);
|
||||
|
@ -316,7 +332,8 @@ class LWasmAtomicExchangeI64 : public LInstructionHelper<INT64_PIECES, 2 + INT64
|
|||
|
||||
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);
|
||||
|
@ -348,7 +365,8 @@ class LWasmAtomicBinopI64 : public LInstructionHelper<INT64_PIECES, 2 + INT64_PI
|
|||
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);
|
||||
|
|
|
@ -54,18 +54,6 @@ namespace js {
|
|||
*/
|
||||
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)
|
||||
{
|
||||
|
@ -83,6 +71,7 @@ bool
|
|||
LiveSavedFrameCache::insert(JSContext* cx, FramePtr& framePtr, const jsbytecode* pc,
|
||||
HandleSavedFrame savedFrame)
|
||||
{
|
||||
MOZ_ASSERT(savedFrame);
|
||||
MOZ_ASSERT(initialized());
|
||||
|
||||
if (!frames->emplaceBack(framePtr, pc, savedFrame)) {
|
||||
|
@ -90,34 +79,25 @@ LiveSavedFrameCache::insert(JSContext* cx, FramePtr& framePtr, const jsbytecode*
|
|||
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;
|
||||
}
|
||||
|
@ -1321,6 +1301,7 @@ SavedStacks::insertFrames(JSContext* cx, FrameIter& iter, MutableHandleSavedFram
|
|||
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);
|
||||
|
@ -1377,12 +1358,11 @@ SavedStacks::insertFrames(JSContext* cx, FrameIter& iter, MutableHandleSavedFram
|
|||
// 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(),
|
||||
|
@ -1408,15 +1388,16 @@ SavedStacks::insertFrames(JSContext* cx, FrameIter& iter, MutableHandleSavedFram
|
|||
}
|
||||
|
||||
++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;
|
||||
}
|
||||
|
|
|
@ -608,31 +608,6 @@ AbstractFramePtr::isDebuggerEvalFrame() const
|
|||
return false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
AbstractFramePtr::hasCachedSavedFrame() const
|
||||
{
|
||||
if (isInterpreterFrame())
|
||||
return asInterpreterFrame()->hasCachedSavedFrame();
|
||||
if (isBaselineFrame())
|
||||
return asBaselineFrame()->hasCachedSavedFrame();
|
||||
if (isWasmDebugFrame())
|
||||
return asWasmDebugFrame()->hasCachedSavedFrame();
|
||||
return asRematerializedFrame()->hasCachedSavedFrame();
|
||||
}
|
||||
|
||||
inline void
|
||||
AbstractFramePtr::setHasCachedSavedFrame()
|
||||
{
|
||||
if (isInterpreterFrame())
|
||||
asInterpreterFrame()->setHasCachedSavedFrame();
|
||||
else if (isBaselineFrame())
|
||||
asBaselineFrame()->setHasCachedSavedFrame();
|
||||
else if (isWasmDebugFrame())
|
||||
asWasmDebugFrame()->setHasCachedSavedFrame();
|
||||
else
|
||||
asRematerializedFrame()->setHasCachedSavedFrame();
|
||||
}
|
||||
|
||||
inline bool
|
||||
AbstractFramePtr::isDebuggee() const
|
||||
{
|
||||
|
@ -998,34 +973,48 @@ InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, HandleValue n
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
FrameIter::hasCachedSavedFrame() const
|
||||
/* static */ inline Maybe<LiveSavedFrameCache::FramePtr>
|
||||
LiveSavedFrameCache::FramePtr::create(const FrameIter& iter)
|
||||
{
|
||||
if (isWasm())
|
||||
return false;
|
||||
if (iter.done())
|
||||
return mozilla::Nothing();
|
||||
|
||||
if (hasUsableAbstractFramePtr())
|
||||
return abstractFramePtr().hasCachedSavedFrame();
|
||||
if (iter.isPhysicalJitFrame())
|
||||
return mozilla::Some(FramePtr(iter.physicalJitFrame()));
|
||||
|
||||
MOZ_ASSERT(jsJitFrame().isIonScripted());
|
||||
// SavedFrame caching is done at the physical frame granularity (rather than
|
||||
// for each inlined frame) for ion. Therefore, it is impossible to have a
|
||||
// cached SavedFrame if this frame is not a physical frame.
|
||||
return isPhysicalIonFrame() && jsJitFrame().current()->hasCachedSavedFrame();
|
||||
if (!iter.hasUsableAbstractFramePtr())
|
||||
return mozilla::Nothing();
|
||||
|
||||
auto afp = iter.abstractFramePtr();
|
||||
|
||||
if (afp.isInterpreterFrame())
|
||||
return mozilla::Some(FramePtr(afp.asInterpreterFrame()));
|
||||
if (afp.isWasmDebugFrame())
|
||||
return mozilla::Some(FramePtr(afp.asWasmDebugFrame()));
|
||||
if (afp.isRematerializedFrame())
|
||||
return mozilla::Some(FramePtr(afp.asRematerializedFrame()));
|
||||
|
||||
MOZ_CRASH("unexpected frame type");
|
||||
}
|
||||
|
||||
struct LiveSavedFrameCache::FramePtr::HasCachedMatcher {
|
||||
template<typename Frame>
|
||||
bool match(Frame* f) const { return f->hasCachedSavedFrame(); }
|
||||
};
|
||||
|
||||
inline bool
|
||||
LiveSavedFrameCache::FramePtr::hasCachedSavedFrame() const {
|
||||
return ptr.match(HasCachedMatcher());
|
||||
}
|
||||
|
||||
struct LiveSavedFrameCache::FramePtr::SetHasCachedMatcher {
|
||||
template<typename Frame>
|
||||
void match(Frame* f) const { f->setHasCachedSavedFrame(); }
|
||||
};
|
||||
|
||||
inline void
|
||||
FrameIter::setHasCachedSavedFrame()
|
||||
{
|
||||
MOZ_ASSERT(!isWasm());
|
||||
|
||||
if (hasUsableAbstractFramePtr()) {
|
||||
abstractFramePtr().setHasCachedSavedFrame();
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(isPhysicalIonFrame());
|
||||
jsJitFrame().current()->setHasCachedSavedFrame();
|
||||
LiveSavedFrameCache::FramePtr::setHasCachedSavedFrame() {
|
||||
ptr.match(SetHasCachedMatcher());
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
|
|
@ -241,8 +241,6 @@ class AbstractFramePtr
|
|||
inline bool isModuleFrame() const;
|
||||
inline bool isEvalFrame() const;
|
||||
inline bool isDebuggerEvalFrame() const;
|
||||
inline bool hasCachedSavedFrame() const;
|
||||
inline void setHasCachedSavedFrame();
|
||||
|
||||
inline bool hasScript() const;
|
||||
inline JSScript* script() const;
|
||||
|
@ -1170,17 +1168,57 @@ struct DefaultHasher<AbstractFramePtr> {
|
|||
class LiveSavedFrameCache
|
||||
{
|
||||
public:
|
||||
using FramePtr = mozilla::Variant<AbstractFramePtr, jit::CommonFrameLayout*>;
|
||||
// The address of a live frame for which we can cache SavedFrames: it has a
|
||||
// 'hasCachedSavedFrame' bit we can examine and set, and can be converted to
|
||||
// a Key to index the cache.
|
||||
class FramePtr {
|
||||
// We use jit::CommonFrameLayout for both Baseline frames and Ion
|
||||
// physical frames.
|
||||
using Ptr = mozilla::Variant<InterpreterFrame*,
|
||||
jit::CommonFrameLayout*,
|
||||
jit::RematerializedFrame*,
|
||||
wasm::DebugFrame*>;
|
||||
|
||||
Ptr ptr;
|
||||
|
||||
template<typename Frame>
|
||||
explicit FramePtr(Frame ptr) : ptr(ptr) { }
|
||||
|
||||
struct HasCachedMatcher;
|
||||
struct SetHasCachedMatcher;
|
||||
|
||||
public:
|
||||
static inline mozilla::Maybe<FramePtr> create(const FrameIter& iter);
|
||||
|
||||
inline bool hasCachedSavedFrame() const;
|
||||
inline void setHasCachedSavedFrame();
|
||||
|
||||
bool operator==(const FramePtr& rhs) const { return rhs.ptr == this->ptr; }
|
||||
bool operator!=(const FramePtr& rhs) const { return !(rhs == *this); }
|
||||
};
|
||||
|
||||
private:
|
||||
// A key in the cache: the address of a frame, live or dead, for which we
|
||||
// can cache SavedFrames. Since the pointer may not be live, the only
|
||||
// operation this type permits is comparison.
|
||||
class Key {
|
||||
FramePtr framePtr;
|
||||
|
||||
public:
|
||||
MOZ_IMPLICIT Key(const FramePtr& framePtr) : framePtr(framePtr) { }
|
||||
|
||||
bool operator==(const Key& rhs) const { return rhs.framePtr == this->framePtr; }
|
||||
bool operator!=(const Key& rhs) const { return !(rhs == *this); }
|
||||
};
|
||||
|
||||
struct Entry
|
||||
{
|
||||
const FramePtr framePtr;
|
||||
const Key key;
|
||||
const jsbytecode* pc;
|
||||
HeapPtr<SavedFrame*> savedFrame;
|
||||
|
||||
Entry(const FramePtr& framePtr, const jsbytecode* pc, SavedFrame* savedFrame)
|
||||
: framePtr(framePtr)
|
||||
Entry(const Key& key, const jsbytecode* pc, SavedFrame* savedFrame)
|
||||
: key(key)
|
||||
, pc(pc)
|
||||
, savedFrame(savedFrame)
|
||||
{ }
|
||||
|
@ -1219,10 +1257,10 @@ class LiveSavedFrameCache
|
|||
return true;
|
||||
}
|
||||
|
||||
static mozilla::Maybe<FramePtr> getFramePtr(const FrameIter& iter);
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
void find(JSContext* cx, FrameIter& frameIter, MutableHandleSavedFrame frame) const;
|
||||
void find(JSContext* cx, FramePtr& frameptr, const jsbytecode* pc,
|
||||
MutableHandleSavedFrame frame) const;
|
||||
bool insert(JSContext* cx, FramePtr& framePtr, const jsbytecode* pc,
|
||||
HandleSavedFrame savedFrame);
|
||||
};
|
||||
|
@ -1939,16 +1977,12 @@ class FrameIter
|
|||
|
||||
inline bool isIon() const;
|
||||
inline bool isBaseline() const;
|
||||
inline bool isPhysicalIonFrame() const;
|
||||
inline bool isPhysicalJitFrame() const;
|
||||
|
||||
bool isEvalFrame() const;
|
||||
bool isFunctionFrame() const;
|
||||
bool hasArgs() const { return isFunctionFrame(); }
|
||||
|
||||
// These two methods may not be called with asm frames.
|
||||
inline bool hasCachedSavedFrame() const;
|
||||
inline void setHasCachedSavedFrame();
|
||||
|
||||
ScriptSource* scriptSource() const;
|
||||
const char* filename() const;
|
||||
const char16_t* displayURL() const;
|
||||
|
@ -2039,8 +2073,8 @@ class FrameIter
|
|||
// This can only be called when isInterp():
|
||||
inline InterpreterFrame* interpFrame() const;
|
||||
|
||||
// This can only be called when isPhysicalIonFrame():
|
||||
inline jit::CommonFrameLayout* physicalIonFrame() const;
|
||||
// This can only be called when isPhysicalJitFrame():
|
||||
inline jit::CommonFrameLayout* physicalJitFrame() const;
|
||||
|
||||
// This is used to provide a raw interface for debugging.
|
||||
void* rawFramePtr() const;
|
||||
|
@ -2273,17 +2307,28 @@ FrameIter::interpFrame() const
|
|||
}
|
||||
|
||||
inline bool
|
||||
FrameIter::isPhysicalIonFrame() const
|
||||
FrameIter::isPhysicalJitFrame() const
|
||||
{
|
||||
return isJSJit() &&
|
||||
jsJitFrame().isIonScripted() &&
|
||||
ionInlineFrames_.frameNo() == 0;
|
||||
if (!isJSJit())
|
||||
return false;
|
||||
|
||||
auto& jitFrame = jsJitFrame();
|
||||
|
||||
if (jitFrame.isBaselineJS())
|
||||
return true;
|
||||
|
||||
if (jitFrame.isIonScripted()) {
|
||||
// Only the bottom of a group of inlined Ion frames is a physical frame.
|
||||
return ionInlineFrames_.frameNo() == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline jit::CommonFrameLayout*
|
||||
FrameIter::physicalIonFrame() const
|
||||
FrameIter::physicalJitFrame() const
|
||||
{
|
||||
MOZ_ASSERT(isPhysicalIonFrame());
|
||||
MOZ_ASSERT(isPhysicalJitFrame());
|
||||
return jsJitFrame().current();
|
||||
}
|
||||
|
||||
|
|
|
@ -189,6 +189,8 @@
|
|||
#include "mozilla/dom/ImageTracker.h"
|
||||
#include "nsIDocShellTreeOwner.h"
|
||||
#include "nsBindingManager.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
#include "GeckoTaskTracer.h"
|
||||
|
@ -369,8 +371,6 @@ public:
|
|||
|
||||
FILE * GetOutFile() { return mFD; }
|
||||
|
||||
PLHashTable * GetIndiFrameHT() { return mIndiFrameCounts; }
|
||||
|
||||
void SetPresContext(nsPresContext * aPresContext) { mPresContext = aPresContext; } // weak reference
|
||||
void SetPresShell(nsIPresShell* aPresShell) { mPresShell= aPresShell; } // weak reference
|
||||
|
||||
|
@ -384,29 +384,14 @@ protected:
|
|||
void DisplayTotals(uint32_t aTotal, uint32_t * aDupArray, char * aTitle);
|
||||
void DisplayHTMLTotals(uint32_t aTotal, uint32_t * aDupArray, char * aTitle);
|
||||
|
||||
static int RemoveItems(PLHashEntry *he, int i, void *arg);
|
||||
static int RemoveIndiItems(PLHashEntry *he, int i, void *arg);
|
||||
void CleanUp();
|
||||
|
||||
// stdout Output Methods
|
||||
static int DoSingleTotal(PLHashEntry *he, int i, void *arg);
|
||||
static int DoSingleIndi(PLHashEntry *he, int i, void *arg);
|
||||
|
||||
void DoGrandTotals();
|
||||
void DoIndiTotalsTree();
|
||||
|
||||
// HTML Output Methods
|
||||
static int DoSingleHTMLTotal(PLHashEntry *he, int i, void *arg);
|
||||
void DoGrandHTMLTotals();
|
||||
|
||||
// Zero Out the Totals
|
||||
static int DoClearTotals(PLHashEntry *he, int i, void *arg);
|
||||
|
||||
// Displays the Diff Totals
|
||||
static int DoDisplayDiffTotals(PLHashEntry *he, int i, void *arg);
|
||||
|
||||
PLHashTable * mCounts;
|
||||
PLHashTable * mIndiFrameCounts;
|
||||
nsClassHashtable<nsCharPtrHashKey, ReflowCounter> mCounts;
|
||||
nsClassHashtable<nsCharPtrHashKey, IndiReflowCounter> mIndiFrameCounts;
|
||||
FILE * mFD;
|
||||
|
||||
bool mDumpFrameCounts;
|
||||
|
@ -10029,11 +10014,9 @@ void ReflowCounter::DisplayHTMLTotals(uint32_t aTotal, const char * aTitle)
|
|||
#define KEY_BUF_SIZE_FOR_PTR 24 // adequate char[] buffer to sprintf a pointer
|
||||
|
||||
ReflowCountMgr::ReflowCountMgr()
|
||||
: mCounts(10)
|
||||
, mIndiFrameCounts(10)
|
||||
{
|
||||
mCounts = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
|
||||
PL_CompareValues, nullptr, nullptr);
|
||||
mIndiFrameCounts = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
|
||||
PL_CompareValues, nullptr, nullptr);
|
||||
mCycledOnce = false;
|
||||
mDumpFrameCounts = false;
|
||||
mDumpFrameByFrameCounts = false;
|
||||
|
@ -10043,18 +10026,12 @@ ReflowCountMgr::ReflowCountMgr()
|
|||
//------------------------------------------------------------------
|
||||
ReflowCountMgr::~ReflowCountMgr()
|
||||
{
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
ReflowCounter * ReflowCountMgr::LookUp(const char * aName)
|
||||
{
|
||||
if (nullptr != mCounts) {
|
||||
ReflowCounter * counter = (ReflowCounter *)PL_HashTableLookup(mCounts, aName);
|
||||
return counter;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
return mCounts.Get(aName);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -10062,29 +10039,24 @@ void ReflowCountMgr::Add(const char * aName, nsIFrame * aFrame)
|
|||
{
|
||||
NS_ASSERTION(aName != nullptr, "Name shouldn't be null!");
|
||||
|
||||
if (mDumpFrameCounts && nullptr != mCounts) {
|
||||
ReflowCounter * counter = (ReflowCounter *)PL_HashTableLookup(mCounts, aName);
|
||||
if (counter == nullptr) {
|
||||
counter = new ReflowCounter(this);
|
||||
char * name = NS_strdup(aName);
|
||||
NS_ASSERTION(name != nullptr, "null ptr");
|
||||
PL_HashTableAdd(mCounts, name, counter);
|
||||
}
|
||||
if (mDumpFrameCounts) {
|
||||
ReflowCounter * counter = mCounts.LookupForAdd(aName).OrInsert([this]() {
|
||||
return new ReflowCounter(this);
|
||||
});
|
||||
counter->Add();
|
||||
}
|
||||
|
||||
if ((mDumpFrameByFrameCounts || mPaintFrameByFrameCounts) &&
|
||||
nullptr != mIndiFrameCounts &&
|
||||
aFrame != nullptr) {
|
||||
char key[KEY_BUF_SIZE_FOR_PTR];
|
||||
SprintfLiteral(key, "%p", (void*)aFrame);
|
||||
IndiReflowCounter * counter = (IndiReflowCounter *)PL_HashTableLookup(mIndiFrameCounts, key);
|
||||
if (counter == nullptr) {
|
||||
counter = new IndiReflowCounter(this);
|
||||
counter->mFrame = aFrame;
|
||||
counter->mName.AssignASCII(aName);
|
||||
PL_HashTableAdd(mIndiFrameCounts, NS_strdup(key), counter);
|
||||
}
|
||||
IndiReflowCounter * counter =
|
||||
mIndiFrameCounts.LookupForAdd(key).OrInsert([&aName, &aFrame, this]() {
|
||||
auto counter = new IndiReflowCounter(this);
|
||||
counter->mFrame = aFrame;
|
||||
counter->mName.AssignASCII(aName);
|
||||
return counter;
|
||||
});
|
||||
// this eliminates extra counts from super classes
|
||||
if (counter != nullptr && counter->mName.EqualsASCII(aName)) {
|
||||
counter->mCount++;
|
||||
|
@ -10102,12 +10074,10 @@ void ReflowCountMgr::PaintCount(const char* aName,
|
|||
uint32_t aColor)
|
||||
{
|
||||
if (mPaintFrameByFrameCounts &&
|
||||
nullptr != mIndiFrameCounts &&
|
||||
aFrame != nullptr) {
|
||||
char key[KEY_BUF_SIZE_FOR_PTR];
|
||||
SprintfLiteral(key, "%p", (void*)aFrame);
|
||||
IndiReflowCounter * counter =
|
||||
(IndiReflowCounter *)PL_HashTableLookup(mIndiFrameCounts, key);
|
||||
IndiReflowCounter * counter = mIndiFrameCounts.Get(key);
|
||||
if (counter != nullptr && counter->mName.EqualsASCII(aName)) {
|
||||
DrawTarget* drawTarget = aRenderingContext->GetDrawTarget();
|
||||
int32_t appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel();
|
||||
|
@ -10169,78 +10139,29 @@ void ReflowCountMgr::PaintCount(const char* aName,
|
|||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
int ReflowCountMgr::RemoveItems(PLHashEntry *he, int i, void *arg)
|
||||
{
|
||||
char *str = (char *)he->key;
|
||||
ReflowCounter * counter = (ReflowCounter *)he->value;
|
||||
delete counter;
|
||||
free(str);
|
||||
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
int ReflowCountMgr::RemoveIndiItems(PLHashEntry *he, int i, void *arg)
|
||||
{
|
||||
char *str = (char *)he->key;
|
||||
IndiReflowCounter * counter = (IndiReflowCounter *)he->value;
|
||||
delete counter;
|
||||
free(str);
|
||||
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void ReflowCountMgr::CleanUp()
|
||||
{
|
||||
if (nullptr != mCounts) {
|
||||
PL_HashTableEnumerateEntries(mCounts, RemoveItems, nullptr);
|
||||
PL_HashTableDestroy(mCounts);
|
||||
mCounts = nullptr;
|
||||
}
|
||||
|
||||
if (nullptr != mIndiFrameCounts) {
|
||||
PL_HashTableEnumerateEntries(mIndiFrameCounts, RemoveIndiItems, nullptr);
|
||||
PL_HashTableDestroy(mIndiFrameCounts);
|
||||
mIndiFrameCounts = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
int ReflowCountMgr::DoSingleTotal(PLHashEntry *he, int i, void *arg)
|
||||
{
|
||||
char *str = (char *)he->key;
|
||||
ReflowCounter * counter = (ReflowCounter *)he->value;
|
||||
|
||||
counter->DisplayTotals(str);
|
||||
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void ReflowCountMgr::DoGrandTotals()
|
||||
{
|
||||
if (nullptr != mCounts) {
|
||||
ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr);
|
||||
if (gTots == nullptr) {
|
||||
gTots = new ReflowCounter(this);
|
||||
PL_HashTableAdd(mCounts, NS_strdup(kGrandTotalsStr), gTots);
|
||||
} else {
|
||||
gTots->ClearTotals();
|
||||
}
|
||||
auto entry = mCounts.LookupForAdd(kGrandTotalsStr);
|
||||
if (!entry) {
|
||||
entry.OrInsert([this]() { return new ReflowCounter(this); });
|
||||
} else {
|
||||
entry.Data()->ClearTotals();
|
||||
}
|
||||
|
||||
printf("\t\t\t\tTotal\n");
|
||||
for (uint32_t i=0;i<78;i++) {
|
||||
printf("-");
|
||||
}
|
||||
printf("\n");
|
||||
PL_HashTableEnumerateEntries(mCounts, DoSingleTotal, this);
|
||||
printf("\t\t\t\tTotal\n");
|
||||
for (uint32_t i=0;i<78;i++) {
|
||||
printf("-");
|
||||
}
|
||||
printf("\n");
|
||||
for (auto iter = mCounts.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.Data()->DisplayTotals(iter.Key());
|
||||
}
|
||||
}
|
||||
|
||||
static void RecurseIndiTotals(nsPresContext* aPresContext,
|
||||
PLHashTable * aHT,
|
||||
nsClassHashtable<nsCharPtrHashKey,
|
||||
IndiReflowCounter>& aHT,
|
||||
nsIFrame * aParentFrame,
|
||||
int32_t aLevel)
|
||||
{
|
||||
|
@ -10250,7 +10171,7 @@ static void RecurseIndiTotals(nsPresContext* aPresContext,
|
|||
|
||||
char key[KEY_BUF_SIZE_FOR_PTR];
|
||||
SprintfLiteral(key, "%p", (void*)aParentFrame);
|
||||
IndiReflowCounter * counter = (IndiReflowCounter *)PL_HashTableLookup(aHT, key);
|
||||
IndiReflowCounter * counter = aHT.Get(key);
|
||||
if (counter) {
|
||||
counter->mHasBeenOutput = true;
|
||||
char * name = ToNewCString(counter->mName);
|
||||
|
@ -10267,69 +10188,51 @@ static void RecurseIndiTotals(nsPresContext* aPresContext,
|
|||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
int ReflowCountMgr::DoSingleIndi(PLHashEntry *he, int i, void *arg)
|
||||
{
|
||||
IndiReflowCounter * counter = (IndiReflowCounter *)he->value;
|
||||
if (counter && !counter->mHasBeenOutput) {
|
||||
char * name = ToNewCString(counter->mName);
|
||||
printf("%s - %p [%d][", name, (void*)counter->mFrame, counter->mCount);
|
||||
printf("%d", counter->mCounter.GetTotal());
|
||||
printf("]\n");
|
||||
free(name);
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void ReflowCountMgr::DoIndiTotalsTree()
|
||||
{
|
||||
if (nullptr != mCounts) {
|
||||
printf("\n------------------------------------------------\n");
|
||||
printf("-- Individual Frame Counts\n");
|
||||
printf("------------------------------------------------\n");
|
||||
printf("\n------------------------------------------------\n");
|
||||
printf("-- Individual Frame Counts\n");
|
||||
printf("------------------------------------------------\n");
|
||||
|
||||
if (mPresShell) {
|
||||
nsIFrame* rootFrame = mPresShell->GetRootFrame();
|
||||
RecurseIndiTotals(mPresContext, mIndiFrameCounts, rootFrame, 0);
|
||||
printf("------------------------------------------------\n");
|
||||
printf("-- Individual Counts of Frames not in Root Tree\n");
|
||||
printf("------------------------------------------------\n");
|
||||
PL_HashTableEnumerateEntries(mIndiFrameCounts, DoSingleIndi, this);
|
||||
if (mPresShell) {
|
||||
nsIFrame* rootFrame = mPresShell->GetRootFrame();
|
||||
RecurseIndiTotals(mPresContext, mIndiFrameCounts, rootFrame, 0);
|
||||
printf("------------------------------------------------\n");
|
||||
printf("-- Individual Counts of Frames not in Root Tree\n");
|
||||
printf("------------------------------------------------\n");
|
||||
for (auto iter = mIndiFrameCounts.Iter(); !iter.Done(); iter.Next()) {
|
||||
IndiReflowCounter* counter = iter.Data();
|
||||
if (!counter->mHasBeenOutput) {
|
||||
char * name = ToNewCString(counter->mName);
|
||||
printf("%s - %p [%d][", name, (void*)counter->mFrame, counter->mCount);
|
||||
printf("%d", counter->mCounter.GetTotal());
|
||||
printf("]\n");
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
int ReflowCountMgr::DoSingleHTMLTotal(PLHashEntry *he, int i, void *arg)
|
||||
{
|
||||
char *str = (char *)he->key;
|
||||
ReflowCounter * counter = (ReflowCounter *)he->value;
|
||||
|
||||
counter->DisplayHTMLTotals(str);
|
||||
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void ReflowCountMgr::DoGrandHTMLTotals()
|
||||
{
|
||||
if (nullptr != mCounts) {
|
||||
ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr);
|
||||
if (gTots == nullptr) {
|
||||
gTots = new ReflowCounter(this);
|
||||
PL_HashTableAdd(mCounts, NS_strdup(kGrandTotalsStr), gTots);
|
||||
} else {
|
||||
gTots->ClearTotals();
|
||||
}
|
||||
auto entry = mCounts.LookupForAdd(kGrandTotalsStr);
|
||||
if (!entry) {
|
||||
entry.OrInsert([this]() { return new ReflowCounter(this); });
|
||||
} else {
|
||||
entry.Data()->ClearTotals();
|
||||
}
|
||||
|
||||
static const char * title[] = {"Class", "Reflows"};
|
||||
fprintf(mFD, "<tr>");
|
||||
for (uint32_t i=0; i < ArrayLength(title); i++) {
|
||||
fprintf(mFD, "<td><center><b>%s<b></center></td>", title[i]);
|
||||
}
|
||||
fprintf(mFD, "</tr>\n");
|
||||
PL_HashTableEnumerateEntries(mCounts, DoSingleHTMLTotal, this);
|
||||
static const char * title[] = {"Class", "Reflows"};
|
||||
fprintf(mFD, "<tr>");
|
||||
for (uint32_t i=0; i < ArrayLength(title); i++) {
|
||||
fprintf(mFD, "<td><center><b>%s<b></center></td>", title[i]);
|
||||
}
|
||||
fprintf(mFD, "</tr>\n");
|
||||
|
||||
for (auto iter = mCounts.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.Data()->DisplayHTMLTotals(iter.Key());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10377,53 +10280,26 @@ void ReflowCountMgr::DisplayHTMLTotals(const char * aStr)
|
|||
#endif // not XP!
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
int ReflowCountMgr::DoClearTotals(PLHashEntry *he, int i, void *arg)
|
||||
{
|
||||
ReflowCounter * counter = (ReflowCounter *)he->value;
|
||||
counter->ClearTotals();
|
||||
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void ReflowCountMgr::ClearTotals()
|
||||
{
|
||||
PL_HashTableEnumerateEntries(mCounts, DoClearTotals, this);
|
||||
for (auto iter = mCounts.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.Data()->ClearTotals();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void ReflowCountMgr::ClearGrandTotals()
|
||||
{
|
||||
if (nullptr != mCounts) {
|
||||
ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr);
|
||||
if (gTots == nullptr) {
|
||||
gTots = new ReflowCounter(this);
|
||||
PL_HashTableAdd(mCounts, NS_strdup(kGrandTotalsStr), gTots);
|
||||
} else {
|
||||
gTots->ClearTotals();
|
||||
gTots->SetTotalsCache();
|
||||
}
|
||||
auto entry = mCounts.LookupForAdd(kGrandTotalsStr);
|
||||
if (!entry) {
|
||||
entry.OrInsert([this]() { return new ReflowCounter(this); });
|
||||
} else {
|
||||
entry.Data()->ClearTotals();
|
||||
entry.Data()->SetTotalsCache();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
int ReflowCountMgr::DoDisplayDiffTotals(PLHashEntry *he, int i, void *arg)
|
||||
{
|
||||
bool cycledOnce = (arg != 0);
|
||||
|
||||
char *str = (char *)he->key;
|
||||
ReflowCounter * counter = (ReflowCounter *)he->value;
|
||||
|
||||
if (cycledOnce) {
|
||||
counter->CalcDiffInTotals();
|
||||
counter->DisplayDiffTotals(str);
|
||||
}
|
||||
counter->SetTotalsCache();
|
||||
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void ReflowCountMgr::DisplayDiffsInTotals()
|
||||
{
|
||||
|
@ -10435,7 +10311,14 @@ void ReflowCountMgr::DisplayDiffsInTotals()
|
|||
printf("\n");
|
||||
ClearGrandTotals();
|
||||
}
|
||||
PL_HashTableEnumerateEntries(mCounts, DoDisplayDiffTotals, (void *)mCycledOnce);
|
||||
|
||||
for (auto iter = mCounts.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (mCycledOnce) {
|
||||
iter.Data()->CalcDiffInTotals();
|
||||
iter.Data()->DisplayDiffTotals(iter.Key());
|
||||
}
|
||||
iter.Data()->SetTotalsCache();
|
||||
}
|
||||
|
||||
mCycledOnce = true;
|
||||
}
|
||||
|
|
|
@ -620,12 +620,6 @@ public:
|
|||
}
|
||||
|
||||
bool NeedStyleFlush() const { return mNeedStyleFlush; }
|
||||
/**
|
||||
* Returns true if we might need to flush layout, even if we haven't scheduled
|
||||
* one yet (as opposed to HasPendingReflow, which returns true if a flush is
|
||||
* scheduled or will soon be scheduled).
|
||||
*/
|
||||
bool NeedLayoutFlush() const { return mNeedLayoutFlush; }
|
||||
|
||||
/**
|
||||
* Callbacks will be called even if reflow itself fails for
|
||||
|
@ -1644,10 +1638,6 @@ public:
|
|||
mIsNeverPainting = aNeverPainting;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if a reflow event has been scheduled, or is going to be scheduled
|
||||
* to run in the future.
|
||||
*/
|
||||
bool HasPendingReflow() const
|
||||
{ return mObservingLayoutFlushes || mReflowContinueTimer; }
|
||||
|
||||
|
|
|
@ -2047,19 +2047,6 @@ FrameLayerBuilder::DidBeginRetainedLayerTransaction(LayerManager* aManager)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
FrameLayerBuilder::StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer)
|
||||
{
|
||||
if (!mRetainingManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayItemData* data = GetDisplayItemDataForManager(aItem, aLayer->Manager());
|
||||
NS_ASSERTION(data, "Must have already stored data for this item!");
|
||||
data->mOptLayer = aLayer;
|
||||
data->mItem = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
FrameLayerBuilder::DidEndTransaction()
|
||||
{
|
||||
|
@ -3241,16 +3228,6 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
|
|||
mNewChildLayers[data->mNewChildLayersIndex].mLayer = paintedLayer.forget();
|
||||
}
|
||||
|
||||
for (auto& item : data->mAssignedDisplayItems) {
|
||||
MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS);
|
||||
MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO);
|
||||
|
||||
InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData);
|
||||
mLayerBuilder->AddPaintedDisplayItem(data, item, *this,
|
||||
data->mAnimatedGeometryRootOffset);
|
||||
item.mDisplayItemData = nullptr;
|
||||
}
|
||||
|
||||
PaintedDisplayItemLayerUserData* userData = GetPaintedDisplayItemLayerUserData(data->mLayer);
|
||||
NS_ASSERTION(userData, "where did our user data go?");
|
||||
userData->mLastItemCount = data->mAssignedDisplayItems.Length();
|
||||
|
@ -3295,10 +3272,6 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
|
|||
data->mLayer->SetVisibleRegion(LayerIntRegion());
|
||||
data->mLayer->InvalidateWholeLayer();
|
||||
data->mLayer->SetEventRegions(EventRegions());
|
||||
|
||||
for (auto& item : data->mAssignedDisplayItems) {
|
||||
mLayerBuilder->StoreOptimizedLayerForFrame(item.mItem, layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3309,6 +3282,15 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
|
|||
FLB_LOG_PAINTED_LAYER_DECISION(data, " Selected painted layer=%p\n", layer.get());
|
||||
}
|
||||
|
||||
for (auto& item : data->mAssignedDisplayItems) {
|
||||
MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS);
|
||||
MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO);
|
||||
|
||||
InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData);
|
||||
mLayerBuilder->AddPaintedDisplayItem(data, item, *this, layer);
|
||||
item.mDisplayItemData = nullptr;
|
||||
}
|
||||
|
||||
if (mLayerBuilder->IsBuildingRetainedLayers()) {
|
||||
newLayerEntry->mVisibleRegion = data->mVisibleRegion;
|
||||
newLayerEntry->mOpaqueRegion = data->mOpaqueRegion;
|
||||
|
@ -4857,7 +4839,7 @@ void
|
|||
FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
|
||||
AssignedDisplayItem& aItem,
|
||||
ContainerState& aContainerState,
|
||||
const nsPoint& aTopLeft)
|
||||
Layer* aLayer)
|
||||
{
|
||||
PaintedLayer* layer = aLayerData->mLayer;
|
||||
PaintedDisplayItemLayerUserData* paintedData =
|
||||
|
@ -4873,7 +4855,7 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
|
|||
// We need to grab these before updating the DisplayItemData because it will overwrite them.
|
||||
nsRegion clip;
|
||||
if (aItem.mClip.ComputeRegionInClips(&aItem.mDisplayItemData->GetClip(),
|
||||
aTopLeft - paintedData->mLastAnimatedGeometryRootOrigin,
|
||||
aLayerData->mAnimatedGeometryRootOffset - paintedData->mLastAnimatedGeometryRootOrigin,
|
||||
&clip)) {
|
||||
intClip = clip.GetBounds().ScaleToOutsidePixels(paintedData->mXScale,
|
||||
paintedData->mYScale,
|
||||
|
@ -4895,6 +4877,12 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
|
|||
data = StoreDataForFrame(aItem.mItem, layer, aItem.mLayerState, nullptr);
|
||||
}
|
||||
data->mInactiveManager = tempManager;
|
||||
// We optimized this PaintedLayer into a ColorLayer/ImageLayer. Store the optimized
|
||||
// layer here.
|
||||
if (aLayer != layer) {
|
||||
data->mOptLayer = aLayer;
|
||||
data->mItem = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (tempManager) {
|
||||
|
|
|
@ -510,10 +510,10 @@ public:
|
|||
* aItem must have an underlying frame.
|
||||
* @param aTopLeft offset from active scrolled root to reference frame
|
||||
*/
|
||||
void AddPaintedDisplayItem(PaintedLayerData* aLayer,
|
||||
void AddPaintedDisplayItem(PaintedLayerData* aLayerData,
|
||||
AssignedDisplayItem& aAssignedDisplayItem,
|
||||
ContainerState& aContainerState,
|
||||
const nsPoint& aTopLeft);
|
||||
Layer* aLayer);
|
||||
|
||||
/**
|
||||
* Calls GetOldLayerForFrame on the underlying frame of the display item,
|
||||
|
@ -590,14 +590,6 @@ public:
|
|||
*/
|
||||
static gfxSize GetPaintedLayerScaleForFrame(nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Stores a Layer as the dedicated layer in the DisplayItemData for a given frame/key pair.
|
||||
*
|
||||
* Used when we optimize a PaintedLayer into an ImageLayer and want to retroactively update the
|
||||
* DisplayItemData so we can retrieve the layer from within layout.
|
||||
*/
|
||||
void StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer);
|
||||
|
||||
static void RemoveFrameFromLayerManager(const nsIFrame* aFrame,
|
||||
SmallPointerArray<DisplayItemData>& aArray);
|
||||
|
||||
|
|
|
@ -148,16 +148,6 @@ RetainedDisplayListBuilder::PreProcessDisplayList(nsDisplayList* aList,
|
|||
return modified;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsSameItem(nsDisplayItem* aFirst, nsDisplayItem* aSecond)
|
||||
{
|
||||
if (!aFirst || !aSecond) {
|
||||
return aFirst == aSecond;
|
||||
}
|
||||
return aFirst->Frame() == aSecond->Frame() &&
|
||||
aFirst->GetPerFrameKey() == aSecond->GetPerFrameKey();
|
||||
}
|
||||
|
||||
struct DisplayItemKey
|
||||
{
|
||||
bool operator ==(const DisplayItemKey& aOther) const {
|
||||
|
@ -337,8 +327,9 @@ UpdateASR(nsDisplayItem* aItem,
|
|||
* The basic algorithm is:
|
||||
*
|
||||
* For-each item i in the new list:
|
||||
* Remove items from the start of the old list up until we reach an item that also exists in the new list (leaving the matched item in place):
|
||||
* Add valid items to the merged list, destroy invalid items.
|
||||
* If the item has a matching item in the old list:
|
||||
* Remove items from the start of the old list up until we reach an item that also exists in the new list (leaving the matched item in place):
|
||||
* Add valid items to the merged list, destroy invalid items.
|
||||
* Add i into the merged list.
|
||||
* If the start of the old list matches i, remove and destroy it, otherwise mark the old version of i as used.
|
||||
* Add all remaining valid items from the old list into the merged list, skipping over (and destroying) any that are marked as used.
|
||||
|
@ -359,7 +350,7 @@ UpdateASR(nsDisplayItem* aItem,
|
|||
*
|
||||
* Merged List: A,B,D
|
||||
*
|
||||
* Example 2 (layout/reftests/display-list/retained-dl-zindex-1.html):
|
||||
* Example 2 (layout/reftests/retained-dl-zindex-1.html):
|
||||
*
|
||||
* Old List: A, B
|
||||
* Modified List: B, A
|
||||
|
@ -372,25 +363,21 @@ UpdateASR(nsDisplayItem* aItem,
|
|||
*
|
||||
* Merged List: B, A
|
||||
*
|
||||
* Example 3 (layout/reftests/display-list/1439809-1.html):
|
||||
* Example 3:
|
||||
*
|
||||
* Old List: A, B, C
|
||||
* Modified List: B, A, C
|
||||
* Old List: A, B
|
||||
* Modified List: B, A
|
||||
* Invalidations: -
|
||||
*
|
||||
* This can happen because a prior merge might have changed the ordering
|
||||
* for non-intersecting items.
|
||||
*
|
||||
* We match the B items, but don't copy A since it's also present in the new list
|
||||
* and then add the new B into the merged list. We then match A, remove it from both lists
|
||||
* and add it to the merged list. We match C, and remove items from the old list until
|
||||
* we get to it. We find B, which has alrady been added to the merged list, so we merge
|
||||
* child lists (if necessary) and then discard it. We then have C at the top of both lists,
|
||||
* so add it to the merged list.
|
||||
* and then add the new B into the merged list. We then add A, and we're done.
|
||||
*
|
||||
* Merged List: B, A, C
|
||||
* Merged List: B, A
|
||||
*
|
||||
* Example 4 (layout/reftests/display-list/retained-dl-zindex-2.html):
|
||||
* Example 4 (layout/reftests/retained-dl-zindex-2.html):
|
||||
*
|
||||
* Element A has two elements covering it (B and C), that don't intersect each
|
||||
* other. We then move C to the back.
|
||||
|
@ -434,7 +421,6 @@ RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
|
|||
Some(ActiveScrolledRoot::PickAncestor(aOutContainerASR.value(), finiteBoundsASR));
|
||||
}
|
||||
|
||||
aItem->SetMerged();
|
||||
merged.AppendToTop(aItem);
|
||||
};
|
||||
|
||||
|
@ -447,138 +433,125 @@ RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
|
|||
}
|
||||
};
|
||||
|
||||
// Build a hashtable of items in the old list so we can look for them quickly.
|
||||
// We have similar data in the nsIFrame DisplayItems() property, but it doesn't
|
||||
// know which display list items are in, and we only want to match items in
|
||||
// this list.
|
||||
nsDataHashtable<DisplayItemHashEntry, nsDisplayItem*> newListLookup(aNewList->Count());
|
||||
for (nsDisplayItem* i = aNewList->GetBottom(); i != nullptr; i = i->GetAbove()) {
|
||||
#ifdef DEBUG
|
||||
if (newListLookup.Get({ i->Frame(), i->GetPerFrameKey() }, nullptr)) {
|
||||
MOZ_CRASH_UNSAFE_PRINTF("Duplicate display items detected!: %s(0x%p) type=%d key=%d",
|
||||
i->Name(), i->Frame(),
|
||||
static_cast<int>(i->GetType()), i->GetPerFrameKey());
|
||||
const bool newListIsEmpty = aNewList->IsEmpty();
|
||||
if (!newListIsEmpty) {
|
||||
// Build a hashtable of items in the old list so we can look for them quickly.
|
||||
// We have similar data in the nsIFrame DisplayItems() property, but it doesn't
|
||||
// know which display list items are in, and we only want to match items in
|
||||
// this list.
|
||||
nsDataHashtable<DisplayItemHashEntry, nsDisplayItem*> oldListLookup(aOldList->Count());
|
||||
|
||||
for (nsDisplayItem* i = aOldList->GetBottom(); i != nullptr; i = i->GetAbove()) {
|
||||
i->SetReused(false);
|
||||
oldListLookup.Put({ i->Frame(), i->GetPerFrameKey() }, i);
|
||||
}
|
||||
|
||||
nsDataHashtable<DisplayItemHashEntry, nsDisplayItem*> newListLookup(aNewList->Count());
|
||||
for (nsDisplayItem* i = aNewList->GetBottom(); i != nullptr; i = i->GetAbove()) {
|
||||
#ifdef DEBUG
|
||||
if (newListLookup.Get({ i->Frame(), i->GetPerFrameKey() }, nullptr)) {
|
||||
MOZ_CRASH_UNSAFE_PRINTF("Duplicate display items detected!: %s(0x%p) type=%d key=%d",
|
||||
i->Name(), i->Frame(),
|
||||
static_cast<int>(i->GetType()), i->GetPerFrameKey());
|
||||
}
|
||||
#endif
|
||||
newListLookup.Put({ i->Frame(), i->GetPerFrameKey() }, i);
|
||||
}
|
||||
newListLookup.Put({ i->Frame(), i->GetPerFrameKey() }, i);
|
||||
}
|
||||
|
||||
while (nsDisplayItem* newItem = aNewList->RemoveBottom()) {
|
||||
nsDisplayItem* old = nullptr;
|
||||
while ((old = aOldList->GetBottom()) && !IsSameItem(old, newItem)) {
|
||||
if (IsAnyAncestorModified(old->FrameForInvalidation())) {
|
||||
// The old item is invalid, discard it.
|
||||
aOldList->RemoveBottom();
|
||||
old->Destroy(&mBuilder);
|
||||
modified = true;
|
||||
} else if (nsDisplayItem* newMatch = newListLookup.Get({ old->Frame(), old->GetPerFrameKey() })) {
|
||||
// TODO: This hashtable lookup should rarely succeed. We can check if it might succeed by
|
||||
// looking at the DisplayItems() list on the frame, and checking for one that isn't the same
|
||||
// pointer but has the same key. If we do find one there, then we need to find out if it's
|
||||
// in this display list or another one, which the hashtable solves.
|
||||
// We could lazily initialize the hashtable until we get to a case that actually needs it.
|
||||
modified = true;
|
||||
if (newMatch->IsMerged()) {
|
||||
// We've already put the new version of this item into the merged list,
|
||||
// so we just need to deal with recursively merging any child lists.
|
||||
// This case happens in Example 3.
|
||||
while (nsDisplayItem* newItem = aNewList->RemoveBottom()) {
|
||||
if (nsDisplayItem* oldItem = oldListLookup.Get({ newItem->Frame(), newItem->GetPerFrameKey() })) {
|
||||
// The new item has a matching counterpart in the old list that we haven't yet reached,
|
||||
// so copy all valid items from the old list into the merged list until we get to the
|
||||
// matched item.
|
||||
nsDisplayItem* old = nullptr;
|
||||
while ((old = aOldList->GetBottom()) && old != oldItem) {
|
||||
if (IsAnyAncestorModified(old->FrameForInvalidation())) {
|
||||
// The old item is invalid, discard it.
|
||||
oldListLookup.Remove({ old->Frame(), old->GetPerFrameKey() });
|
||||
aOldList->RemoveBottom();
|
||||
old->Destroy(&mBuilder);
|
||||
modified = true;
|
||||
} else if (newListLookup.Get({ old->Frame(), old->GetPerFrameKey() })) {
|
||||
// This old item is also in the new list, but we haven't got to it yet.
|
||||
// Stop now, and we'll deal with it when we get to the new entry.
|
||||
modified = true;
|
||||
break;
|
||||
} else {
|
||||
// Recurse into the child list (without a matching new list) to
|
||||
// ensure that we find and remove any invalidated items.
|
||||
if (old->GetChildren()) {
|
||||
nsDisplayList empty;
|
||||
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
|
||||
if (MergeDisplayLists(&empty, old->GetChildren(),
|
||||
old->GetChildren(), containerASRForChildren)) {
|
||||
modified = true;
|
||||
}
|
||||
UpdateASR(old, containerASRForChildren);
|
||||
old->UpdateBounds(&mBuilder);
|
||||
}
|
||||
aOldList->RemoveBottom();
|
||||
ReuseItem(old);
|
||||
}
|
||||
}
|
||||
bool destroy = false;
|
||||
if (old == oldItem) {
|
||||
// If we advanced the old list until the matching item then we can pop
|
||||
// the matching item off the old list and make sure we clean it up.
|
||||
aOldList->RemoveBottom();
|
||||
destroy = true;
|
||||
} else {
|
||||
// If we didn't get to the matching item, then mark the old item
|
||||
// as being reused (since we're adding the new version to the new
|
||||
// list now) so that we don't add it twice at the end.
|
||||
oldItem->SetReused(true);
|
||||
}
|
||||
|
||||
if (!IsAnyAncestorModified(old->FrameForInvalidation()) &&
|
||||
old->GetChildren()) {
|
||||
// Recursively merge any child lists, destroy the old item and add
|
||||
// the new one to the list.
|
||||
if (destroy &&
|
||||
oldItem->GetType() == DisplayItemType::TYPE_LAYER_EVENT_REGIONS &&
|
||||
!IsAnyAncestorModified(oldItem->FrameForInvalidation())) {
|
||||
// Event regions items don't have anything interesting other than
|
||||
// the lists of regions and frames, so we have no need to use the
|
||||
// newer item. Always use the old item instead since we assume it's
|
||||
// likely to have the bigger lists and merging will be quicker.
|
||||
if (MergeLayerEventRegions(oldItem, newItem)) {
|
||||
modified = true;
|
||||
}
|
||||
ReuseItem(oldItem);
|
||||
newItem->Destroy(&mBuilder);
|
||||
} else {
|
||||
if (IsAnyAncestorModified(oldItem->FrameForInvalidation())) {
|
||||
modified = true;
|
||||
} else if (oldItem->GetChildren()) {
|
||||
MOZ_ASSERT(newItem->GetChildren());
|
||||
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
|
||||
MergeDisplayLists(newMatch->GetChildren(), old->GetChildren(),
|
||||
newMatch->GetChildren(), containerASRForChildren);
|
||||
UpdateASR(newMatch, containerASRForChildren);
|
||||
newMatch->UpdateBounds(&mBuilder);
|
||||
if (MergeDisplayLists(newItem->GetChildren(), oldItem->GetChildren(),
|
||||
newItem->GetChildren(), containerASRForChildren)) {
|
||||
modified = true;
|
||||
}
|
||||
UpdateASR(newItem, containerASRForChildren);
|
||||
newItem->UpdateBounds(&mBuilder);
|
||||
}
|
||||
|
||||
old->Destroy(&mBuilder);
|
||||
} else {
|
||||
// This old item is also in the new list, but we haven't got to it yet.
|
||||
// Stop now, and we'll deal with it when we get to the new entry.
|
||||
break;
|
||||
if (destroy) {
|
||||
oldItem->Destroy(&mBuilder);
|
||||
}
|
||||
UseItem(newItem);
|
||||
}
|
||||
} else {
|
||||
// Recurse into the child list (without a matching new list) to
|
||||
// ensure that we find and remove any invalidated items.
|
||||
if (old->GetChildren()) {
|
||||
nsDisplayList empty;
|
||||
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
|
||||
if (MergeDisplayLists(&empty, old->GetChildren(),
|
||||
old->GetChildren(), containerASRForChildren)) {
|
||||
modified = true;
|
||||
|
||||
}
|
||||
UpdateASR(old, containerASRForChildren);
|
||||
old->UpdateBounds(&mBuilder);
|
||||
}
|
||||
aOldList->RemoveBottom();
|
||||
ReuseItem(old);
|
||||
}
|
||||
}
|
||||
bool destroy = false;
|
||||
if (IsSameItem(newItem, old)) {
|
||||
// If we advanced the old list until the matching item then we can pop
|
||||
// the matching item off the old list and make sure we clean it up.
|
||||
aOldList->RemoveBottom();
|
||||
destroy = true;
|
||||
}
|
||||
|
||||
// Recursively merge any child lists, destroy the old item and add
|
||||
// the new one to the list.
|
||||
if (destroy &&
|
||||
old->GetType() == DisplayItemType::TYPE_LAYER_EVENT_REGIONS &&
|
||||
!IsAnyAncestorModified(old->FrameForInvalidation())) {
|
||||
// Event regions items don't have anything interesting other than
|
||||
// the lists of regions and frames, so we have no need to use the
|
||||
// newer item. Always use the old item instead since we assume it's
|
||||
// likely to have the bigger lists and merging will be quicker.
|
||||
if (MergeLayerEventRegions(old, newItem)) {
|
||||
// If there was no matching item in the old list, then we only need to
|
||||
// add the new item to the merged list.
|
||||
modified = true;
|
||||
UseItem(newItem);
|
||||
}
|
||||
ReuseItem(old);
|
||||
newItem->Destroy(&mBuilder);
|
||||
} else {
|
||||
if (destroy) {
|
||||
if (!IsAnyAncestorModified(old->FrameForInvalidation()) &&
|
||||
old->GetChildren()) {
|
||||
MOZ_ASSERT(newItem->GetChildren());
|
||||
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
|
||||
if (MergeDisplayLists(newItem->GetChildren(), old->GetChildren(),
|
||||
newItem->GetChildren(), containerASRForChildren)) {
|
||||
modified = true;
|
||||
}
|
||||
UpdateASR(newItem, containerASRForChildren);
|
||||
newItem->UpdateBounds(&mBuilder);
|
||||
}
|
||||
|
||||
old->Destroy(&mBuilder);
|
||||
} else {
|
||||
modified = true;
|
||||
}
|
||||
UseItem(newItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Reuse the remaining valid items from the old display list.
|
||||
while (nsDisplayItem* old = aOldList->RemoveBottom()) {
|
||||
if (IsAnyAncestorModified(old->FrameForInvalidation())) {
|
||||
old->Destroy(&mBuilder);
|
||||
modified = true;
|
||||
} else if (nsDisplayItem* newMatch = newListLookup.Get({ old->Frame(), old->GetPerFrameKey() })) {
|
||||
MOZ_ASSERT(newMatch->IsMerged());
|
||||
if (old->GetChildren()) {
|
||||
MOZ_ASSERT(newMatch->GetChildren());
|
||||
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
|
||||
MergeDisplayLists(newMatch->GetChildren(), old->GetChildren(),
|
||||
newMatch->GetChildren(), containerASRForChildren);
|
||||
UpdateASR(newMatch, containerASRForChildren);
|
||||
newMatch->UpdateBounds(&mBuilder);
|
||||
}
|
||||
old->Destroy(&mBuilder);
|
||||
} else {
|
||||
if (!IsAnyAncestorModified(old->FrameForInvalidation()) &&
|
||||
(!old->IsReused() || newListIsEmpty)) {
|
||||
if (old->GetChildren()) {
|
||||
// We are calling MergeDisplayLists() to ensure that the display items
|
||||
// with modified or deleted children will be correctly handled.
|
||||
|
@ -600,6 +573,9 @@ RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
|
|||
}
|
||||
}
|
||||
ReuseItem(old);
|
||||
} else {
|
||||
old->Destroy(&mBuilder);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3095,7 +3095,6 @@ nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
|||
, mForceNotVisible(aBuilder->IsBuildingInvisibleItems())
|
||||
, mDisableSubpixelAA(false)
|
||||
, mReusedItem(false)
|
||||
, mMergedItem(false)
|
||||
, mBackfaceHidden(mFrame->In3DContextAndBackfaceIsHidden())
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
, mPainted(false)
|
||||
|
|
|
@ -2104,7 +2104,6 @@ public:
|
|||
, mForceNotVisible(false)
|
||||
, mDisableSubpixelAA(false)
|
||||
, mReusedItem(false)
|
||||
, mMergedItem(false)
|
||||
, mBackfaceHidden(mFrame->In3DContextAndBackfaceIsHidden())
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
, mPainted(false)
|
||||
|
@ -2178,7 +2177,6 @@ public:
|
|||
, mForceNotVisible(aOther.mForceNotVisible)
|
||||
, mDisableSubpixelAA(aOther.mDisableSubpixelAA)
|
||||
, mReusedItem(false)
|
||||
, mMergedItem(false)
|
||||
, mBackfaceHidden(mFrame->In3DContextAndBackfaceIsHidden())
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
, mPainted(false)
|
||||
|
@ -2826,16 +2824,6 @@ public:
|
|||
mReusedItem = aReused;
|
||||
}
|
||||
|
||||
bool IsMerged() const
|
||||
{
|
||||
return mMergedItem;
|
||||
}
|
||||
|
||||
void SetMerged()
|
||||
{
|
||||
mMergedItem = true;
|
||||
}
|
||||
|
||||
virtual bool CanBeReused() const { return true; }
|
||||
|
||||
virtual nsIFrame* GetDependentFrame()
|
||||
|
@ -2880,7 +2868,6 @@ protected:
|
|||
bool mForceNotVisible;
|
||||
bool mDisableSubpixelAA;
|
||||
bool mReusedItem;
|
||||
bool mMergedItem;
|
||||
bool mBackfaceHidden;
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
// True if this frame has been painted.
|
||||
|
|
|
@ -1290,7 +1290,7 @@ nsresult CacheFile::GetOnStartTime(uint64_t *_retval)
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
nsresult rv;
|
||||
*_retval = nsCString(onStartTimeStr).ToInteger64(&rv);
|
||||
*_retval = nsDependentCString(onStartTimeStr).ToInteger64(&rv);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1305,7 +1305,7 @@ nsresult CacheFile::GetOnStopTime(uint64_t *_retval)
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
nsresult rv;
|
||||
*_retval = nsCString(onStopTimeStr).ToInteger64(&rv);
|
||||
*_retval = nsDependentCString(onStopTimeStr).ToInteger64(&rv);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2548,7 +2548,7 @@ CacheFile::InitIndexEntry()
|
|||
static auto toUint16 = [](const char* s) -> uint16_t {
|
||||
if (s) {
|
||||
nsresult rv;
|
||||
uint64_t n64 = nsCString(s).ToInteger64(&rv);
|
||||
uint64_t n64 = nsDependentCString(s).ToInteger64(&rv);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return n64 <= kIndexTimeOutOfBound ? n64 : kIndexTimeOutOfBound ;
|
||||
}
|
||||
|
|
|
@ -2734,7 +2734,7 @@ CacheIndex::InitEntryFromDiskData(CacheIndexEntry *aEntry,
|
|||
return kIndexTimeNotAvailable;
|
||||
}
|
||||
nsresult rv;
|
||||
uint64_t n64 = nsCString(aUint16String).ToInteger64(&rv);
|
||||
uint64_t n64 = nsDependentCString(aUint16String).ToInteger64(&rv);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return n64 <= kIndexTimeOutOfBound ? n64 : kIndexTimeOutOfBound;
|
||||
};
|
||||
|
|
|
@ -54,7 +54,7 @@ StrEquivalent(const char16_t *a, const char16_t *b)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
nsHttpAuthCache::nsHttpAuthCache()
|
||||
: mDB(nullptr)
|
||||
: mDB(128)
|
||||
, mObserver(new OriginClearObserver(this))
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
|
||||
|
@ -65,10 +65,8 @@ nsHttpAuthCache::nsHttpAuthCache()
|
|||
|
||||
nsHttpAuthCache::~nsHttpAuthCache()
|
||||
{
|
||||
if (mDB) {
|
||||
DebugOnly<nsresult> rv = ClearAll();
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
DebugOnly<nsresult> rv = ClearAll();
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
|
||||
if (obsSvc) {
|
||||
obsSvc->RemoveObserver(mObserver, "clear-origin-attributes-data");
|
||||
|
@ -76,22 +74,6 @@ nsHttpAuthCache::~nsHttpAuthCache()
|
|||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpAuthCache::Init()
|
||||
{
|
||||
NS_ENSURE_TRUE(!mDB, NS_ERROR_ALREADY_INITIALIZED);
|
||||
|
||||
LOG(("nsHttpAuthCache::Init\n"));
|
||||
|
||||
mDB = PL_NewHashTable(128, (PLHashFunction) PL_HashString,
|
||||
(PLHashComparator) PL_CompareStrings,
|
||||
(PLHashComparator) 0, &gHashAllocOps, this);
|
||||
if (!mDB)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpAuthCache::GetAuthEntryForPath(const char *scheme,
|
||||
const char *host,
|
||||
|
@ -150,24 +132,17 @@ nsHttpAuthCache::SetAuthEntry(const char *scheme,
|
|||
LOG(("nsHttpAuthCache::SetAuthEntry [key=%s://%s:%d realm=%s path=%s metadata=%p]\n",
|
||||
scheme, host, port, realm, path, metadata));
|
||||
|
||||
if (!mDB) {
|
||||
rv = Init();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
nsAutoCString key;
|
||||
nsHttpAuthNode *node = LookupAuthNode(scheme, host, port, originSuffix, key);
|
||||
|
||||
if (!node) {
|
||||
// create a new entry node and set the given entry
|
||||
node = new nsHttpAuthNode();
|
||||
if (!node)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = node->SetAuthEntry(path, realm, creds, challenge, ident, metadata);
|
||||
if (NS_FAILED(rv))
|
||||
delete node;
|
||||
else
|
||||
PL_HashTableAdd(mDB, strdup(key.get()), node);
|
||||
mDB.Put(key, node);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -181,23 +156,16 @@ nsHttpAuthCache::ClearAuthEntry(const char *scheme,
|
|||
const char *realm,
|
||||
nsACString const &originSuffix)
|
||||
{
|
||||
if (!mDB)
|
||||
return;
|
||||
|
||||
nsAutoCString key;
|
||||
GetAuthKey(scheme, host, port, originSuffix, key);
|
||||
PL_HashTableRemove(mDB, key.get());
|
||||
mDB.Remove(key);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpAuthCache::ClearAll()
|
||||
{
|
||||
LOG(("nsHttpAuthCache::ClearAll\n"));
|
||||
|
||||
if (mDB) {
|
||||
PL_HashTableDestroy(mDB);
|
||||
mDB = 0;
|
||||
}
|
||||
mDB.Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -212,57 +180,10 @@ nsHttpAuthCache::LookupAuthNode(const char *scheme,
|
|||
nsACString const &originSuffix,
|
||||
nsCString &key)
|
||||
{
|
||||
if (!mDB)
|
||||
return nullptr;
|
||||
|
||||
GetAuthKey(scheme, host, port, originSuffix, key);
|
||||
|
||||
return (nsHttpAuthNode *) PL_HashTableLookup(mDB, key.get());
|
||||
return mDB.Get(key);
|
||||
}
|
||||
|
||||
void *
|
||||
nsHttpAuthCache::AllocTable(void *self, size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpAuthCache::FreeTable(void *self, void *item)
|
||||
{
|
||||
free(item);
|
||||
}
|
||||
|
||||
PLHashEntry *
|
||||
nsHttpAuthCache::AllocEntry(void *self, const void *key)
|
||||
{
|
||||
return (PLHashEntry *) malloc(sizeof(PLHashEntry));
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpAuthCache::FreeEntry(void *self, PLHashEntry *he, unsigned flag)
|
||||
{
|
||||
if (flag == HT_FREE_VALUE) {
|
||||
// this would only happen if PL_HashTableAdd were to replace an
|
||||
// existing entry in the hash table, but we _always_ do a lookup
|
||||
// before adding a new entry to avoid this case.
|
||||
NS_NOTREACHED("should never happen");
|
||||
}
|
||||
else if (flag == HT_FREE_ENTRY) {
|
||||
// three wonderful flavors of freeing memory ;-)
|
||||
delete (nsHttpAuthNode *) he->value;
|
||||
free((char *) he->key);
|
||||
free(he);
|
||||
}
|
||||
}
|
||||
|
||||
PLHashAllocOps nsHttpAuthCache::gHashAllocOps =
|
||||
{
|
||||
nsHttpAuthCache::AllocTable,
|
||||
nsHttpAuthCache::FreeTable,
|
||||
nsHttpAuthCache::AllocEntry,
|
||||
nsHttpAuthCache::FreeEntry
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsHttpAuthCache::OriginClearObserver, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -282,37 +203,27 @@ nsHttpAuthCache::OriginClearObserver::Observe(nsISupports *subject,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
RemoveEntriesForPattern(PLHashEntry *entry, int32_t number, void *arg)
|
||||
{
|
||||
nsDependentCString key(static_cast<const char*>(entry->key));
|
||||
|
||||
// Extract the origin attributes suffix from the key.
|
||||
int32_t colon = key.Find(NS_LITERAL_CSTRING(":"));
|
||||
MOZ_ASSERT(colon != kNotFound);
|
||||
nsDependentCSubstring oaSuffix;
|
||||
oaSuffix.Rebind(key.BeginReading(), colon);
|
||||
|
||||
// Build the OriginAttributes object of it...
|
||||
OriginAttributes oa;
|
||||
DebugOnly<bool> rv = oa.PopulateFromSuffix(oaSuffix);
|
||||
MOZ_ASSERT(rv);
|
||||
|
||||
// ...and match it against the given pattern.
|
||||
OriginAttributesPattern const *pattern = static_cast<OriginAttributesPattern const*>(arg);
|
||||
if (pattern->Matches(oa)) {
|
||||
return HT_ENUMERATE_NEXT | HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpAuthCache::ClearOriginData(OriginAttributesPattern const &pattern)
|
||||
{
|
||||
if (!mDB) {
|
||||
return;
|
||||
for (auto iter = mDB.Iter(); !iter.Done(); iter.Next()) {
|
||||
const nsACString& key = iter.Key();
|
||||
|
||||
// Extract the origin attributes suffix from the key.
|
||||
int32_t colon = key.FindChar(':');
|
||||
MOZ_ASSERT(colon != kNotFound);
|
||||
nsDependentCSubstring oaSuffix = StringHead(key, colon);
|
||||
|
||||
// Build the OriginAttributes object of it...
|
||||
OriginAttributes oa;
|
||||
DebugOnly<bool> rv = oa.PopulateFromSuffix(oaSuffix);
|
||||
MOZ_ASSERT(rv);
|
||||
|
||||
// ...and match it against the given pattern.
|
||||
if (pattern.Matches(oa)) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
PL_HashTableEnumerateEntries(mDB, RemoveEntriesForPattern, (void*)&pattern);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
#include "nsError.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsStringFwd.h"
|
||||
#include "plhash.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -166,6 +167,7 @@ private:
|
|||
nsTArray<nsAutoPtr<nsHttpAuthEntry> > mList;
|
||||
|
||||
friend class nsHttpAuthCache;
|
||||
friend class nsAutoPtr<nsHttpAuthNode>; // needs to call the destructor
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -179,8 +181,6 @@ public:
|
|||
nsHttpAuthCache();
|
||||
~nsHttpAuthCache();
|
||||
|
||||
MOZ_MUST_USE nsresult Init();
|
||||
|
||||
// |scheme|, |host|, and |port| are required
|
||||
// |path| can be null
|
||||
// |entry| is either null or a weak reference
|
||||
|
@ -233,14 +233,6 @@ private:
|
|||
nsACString const &originSuffix,
|
||||
nsCString &key);
|
||||
|
||||
// hash table allocation functions
|
||||
static void* AllocTable(void *, size_t size);
|
||||
static void FreeTable(void *, void *item);
|
||||
static PLHashEntry* AllocEntry(void *, const void *key);
|
||||
static void FreeEntry(void *, PLHashEntry *he, unsigned flag);
|
||||
|
||||
static PLHashAllocOps gHashAllocOps;
|
||||
|
||||
class OriginClearObserver : public nsIObserver {
|
||||
virtual ~OriginClearObserver() {}
|
||||
public:
|
||||
|
@ -253,7 +245,8 @@ private:
|
|||
void ClearOriginData(OriginAttributesPattern const &pattern);
|
||||
|
||||
private:
|
||||
PLHashTable *mDB; // "host:port" --> nsHttpAuthNode
|
||||
using AuthNodeTable = nsClassHashtable<nsCStringHashKey, nsHttpAuthNode>;
|
||||
AuthNodeTable mDB; // "host:port" --> nsHttpAuthNode
|
||||
RefPtr<OriginClearObserver> mObserver;
|
||||
};
|
||||
|
||||
|
|
|
@ -501,12 +501,6 @@ nsHttpHandler::Init()
|
|||
mSessionStartTime = NowInSeconds();
|
||||
mHandlerActive = true;
|
||||
|
||||
rv = mAuthCache.Init();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mPrivateAuthCache.Init();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = InitConnectionMgr();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "nsHTMLTags.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsStaticAtom.h"
|
||||
|
@ -24,31 +25,8 @@ const char16_t* const nsHTMLTags::sTagUnicodeTable[] = {
|
|||
#undef HTML_OTHER
|
||||
|
||||
int32_t nsHTMLTags::gTableRefCount;
|
||||
PLHashTable* nsHTMLTags::gTagTable;
|
||||
PLHashTable* nsHTMLTags::gTagAtomTable;
|
||||
|
||||
// char16_t* -> id hash
|
||||
static PLHashNumber
|
||||
HTMLTagsHashCodeUCPtr(const void *key)
|
||||
{
|
||||
return HashString(static_cast<const char16_t*>(key));
|
||||
}
|
||||
|
||||
static int
|
||||
HTMLTagsKeyCompareUCPtr(const void *key1, const void *key2)
|
||||
{
|
||||
const char16_t *str1 = (const char16_t *)key1;
|
||||
const char16_t *str2 = (const char16_t *)key2;
|
||||
|
||||
return nsCRT::strcmp(str1, str2) == 0;
|
||||
}
|
||||
|
||||
// nsAtom* -> id hash
|
||||
static PLHashNumber
|
||||
HTMLTagsHashCodeAtom(const void *key)
|
||||
{
|
||||
return NS_PTR_TO_INT32(key) >> 2;
|
||||
}
|
||||
nsHTMLTags::TagStringHash* nsHTMLTags::gTagTable;
|
||||
nsHTMLTags::TagAtomHash* nsHTMLTags::gTagAtomTable;
|
||||
|
||||
#define NS_HTMLTAG_NAME_MAX_LENGTH 10
|
||||
|
||||
|
@ -114,15 +92,8 @@ nsHTMLTags::AddRefTable(void)
|
|||
if (gTableRefCount++ == 0) {
|
||||
NS_ASSERTION(!gTagTable && !gTagAtomTable, "pre existing hash!");
|
||||
|
||||
gTagTable = PL_NewHashTable(64, HTMLTagsHashCodeUCPtr,
|
||||
HTMLTagsKeyCompareUCPtr, PL_CompareValues,
|
||||
nullptr, nullptr);
|
||||
NS_ENSURE_TRUE(gTagTable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
gTagAtomTable = PL_NewHashTable(64, HTMLTagsHashCodeAtom,
|
||||
PL_CompareValues, PL_CompareValues,
|
||||
nullptr, nullptr);
|
||||
NS_ENSURE_TRUE(gTagAtomTable, NS_ERROR_OUT_OF_MEMORY);
|
||||
gTagTable = new TagStringHash(64);
|
||||
gTagAtomTable = new TagAtomHash(64);
|
||||
|
||||
// Fill in gTagTable with the above static char16_t strings as
|
||||
// keys and the value of the corresponding enum as the value in
|
||||
|
@ -130,11 +101,14 @@ nsHTMLTags::AddRefTable(void)
|
|||
|
||||
int32_t i;
|
||||
for (i = 0; i < NS_HTML_TAG_MAX; ++i) {
|
||||
PL_HashTableAdd(gTagTable, sTagUnicodeTable[i],
|
||||
NS_INT32_TO_PTR(i + 1));
|
||||
|
||||
PL_HashTableAdd(gTagAtomTable, sTagAtomTable[i],
|
||||
NS_INT32_TO_PTR(i + 1));
|
||||
const char16_t* tagName = sTagUnicodeTable[i];
|
||||
const nsHTMLTag tagValue = static_cast<nsHTMLTag>(i + 1);
|
||||
// We use AssignLiteral here to avoid a string copy. This is okay
|
||||
// because this is truly static data.
|
||||
nsString tmp;
|
||||
tmp.AssignLiteral(tagName, nsString::char_traits::length(tagName));
|
||||
gTagTable->Put(tmp, tagValue);
|
||||
gTagAtomTable->Put(sTagAtomTable[i], tagValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,14 +120,10 @@ void
|
|||
nsHTMLTags::ReleaseTable(void)
|
||||
{
|
||||
if (0 == --gTableRefCount) {
|
||||
if (gTagTable) {
|
||||
// Nothing to delete/free in this table, just destroy the table.
|
||||
|
||||
PL_HashTableDestroy(gTagTable);
|
||||
PL_HashTableDestroy(gTagAtomTable);
|
||||
gTagTable = nullptr;
|
||||
gTagAtomTable = nullptr;
|
||||
}
|
||||
delete gTagTable;
|
||||
delete gTagAtomTable;
|
||||
gTagTable = nullptr;
|
||||
gTagAtomTable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,33 +137,28 @@ nsHTMLTags::StringTagToId(const nsAString& aTagName)
|
|||
return eHTMLTag_userdefined;
|
||||
}
|
||||
|
||||
char16_t buf[NS_HTMLTAG_NAME_MAX_LENGTH + 1];
|
||||
// Setup a stack allocated string buffer with the appropriate length.
|
||||
nsAutoString lowerCase;
|
||||
lowerCase.SetLength(length);
|
||||
|
||||
nsAString::const_iterator iter;
|
||||
uint32_t i = 0;
|
||||
char16_t c;
|
||||
|
||||
aTagName.BeginReading(iter);
|
||||
// Operate on the raw buffers to avoid bounds checks.
|
||||
auto src = aTagName.BeginReading();
|
||||
auto dst = lowerCase.BeginWriting();
|
||||
|
||||
// Fast lowercasing-while-copying of ASCII characters into a
|
||||
// char16_t buffer
|
||||
// nsString buffer.
|
||||
|
||||
while (i < length) {
|
||||
c = *iter;
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
char16_t c = src[i];
|
||||
|
||||
if (c <= 'Z' && c >= 'A') {
|
||||
c |= 0x20; // Lowercase the ASCII character.
|
||||
}
|
||||
|
||||
buf[i] = c; // Copy ASCII character.
|
||||
|
||||
++i;
|
||||
++iter;
|
||||
dst[i] = c; // Copy ASCII character.
|
||||
}
|
||||
|
||||
buf[i] = 0;
|
||||
|
||||
return CaseSensitiveStringTagToId(buf);
|
||||
return CaseSensitiveStringTagToId(lowerCase);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -208,14 +173,15 @@ nsHTMLTags::TestTagTable()
|
|||
// Make sure we can find everything we are supposed to
|
||||
for (int i = 0; i < NS_HTML_TAG_MAX; ++i) {
|
||||
tag = sTagUnicodeTable[i];
|
||||
id = StringTagToId(nsDependentString(tag));
|
||||
const nsAString& tagString = nsDependentString(tag);
|
||||
id = StringTagToId(tagString);
|
||||
NS_ASSERTION(id != eHTMLTag_userdefined, "can't find tag id");
|
||||
|
||||
nsAutoString uname(tag);
|
||||
nsAutoString uname(tagString);
|
||||
ToUpperCase(uname);
|
||||
NS_ASSERTION(id == StringTagToId(uname), "wrong id");
|
||||
|
||||
NS_ASSERTION(id == CaseSensitiveStringTagToId(tag), "wrong id");
|
||||
NS_ASSERTION(id == CaseSensitiveStringTagToId(tagString), "wrong id");
|
||||
|
||||
atom = NS_Atomize(tag);
|
||||
NS_ASSERTION(id == CaseSensitiveAtomTagToId(atom), "wrong id");
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
#include "nsStaticAtom.h"
|
||||
#include "nsString.h"
|
||||
#include "plhash.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
/*
|
||||
Declare the enum list using the magic of preprocessing
|
||||
|
@ -40,6 +41,9 @@ enum nsHTMLTag {
|
|||
|
||||
class nsHTMLTags {
|
||||
public:
|
||||
using TagStringHash = nsDataHashtable<nsStringHashKey, nsHTMLTag>;
|
||||
using TagAtomHash = nsDataHashtable<nsPtrHashKey<nsAtom>, nsHTMLTag>;
|
||||
|
||||
static void RegisterAtoms(void);
|
||||
static nsresult AddRefTable(void);
|
||||
static void ReleaseTable(void);
|
||||
|
@ -51,23 +55,20 @@ public:
|
|||
return StringTagToId(nsDependentAtomString(aTagName));
|
||||
}
|
||||
|
||||
static nsHTMLTag CaseSensitiveStringTagToId(const char16_t* aTagName)
|
||||
static nsHTMLTag CaseSensitiveStringTagToId(const nsAString& aTagName)
|
||||
{
|
||||
NS_ASSERTION(gTagTable, "no lookup table, needs addref");
|
||||
NS_ASSERTION(aTagName, "null tagname!");
|
||||
|
||||
void* tag = PL_HashTableLookupConst(gTagTable, aTagName);
|
||||
|
||||
return tag ? (nsHTMLTag)NS_PTR_TO_INT32(tag) : eHTMLTag_userdefined;
|
||||
nsHTMLTag* tag = gTagTable->GetValue(aTagName);
|
||||
return tag ? *tag : eHTMLTag_userdefined;
|
||||
}
|
||||
static nsHTMLTag CaseSensitiveAtomTagToId(nsAtom* aTagName)
|
||||
{
|
||||
NS_ASSERTION(gTagAtomTable, "no lookup table, needs addref");
|
||||
NS_ASSERTION(aTagName, "null tagname!");
|
||||
|
||||
void* tag = PL_HashTableLookupConst(gTagAtomTable, aTagName);
|
||||
|
||||
return tag ? (nsHTMLTag)NS_PTR_TO_INT32(tag) : eHTMLTag_userdefined;
|
||||
nsHTMLTag* tag = gTagAtomTable->GetValue(aTagName);
|
||||
return tag ? *tag : eHTMLTag_userdefined;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -80,8 +81,8 @@ private:
|
|||
static const char16_t* const sTagUnicodeTable[];
|
||||
|
||||
static int32_t gTableRefCount;
|
||||
static PLHashTable* gTagTable;
|
||||
static PLHashTable* gTagAtomTable;
|
||||
static TagStringHash* gTagTable;
|
||||
static TagAtomHash* gTagAtomTable;
|
||||
};
|
||||
|
||||
#endif /* nsHTMLTags_h___ */
|
||||
|
|
|
@ -1,264 +1,264 @@
|
|||
[Default Applications]
|
||||
application/csv=xdg-open.html
|
||||
application/excel=xdg-open.html
|
||||
application/msexcel=xdg-open.html
|
||||
application/msword=xdg-open.html
|
||||
application/ogg=xdg-open.html
|
||||
application/oxps=xdg-open.html
|
||||
application/pdf=xdg-open.html
|
||||
application/postscript=xdg-open.html
|
||||
application/rtf=xdg-open.html
|
||||
application/tab-separated-values=xdg-open.html
|
||||
application/vnd.debian.binary-package=xdg-open.html
|
||||
application/vnd.ms-cab-compressed=xdg-open.html
|
||||
application/vnd.lotus-1-2-3=xdg-open.html
|
||||
application/vnd.ms-excel=xdg-open.html
|
||||
application/vnd.ms-word=xdg-open.html
|
||||
application/vnd.ms-xpsdocument=xdg-open.html
|
||||
application/vnd.rn-realmedia=xdg-open.html
|
||||
application/vnd.sun.xml.base=xdg-open.html
|
||||
application/vnd.sun.xml.calc=xdg-open.html
|
||||
application/vnd.sun.xml.calc.template=xdg-open.html
|
||||
application/vnd.sun.xml.draw=xdg-open.html
|
||||
application/vnd.sun.xml.draw.template=xdg-open.html
|
||||
application/vnd.sun.xml.math=xdg-open.html
|
||||
application/vnd.sun.xml.writer=xdg-open.html
|
||||
application/vnd.sun.xml.writer.template=xdg-open.html
|
||||
application/vnd.sun.xml.writer.global=xdg-open.html
|
||||
application/vnd.oasis.opendocument.database=xdg-open.html
|
||||
application/vnd.oasis.opendocument.formula=xdg-open.html
|
||||
application/vnd.oasis.opendocument.graphics=xdg-open.html
|
||||
application/vnd.oasis.opendocument.graphics-template=xdg-open.html
|
||||
application/vnd.oasis.opendocument.presentation=xdg-open.html
|
||||
application/vnd.oasis.opendocument.presentation-template=xdg-open.html
|
||||
application/vnd.oasis.opendocument.spreadsheet=xdg-open.html
|
||||
application/vnd.oasis.opendocument.spreadsheet-template=xdg-open.html
|
||||
application/vnd.oasis.opendocument.text=xdg-open.html
|
||||
application/vnd.oasis.opendocument.text-template=xdg-open.html
|
||||
application/vnd.oasis.opendocument.text-web=xdg-open.html
|
||||
application/vnd.oasis.opendocument.text-master=xdg-open.html
|
||||
application/vnd.sun.xml.impress=xdg-open.html
|
||||
application/vnd.sun.xml.impress.template=xdg-open.html
|
||||
application/vnd.stardivision.calc=xdg-open.html
|
||||
application/vnd.stardivision.draw=xdg-open.html
|
||||
application/vnd.stardivision.impress=xdg-open.html
|
||||
application/vnd.stardivision.math=xdg-open.html
|
||||
application/vnd.stardivision.writer=xdg-open.html
|
||||
application/mspowerpoint=xdg-open.html
|
||||
application/vnd.ms-powerpoint=xdg-open.html
|
||||
application/vnd.wordperfect=xdg-open.html
|
||||
application/wordperfect=xdg-open.html
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.document=xdg-open.html
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.template=xdg-open.html
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet=xdg-open.html
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.template=xdg-open.html
|
||||
application/vnd.openxmlformats-officedocument.presentationml.slide=xdg-open.html
|
||||
application/vnd.openxmlformats-officedocument.presentationml.slideshow=xdg-open.html
|
||||
application/vnd.openxmlformats-officedocument.presentationml.presentation=xdg-open.html
|
||||
application/vnd.openxmlformats-officedocument.presentationml.template=xdg-open.html
|
||||
application/x-123=xdg-open.html
|
||||
application/x-abiword=xdg-open.html
|
||||
application/x-applix-spreadsheet=xdg-open.html
|
||||
application/x-ar=xdg-open.html
|
||||
application/x-arj=xdg-open.html
|
||||
application/x-audacity-project=xdg-open.html
|
||||
application/x-bzdvi=xdg-open.html
|
||||
application/x-bzip-compressed-tar=xdg-open.html
|
||||
application/x-bzip=xdg-open.html
|
||||
application/x-bzpdf=xdg-open.html
|
||||
application/x-bzpostscript=xdg-open.html
|
||||
application/x-cbr=xdg-open.html
|
||||
application/x-cbt=xdg-open.html
|
||||
application/x-cbz=xdg-open.html
|
||||
application/x-compressed-tar=xdg-open.html
|
||||
application/x-compress=xdg-open.html
|
||||
application/x-cab=xdg-open.html
|
||||
application/x-ms-cab-compressed=xdg-open.html
|
||||
application/x-deb=xdg-open.html
|
||||
application/x-debian-package=xdg-open.html
|
||||
application/x-dos_ms_excel=xdg-open.html
|
||||
application/x-dvi=xdg-open.html
|
||||
application/x-ear=xdg-open.html
|
||||
application/x-excel=xdg-open.html
|
||||
application/x-extension-m4a=xdg-open.html
|
||||
application/x-extension-mp4=xdg-open.html
|
||||
application/x-flac=xdg-open.html
|
||||
application/x-glade=xdg-open.html
|
||||
application/x-gnumeric=xdg-open.html
|
||||
application/x-gtar=xdg-open.html
|
||||
application/x-gzdvi=xdg-open.html
|
||||
application/x-gzip=xdg-open.html
|
||||
application/x-gzpdf=xdg-open.html
|
||||
application/x-gzpostscript=xdg-open.html
|
||||
application/xhtml+xml=xdg-open.html
|
||||
application/x-jar=xdg-open.html
|
||||
application/x-java-archive=xdg-open.html
|
||||
application/x-java-jnlp-file=xdg-open.html
|
||||
application/x-lha=xdg-open.html
|
||||
application/x-lhz=xdg-open.html
|
||||
application/xls=xdg-open.html
|
||||
application/x-lzop=xdg-open.html
|
||||
application/x-matroska=xdg-open.html
|
||||
application/x-mps=xdg-open.html
|
||||
application/x-ms-excel=xdg-open.html
|
||||
application/x-msexcel=xdg-open.html
|
||||
application/x-ogg=xdg-open.html
|
||||
application/x-oleo=xdg-open.html
|
||||
application/x-perl=xdg-open.html
|
||||
application/x-planperfect=xdg-open.html
|
||||
application/x-quattropro=xdg-open.html
|
||||
application/x-rar-compressed=xdg-open.html
|
||||
application/x-rar=xdg-open.html
|
||||
application/x-rpm=xdg-open.html
|
||||
application/x-sc=xdg-open.html
|
||||
application/x-shockwave-flash=xdg-open.html
|
||||
application/x-sylk=xdg-open.html
|
||||
application/x-tar=xdg-open.html
|
||||
application/x-war=xdg-open.html
|
||||
application/x-xbase=xdg-open.html
|
||||
application/x-xls=xdg-open.html
|
||||
application/x-xzpdf=xdg-open.html
|
||||
application/x-zip-compressed=xdg-open.html
|
||||
application/x-zip=xdg-open.html
|
||||
application/x-zoo=xdg-open.html
|
||||
application/zip=xdg-open.html
|
||||
audio/3gpp=xdg-open.html
|
||||
audio/ac3=xdg-open.html
|
||||
audio/AMR=xdg-open.html
|
||||
audio/AMR-WB=xdg-open.html
|
||||
audio/basic=xdg-open.html
|
||||
audio/flac=xdg-open.html
|
||||
audio/midi=xdg-open.html
|
||||
audio/mp4=xdg-open.html
|
||||
audio/mpeg=xdg-open.html
|
||||
audio/mpegurl=xdg-open.html
|
||||
audio/ogg=xdg-open.html
|
||||
audio/prs.sid=xdg-open.html
|
||||
audio/vnd.rn-realaudio=xdg-open.html
|
||||
audio/x-ape=xdg-open.html
|
||||
audio/x-flac=xdg-open.html
|
||||
audio/x-gsm=xdg-open.html
|
||||
audio/x-it=xdg-open.html
|
||||
audio/x-m4a=xdg-open.html
|
||||
audio/x-matroska=xdg-open.html
|
||||
audio/x-mod=xdg-open.html
|
||||
audio/x-mp3=xdg-open.html
|
||||
audio/x-mpeg=xdg-open.html
|
||||
audio/x-mpegurl=xdg-open.html
|
||||
audio/x-ms-asf=xdg-open.html
|
||||
audio/x-ms-asx=xdg-open.html
|
||||
audio/x-ms-wax=xdg-open.html
|
||||
audio/x-ms-wma=xdg-open.html
|
||||
audio/x-musepack=xdg-open.html
|
||||
audio/x-pn-aiff=xdg-open.html
|
||||
audio/x-pn-au=xdg-open.html
|
||||
audio/x-pn-realaudio=xdg-open.html
|
||||
audio/x-pn-realaudio-plugin=xdg-open.html
|
||||
audio/x-pn-wav=xdg-open.html
|
||||
audio/x-pn-windows-acm=xdg-open.html
|
||||
audio/x-realaudio=xdg-open.html
|
||||
audio/x-real-audio=xdg-open.html
|
||||
audio/x-sbc=xdg-open.html
|
||||
audio/x-scpls=xdg-open.html
|
||||
audio/x-speex=xdg-open.html
|
||||
audio/x-tta=xdg-open.html
|
||||
audio/x-wav=xdg-open.html
|
||||
audio/x-wavpack=xdg-open.html
|
||||
audio/x-vorbis=xdg-open.html
|
||||
audio/x-vorbis+ogg=xdg-open.html
|
||||
audio/x-xm=xdg-open.html
|
||||
image/bmp=xdg-open.html
|
||||
image/gif=xdg-open.html
|
||||
image/jpeg=xdg-open.html
|
||||
image/jpg=xdg-open.html
|
||||
image/pjpeg=xdg-open.html
|
||||
image/png=xdg-open.html
|
||||
image/svg+xml=xdg-open.html
|
||||
image/tiff=xdg-open.html
|
||||
image/vnd.djvu=xdg-open.html
|
||||
image/vnd.rn-realpix=xdg-open.html
|
||||
image/x-bmp=xdg-open.html
|
||||
image/x-bzeps=xdg-open.html
|
||||
image/x-eps=xdg-open.html
|
||||
image/x-gray=xdg-open.html
|
||||
image/x-gzeps=xdg-open.html
|
||||
image/x-icb=xdg-open.html
|
||||
image/x-ico=xdg-open.html
|
||||
image/x-png=xdg-open.html
|
||||
image/x-portable-anymap=xdg-open.html
|
||||
image/x-portable-bitmap=xdg-open.html
|
||||
image/x-portable-graymap=xdg-open.html
|
||||
image/x-portable-pixmap=xdg-open.html
|
||||
image/x-psd=xdg-open.html
|
||||
image/x-xbitmap=xdg-open.html
|
||||
image/x-xpixmap=xdg-open.html
|
||||
inode/directory=xdg-open.html
|
||||
misc/ultravox=xdg-open.html
|
||||
multipart/x-zip=xdg-open.html
|
||||
text/abiword=xdg-open.html
|
||||
text/calendar=xdg-open.html
|
||||
text/comma-separated-values=xdg-open.html
|
||||
text/csv=xdg-open.html
|
||||
text/html=xdg-open.html
|
||||
text/plain=xdg-open.html
|
||||
text/richtext=xdg-open.html
|
||||
text/rtf=xdg-open.html
|
||||
text/spreadsheet=xdg-open.html
|
||||
text/tab-separated-values=xdg-open.html
|
||||
text/x-comma-separated-values=xdg-open.html
|
||||
text/x-c++hdr=xdg-open.html
|
||||
text/x-c++src=xdg-open.html
|
||||
text/x-xsrc=xdg-open.html
|
||||
text/x-chdr=xdg-open.html
|
||||
text/x-csrc=xdg-open.html
|
||||
text/x-dtd=xdg-open.html
|
||||
text/x-java=xdg-open.html
|
||||
text/mathml=xdg-open.html
|
||||
text/x-python=xdg-open.html
|
||||
text/x-sql=xdg-open.html
|
||||
text/xml=xdg-open.html
|
||||
video/3gpp=xdg-open.html
|
||||
video/dv=xdg-open.html
|
||||
video/fli=xdg-open.html
|
||||
video/flv=xdg-open.html
|
||||
video/mp2t=xdg-open.html
|
||||
video/mp4=xdg-open.html
|
||||
video/mp4v-es=xdg-open.html
|
||||
video/mpeg=xdg-open.html
|
||||
video/msvideo=xdg-open.html
|
||||
video/ogg=xdg-open.html
|
||||
video/quicktime=xdg-open.html
|
||||
video/vivo=xdg-open.html
|
||||
video/vnd.divx=xdg-open.html
|
||||
video/vnd.rn-realvideo=xdg-open.html
|
||||
video/vnd.vivo=xdg-open.html
|
||||
video/webm=xdg-open.html
|
||||
video/x-anim=xdg-open.html
|
||||
video/x-avi=xdg-open.html
|
||||
video/x-flc=xdg-open.html
|
||||
video/x-fli=xdg-open.html
|
||||
video/x-flic=xdg-open.html
|
||||
video/x-flv=xdg-open.html
|
||||
video/x-m4v=xdg-open.html
|
||||
video/x-matroska=xdg-open.html
|
||||
video/x-mpeg=xdg-open.html
|
||||
video/x-ms-asf=xdg-open.html
|
||||
video/x-ms-asx=xdg-open.html
|
||||
video/x-msvideo=xdg-open.html
|
||||
video/x-ms-wm=xdg-open.html
|
||||
video/x-ms-wmv=xdg-open.html
|
||||
video/x-ms-wmx=xdg-open.html
|
||||
video/x-ms-wvx=xdg-open.html
|
||||
video/x-nsv=xdg-open.html
|
||||
video/x-ogm+ogg=xdg-open.html
|
||||
video/x-theora+ogg=xdg-open.html
|
||||
video/x-totem-stream=xdg-open.html
|
||||
x-content/video-dvd=xdg-open.html
|
||||
x-content/video-vcd=xdg-open.html
|
||||
x-content/video-svcd=xdg-open.html
|
||||
x-content/audio-cdda=xdg-open.html
|
||||
x-content/audio-dvd=xdg-open.html
|
||||
x-content/audio-player=xdg-open.html
|
||||
x-content/image-dcf=xdg-open.html
|
||||
x-content/image-picturecd=xdg-open.html
|
||||
zz-application/zz-winassoc-xls=xdg-open.html
|
||||
application/csv=xdg-open.desktop
|
||||
application/excel=xdg-open.desktop
|
||||
application/msexcel=xdg-open.desktop
|
||||
application/msword=xdg-open.desktop
|
||||
application/ogg=xdg-open.desktop
|
||||
application/oxps=xdg-open.desktop
|
||||
application/pdf=xdg-open.desktop
|
||||
application/postscript=xdg-open.desktop
|
||||
application/rtf=xdg-open.desktop
|
||||
application/tab-separated-values=xdg-open.desktop
|
||||
application/vnd.debian.binary-package=xdg-open.desktop
|
||||
application/vnd.ms-cab-compressed=xdg-open.desktop
|
||||
application/vnd.lotus-1-2-3=xdg-open.desktop
|
||||
application/vnd.ms-excel=xdg-open.desktop
|
||||
application/vnd.ms-word=xdg-open.desktop
|
||||
application/vnd.ms-xpsdocument=xdg-open.desktop
|
||||
application/vnd.rn-realmedia=xdg-open.desktop
|
||||
application/vnd.sun.xml.base=xdg-open.desktop
|
||||
application/vnd.sun.xml.calc=xdg-open.desktop
|
||||
application/vnd.sun.xml.calc.template=xdg-open.desktop
|
||||
application/vnd.sun.xml.draw=xdg-open.desktop
|
||||
application/vnd.sun.xml.draw.template=xdg-open.desktop
|
||||
application/vnd.sun.xml.math=xdg-open.desktop
|
||||
application/vnd.sun.xml.writer=xdg-open.desktop
|
||||
application/vnd.sun.xml.writer.template=xdg-open.desktop
|
||||
application/vnd.sun.xml.writer.global=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.database=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.formula=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.graphics=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.graphics-template=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.presentation=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.presentation-template=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.spreadsheet=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.spreadsheet-template=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.text=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.text-template=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.text-web=xdg-open.desktop
|
||||
application/vnd.oasis.opendocument.text-master=xdg-open.desktop
|
||||
application/vnd.sun.xml.impress=xdg-open.desktop
|
||||
application/vnd.sun.xml.impress.template=xdg-open.desktop
|
||||
application/vnd.stardivision.calc=xdg-open.desktop
|
||||
application/vnd.stardivision.draw=xdg-open.desktop
|
||||
application/vnd.stardivision.impress=xdg-open.desktop
|
||||
application/vnd.stardivision.math=xdg-open.desktop
|
||||
application/vnd.stardivision.writer=xdg-open.desktop
|
||||
application/mspowerpoint=xdg-open.desktop
|
||||
application/vnd.ms-powerpoint=xdg-open.desktop
|
||||
application/vnd.wordperfect=xdg-open.desktop
|
||||
application/wordperfect=xdg-open.desktop
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.document=xdg-open.desktop
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.template=xdg-open.desktop
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet=xdg-open.desktop
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.template=xdg-open.desktop
|
||||
application/vnd.openxmlformats-officedocument.presentationml.slide=xdg-open.desktop
|
||||
application/vnd.openxmlformats-officedocument.presentationml.slideshow=xdg-open.desktop
|
||||
application/vnd.openxmlformats-officedocument.presentationml.presentation=xdg-open.desktop
|
||||
application/vnd.openxmlformats-officedocument.presentationml.template=xdg-open.desktop
|
||||
application/x-123=xdg-open.desktop
|
||||
application/x-abiword=xdg-open.desktop
|
||||
application/x-applix-spreadsheet=xdg-open.desktop
|
||||
application/x-ar=xdg-open.desktop
|
||||
application/x-arj=xdg-open.desktop
|
||||
application/x-audacity-project=xdg-open.desktop
|
||||
application/x-bzdvi=xdg-open.desktop
|
||||
application/x-bzip-compressed-tar=xdg-open.desktop
|
||||
application/x-bzip=xdg-open.desktop
|
||||
application/x-bzpdf=xdg-open.desktop
|
||||
application/x-bzpostscript=xdg-open.desktop
|
||||
application/x-cbr=xdg-open.desktop
|
||||
application/x-cbt=xdg-open.desktop
|
||||
application/x-cbz=xdg-open.desktop
|
||||
application/x-compressed-tar=xdg-open.desktop
|
||||
application/x-compress=xdg-open.desktop
|
||||
application/x-cab=xdg-open.desktop
|
||||
application/x-ms-cab-compressed=xdg-open.desktop
|
||||
application/x-deb=xdg-open.desktop
|
||||
application/x-debian-package=xdg-open.desktop
|
||||
application/x-dos_ms_excel=xdg-open.desktop
|
||||
application/x-dvi=xdg-open.desktop
|
||||
application/x-ear=xdg-open.desktop
|
||||
application/x-excel=xdg-open.desktop
|
||||
application/x-extension-m4a=xdg-open.desktop
|
||||
application/x-extension-mp4=xdg-open.desktop
|
||||
application/x-flac=xdg-open.desktop
|
||||
application/x-glade=xdg-open.desktop
|
||||
application/x-gnumeric=xdg-open.desktop
|
||||
application/x-gtar=xdg-open.desktop
|
||||
application/x-gzdvi=xdg-open.desktop
|
||||
application/x-gzip=xdg-open.desktop
|
||||
application/x-gzpdf=xdg-open.desktop
|
||||
application/x-gzpostscript=xdg-open.desktop
|
||||
application/xhtml+xml=xdg-open.desktop
|
||||
application/x-jar=xdg-open.desktop
|
||||
application/x-java-archive=xdg-open.desktop
|
||||
application/x-java-jnlp-file=xdg-open.desktop
|
||||
application/x-lha=xdg-open.desktop
|
||||
application/x-lhz=xdg-open.desktop
|
||||
application/xls=xdg-open.desktop
|
||||
application/x-lzop=xdg-open.desktop
|
||||
application/x-matroska=xdg-open.desktop
|
||||
application/x-mps=xdg-open.desktop
|
||||
application/x-ms-excel=xdg-open.desktop
|
||||
application/x-msexcel=xdg-open.desktop
|
||||
application/x-ogg=xdg-open.desktop
|
||||
application/x-oleo=xdg-open.desktop
|
||||
application/x-perl=xdg-open.desktop
|
||||
application/x-planperfect=xdg-open.desktop
|
||||
application/x-quattropro=xdg-open.desktop
|
||||
application/x-rar-compressed=xdg-open.desktop
|
||||
application/x-rar=xdg-open.desktop
|
||||
application/x-rpm=xdg-open.desktop
|
||||
application/x-sc=xdg-open.desktop
|
||||
application/x-shockwave-flash=xdg-open.desktop
|
||||
application/x-sylk=xdg-open.desktop
|
||||
application/x-tar=xdg-open.desktop
|
||||
application/x-war=xdg-open.desktop
|
||||
application/x-xbase=xdg-open.desktop
|
||||
application/x-xls=xdg-open.desktop
|
||||
application/x-xzpdf=xdg-open.desktop
|
||||
application/x-zip-compressed=xdg-open.desktop
|
||||
application/x-zip=xdg-open.desktop
|
||||
application/x-zoo=xdg-open.desktop
|
||||
application/zip=xdg-open.desktop
|
||||
audio/3gpp=xdg-open.desktop
|
||||
audio/ac3=xdg-open.desktop
|
||||
audio/AMR=xdg-open.desktop
|
||||
audio/AMR-WB=xdg-open.desktop
|
||||
audio/basic=xdg-open.desktop
|
||||
audio/flac=xdg-open.desktop
|
||||
audio/midi=xdg-open.desktop
|
||||
audio/mp4=xdg-open.desktop
|
||||
audio/mpeg=xdg-open.desktop
|
||||
audio/mpegurl=xdg-open.desktop
|
||||
audio/ogg=xdg-open.desktop
|
||||
audio/prs.sid=xdg-open.desktop
|
||||
audio/vnd.rn-realaudio=xdg-open.desktop
|
||||
audio/x-ape=xdg-open.desktop
|
||||
audio/x-flac=xdg-open.desktop
|
||||
audio/x-gsm=xdg-open.desktop
|
||||
audio/x-it=xdg-open.desktop
|
||||
audio/x-m4a=xdg-open.desktop
|
||||
audio/x-matroska=xdg-open.desktop
|
||||
audio/x-mod=xdg-open.desktop
|
||||
audio/x-mp3=xdg-open.desktop
|
||||
audio/x-mpeg=xdg-open.desktop
|
||||
audio/x-mpegurl=xdg-open.desktop
|
||||
audio/x-ms-asf=xdg-open.desktop
|
||||
audio/x-ms-asx=xdg-open.desktop
|
||||
audio/x-ms-wax=xdg-open.desktop
|
||||
audio/x-ms-wma=xdg-open.desktop
|
||||
audio/x-musepack=xdg-open.desktop
|
||||
audio/x-pn-aiff=xdg-open.desktop
|
||||
audio/x-pn-au=xdg-open.desktop
|
||||
audio/x-pn-realaudio=xdg-open.desktop
|
||||
audio/x-pn-realaudio-plugin=xdg-open.desktop
|
||||
audio/x-pn-wav=xdg-open.desktop
|
||||
audio/x-pn-windows-acm=xdg-open.desktop
|
||||
audio/x-realaudio=xdg-open.desktop
|
||||
audio/x-real-audio=xdg-open.desktop
|
||||
audio/x-sbc=xdg-open.desktop
|
||||
audio/x-scpls=xdg-open.desktop
|
||||
audio/x-speex=xdg-open.desktop
|
||||
audio/x-tta=xdg-open.desktop
|
||||
audio/x-wav=xdg-open.desktop
|
||||
audio/x-wavpack=xdg-open.desktop
|
||||
audio/x-vorbis=xdg-open.desktop
|
||||
audio/x-vorbis+ogg=xdg-open.desktop
|
||||
audio/x-xm=xdg-open.desktop
|
||||
image/bmp=xdg-open.desktop
|
||||
image/gif=xdg-open.desktop
|
||||
image/jpeg=xdg-open.desktop
|
||||
image/jpg=xdg-open.desktop
|
||||
image/pjpeg=xdg-open.desktop
|
||||
image/png=xdg-open.desktop
|
||||
image/svg+xml=xdg-open.desktop
|
||||
image/tiff=xdg-open.desktop
|
||||
image/vnd.djvu=xdg-open.desktop
|
||||
image/vnd.rn-realpix=xdg-open.desktop
|
||||
image/x-bmp=xdg-open.desktop
|
||||
image/x-bzeps=xdg-open.desktop
|
||||
image/x-eps=xdg-open.desktop
|
||||
image/x-gray=xdg-open.desktop
|
||||
image/x-gzeps=xdg-open.desktop
|
||||
image/x-icb=xdg-open.desktop
|
||||
image/x-ico=xdg-open.desktop
|
||||
image/x-png=xdg-open.desktop
|
||||
image/x-portable-anymap=xdg-open.desktop
|
||||
image/x-portable-bitmap=xdg-open.desktop
|
||||
image/x-portable-graymap=xdg-open.desktop
|
||||
image/x-portable-pixmap=xdg-open.desktop
|
||||
image/x-psd=xdg-open.desktop
|
||||
image/x-xbitmap=xdg-open.desktop
|
||||
image/x-xpixmap=xdg-open.desktop
|
||||
inode/directory=xdg-open.desktop
|
||||
misc/ultravox=xdg-open.desktop
|
||||
multipart/x-zip=xdg-open.desktop
|
||||
text/abiword=xdg-open.desktop
|
||||
text/calendar=xdg-open.desktop
|
||||
text/comma-separated-values=xdg-open.desktop
|
||||
text/csv=xdg-open.desktop
|
||||
text/html=xdg-open.desktop
|
||||
text/plain=xdg-open.desktop
|
||||
text/richtext=xdg-open.desktop
|
||||
text/rtf=xdg-open.desktop
|
||||
text/spreadsheet=xdg-open.desktop
|
||||
text/tab-separated-values=xdg-open.desktop
|
||||
text/x-comma-separated-values=xdg-open.desktop
|
||||
text/x-c++hdr=xdg-open.desktop
|
||||
text/x-c++src=xdg-open.desktop
|
||||
text/x-xsrc=xdg-open.desktop
|
||||
text/x-chdr=xdg-open.desktop
|
||||
text/x-csrc=xdg-open.desktop
|
||||
text/x-dtd=xdg-open.desktop
|
||||
text/x-java=xdg-open.desktop
|
||||
text/mathml=xdg-open.desktop
|
||||
text/x-python=xdg-open.desktop
|
||||
text/x-sql=xdg-open.desktop
|
||||
text/xml=xdg-open.desktop
|
||||
video/3gpp=xdg-open.desktop
|
||||
video/dv=xdg-open.desktop
|
||||
video/fli=xdg-open.desktop
|
||||
video/flv=xdg-open.desktop
|
||||
video/mp2t=xdg-open.desktop
|
||||
video/mp4=xdg-open.desktop
|
||||
video/mp4v-es=xdg-open.desktop
|
||||
video/mpeg=xdg-open.desktop
|
||||
video/msvideo=xdg-open.desktop
|
||||
video/ogg=xdg-open.desktop
|
||||
video/quicktime=xdg-open.desktop
|
||||
video/vivo=xdg-open.desktop
|
||||
video/vnd.divx=xdg-open.desktop
|
||||
video/vnd.rn-realvideo=xdg-open.desktop
|
||||
video/vnd.vivo=xdg-open.desktop
|
||||
video/webm=xdg-open.desktop
|
||||
video/x-anim=xdg-open.desktop
|
||||
video/x-avi=xdg-open.desktop
|
||||
video/x-flc=xdg-open.desktop
|
||||
video/x-fli=xdg-open.desktop
|
||||
video/x-flic=xdg-open.desktop
|
||||
video/x-flv=xdg-open.desktop
|
||||
video/x-m4v=xdg-open.desktop
|
||||
video/x-matroska=xdg-open.desktop
|
||||
video/x-mpeg=xdg-open.desktop
|
||||
video/x-ms-asf=xdg-open.desktop
|
||||
video/x-ms-asx=xdg-open.desktop
|
||||
video/x-msvideo=xdg-open.desktop
|
||||
video/x-ms-wm=xdg-open.desktop
|
||||
video/x-ms-wmv=xdg-open.desktop
|
||||
video/x-ms-wmx=xdg-open.desktop
|
||||
video/x-ms-wvx=xdg-open.desktop
|
||||
video/x-nsv=xdg-open.desktop
|
||||
video/x-ogm+ogg=xdg-open.desktop
|
||||
video/x-theora+ogg=xdg-open.desktop
|
||||
video/x-totem-stream=xdg-open.desktop
|
||||
x-content/video-dvd=xdg-open.desktop
|
||||
x-content/video-vcd=xdg-open.desktop
|
||||
x-content/video-svcd=xdg-open.desktop
|
||||
x-content/audio-cdda=xdg-open.desktop
|
||||
x-content/audio-dvd=xdg-open.desktop
|
||||
x-content/audio-player=xdg-open.desktop
|
||||
x-content/image-dcf=xdg-open.desktop
|
||||
x-content/image-picturecd=xdg-open.desktop
|
||||
zz-application/zz-winassoc-xls=xdg-open.desktop
|
||||
|
|
Загрузка…
Ссылка в новой задаче