Merge mozilla-central to autoland. CLOSED TREE

This commit is contained in:
Narcis Beleuzu 2018-03-08 20:03:58 +02:00
Родитель b3742b1eaf eb51abf4fb
Коммит 67adc3007a
51 изменённых файлов: 2426 добавлений и 1720 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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