merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2017-07-26 11:11:40 +02:00
commit 198430bca2
181 changed files with 1969 additions and 1183 deletions

View File

@ -2107,11 +2107,31 @@ DocAccessible::DoARIAOwnsRelocation(Accessible* aOwner)
#endif
// Same child on same position, no change.
if (child->Parent() == aOwner &&
child->IndexInParent() == static_cast<int32_t>(insertIdx)) {
MOZ_ASSERT(owned->ElementAt(idx) == child, "Not in sync!");
idx++;
continue;
if (child->Parent() == aOwner) {
int32_t indexInParent = child->IndexInParent();
// The child is being placed in its current index,
// eg. aria-owns='id1 id2 id3' is changed to aria-owns='id3 id2 id1'.
if (indexInParent == static_cast<int32_t>(insertIdx)) {
MOZ_ASSERT(child->IsRelocated(),
"A child, having an index in parent from aria ownded indices range, has to be aria owned");
MOZ_ASSERT(owned->ElementAt(idx) == child,
"Unexpected child in ARIA owned array");
idx++;
continue;
}
// The child is being inserted directly after its current index,
// resulting in a no-move case. This will happen when a parent aria-owns
// its last ordinal child:
// <ul aria-owns='id2'><li id='id1'></li><li id='id2'></li></ul>
if (indexInParent == static_cast<int32_t>(insertIdx) - 1) {
MOZ_ASSERT(!child->IsRelocated(), "Child should be in its ordinal position");
child->SetRelocated(true);
owned->InsertElementAt(idx, child);
idx++;
continue;
}
}
MOZ_ASSERT(owned->SafeElementAt(idx) != child, "Already in place!");
@ -2190,7 +2210,23 @@ DocAccessible::PutChildrenBack(nsTArray<RefPtr<Accessible> >* aChildren,
}
}
}
MoveChild(child, origContainer, idxInParent);
// The child may have already be in its ordinal place for 2 reasons:
// 1. It was the last ordinal child, and the first aria-owned child.
// given: <ul id="list" aria-owns="b"><li id="a"></li><li id="b"></li></ul>
// after load: $("list").setAttribute("aria-owns", "");
// 2. The preceding adopted children were just reclaimed, eg:
// given: <ul id="list"><li id="b"></li></ul>
// after load: $("list").setAttribute("aria-owns", "a b");
// later: $("list").setAttribute("aria-owns", "");
if (origContainer != owner || child->IndexInParent() != idxInParent) {
MoveChild(child, origContainer, idxInParent);
} else {
MOZ_ASSERT(!child->PrevSibling() || !child->PrevSibling()->IsRelocated(),
"No relocated child should appear before this one");
MOZ_ASSERT(!child->NextSibling() || child->NextSibling()->IsRelocated(),
"No ordinal child should appear after this one");
}
}
aChildren->RemoveElementsAt(aStartIdx, aChildren->Length() - aStartIdx);

View File

@ -36,7 +36,8 @@ BROWSER_CHROME_MANIFESTS += [
'tests/browser/e10s/browser.ini',
'tests/browser/events/browser.ini',
'tests/browser/scroll/browser.ini',
'tests/browser/states/browser.ini'
'tests/browser/states/browser.ini',
'tests/browser/tree/browser.ini'
]
with Files("**"):

View File

@ -160,13 +160,15 @@ class UnexpectedEvents {
* @param {Array} events a list of events to wait (same format as
* waitForEvent arguments)
*/
function waitForEvents(events, unexpected = [], ordered = false) {
function waitForEvents(events, ordered = false) {
let expected = events.expected || events;
let unexpected = events.unexpected || [];
// Next expected event index.
let currentIdx = 0;
let unexpectedListener = new UnexpectedEvents(unexpected);
return Promise.all(events.map((evt, idx) => {
return Promise.all(expected.map((evt, idx) => {
let promise = evt instanceof Array ? waitForEvent(...evt) : evt;
return promise.then(result => {
if (ordered) {
@ -181,6 +183,6 @@ function waitForEvents(events, unexpected = [], ordered = false) {
});
}
function waitForOrderedEvents(events, unexpected = []) {
return waitForEvents(events, unexpected, true);
function waitForOrderedEvents(events) {
return waitForEvents(events, true);
}

View File

@ -11,7 +11,7 @@
invokeSetStyle, getAccessibleDOMNodeID, getAccessibleTagName,
addAccessibleTask, findAccessibleChildByID, isDefunct,
CURRENT_CONTENT_DIR, loadScripts, loadFrameScripts, snippetToURL,
Cc, Cu */
Cc, Cu, arrayFromChildren */
const { interfaces: Ci, utils: Cu, classes: Cc } = Components;
@ -358,3 +358,8 @@ function queryInterfaces(accessible, interfaces) {
return accessible;
}
function arrayFromChildren(accessible) {
return Array.from({ length: accessible.childCount }, (c, i) =>
accessible.getChildAt(i));
}

View File

@ -0,0 +1,9 @@
[DEFAULT]
skip-if = e10s && os == 'win' && release_or_beta
support-files =
head.js
!/accessible/tests/browser/events.js
!/accessible/tests/browser/shared-head.js
!/accessible/tests/mochitest/*.js
[browser_test_aria_owns.js]

View File

@ -0,0 +1,96 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
function testChildrenIds(acc, expectedIds) {
let ids = arrayFromChildren(acc).map(child => getAccessibleDOMNodeID(child));
Assert.deepEqual(ids, expectedIds,
`Children for ${getAccessibleDOMNodeID(acc)} are wrong.`);
}
async function runTests(browser, accDoc) {
let one = findAccessibleChildByID(accDoc, "one");
let two = findAccessibleChildByID(accDoc, "two");
let three = findAccessibleChildByID(accDoc, "three");
let four = findAccessibleChildByID(accDoc, "four");
testChildrenIds(one, ["a"]);
testChildrenIds(two, ["b", "c", "d"]);
testChildrenIds(three, []);
let onReorders = waitForEvents({
expected: [
[EVENT_REORDER, "two"]], // children will be reordered via aria-owns
unexpected: [
[EVENT_REORDER, "one"], // child will remain in place
[EVENT_REORDER, "three"], // none of its children will be reclaimed
[EVENT_REORDER, "four"]] // child will remain in place
});
await ContentTask.spawn(browser, null, async function() {
// aria-own ordinal child in place, should be a no-op.
document.getElementById("one").setAttribute("aria-owns", "a");
// remove aria-owned child that is already ordinal, should be no-op.
document.getElementById("four").removeAttribute("aria-owns");
// shuffle aria-owns with markup child.
document.getElementById("two").setAttribute("aria-owns", "d c");
});
await onReorders;
testChildrenIds(one, ["a"]);
testChildrenIds(two, ["b", "d", "c"]);
testChildrenIds(three, []);
testChildrenIds(four, ["e"]);
onReorders = waitForEvent(EVENT_REORDER, "one");
await ContentTask.spawn(browser, null, async function() {
let aa = document.createElement("li");
aa.id = "aa";
document.getElementById("one").appendChild(aa);
});
await onReorders;
testChildrenIds(one, ["aa", "a"]);
onReorders = waitForEvents([
[EVENT_REORDER, "two"], // "b" will go to "three"
[EVENT_REORDER, "three"], // some children will be reclaimed and acquired
[EVENT_REORDER, "one"]]); // removing aria-owns will reorder native children
await ContentTask.spawn(browser, null, async function() {
// removing aria-owns should reorder the children
document.getElementById("one").removeAttribute("aria-owns");
// child order will be overridden by aria-owns
document.getElementById("three").setAttribute("aria-owns", "b d");
});
await onReorders;
testChildrenIds(one, ["a", "aa"]);
testChildrenIds(two, ["c"]);
testChildrenIds(three, ["b", "d"]);
}
/**
* Test caching of accessible object states
*/
addAccessibleTask(`
<ul id="one">
<li id="a">Test</li>
</ul>
<ul id="two" aria-owns="d">
<li id="b">Test 2</li>
<li id="c">Test 3</li>
</ul>
<ul id="three">
<li id="d">Test 4</li>
</ul>
<ul id="four" aria-owns="e">
<li id="e">Test 5</li>
</ul>
`, runTests);

View File

@ -0,0 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
// Load the shared-head file first.
/* import-globals-from ../shared-head.js */
Services.scriptloader.loadSubScript(
'chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js',
this);
// Loading and common.js from accessible/tests/mochitest/ for all tests, as
// well as events.js.
loadScripts({ name: 'common.js', dir: MOCHITESTS_DIR }, 'events.js', 'layout.js');

View File

@ -1445,8 +1445,6 @@ AccessibleWrap::GetIAccessibleFor(const VARIANT& aVarChild, bool* aIsDefunct)
if (XRE_IsParentProcess() && !IsProxy() && !sIDGen.IsChromeID(varChild.lVal)) {
return GetRemoteIAccessibleFor(varChild);
}
MOZ_ASSERT(XRE_IsParentProcess() ||
sIDGen.IsIDForThisContentProcess(varChild.lVal));
if (varChild.lVal > 0) {
// Gecko child indices are 0-based in contrast to indices used in MSAA.

View File

@ -911,6 +911,7 @@ var RefreshBlocker = {
this._filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Ci.nsIWebProgress);
this._filter.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_ALL);
this._filter.target = tabEventTarget;
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);

View File

@ -313,6 +313,18 @@
margin-top: -32px;
}
/* Remove default dotted outline around buttons' text */
.onboarding-tour-action-button::-moz-focus-inner {
border: 0;
}
/* Keyboard focus specific outline */
.onboarding-tour-action-button:-moz-focusring {
outline: 2px solid rgba(0,149,221,0.5);
outline-offset: 1px;
-moz-outline-radius: 2px;
}
.onboarding-tour-action-button:hover:not([disabled]) ,
#onboarding-notification-action-btn:hover {
background: #0060df;

View File

@ -35,10 +35,10 @@ module.exports = createClass({
let { boxModel } = this.props;
let { geometryEditorEnabled, layout } = boxModel;
let {
height,
height = "-",
isPositionEditable,
position,
width,
width = "-",
} = layout;
let buttonClass = "layout-geometry-editor devtools-button";

View File

@ -120,12 +120,12 @@ module.exports = createClass({
},
getHeightValue(property) {
let { layout } = this.props.boxModel;
if (property == undefined) {
return "-";
}
let { layout } = this.props.boxModel;
property -= parseFloat(layout["border-top-width"]) +
parseFloat(layout["border-bottom-width"]) +
parseFloat(layout["padding-top"]) +
@ -136,12 +136,12 @@ module.exports = createClass({
},
getWidthValue(property) {
let { layout } = this.props.boxModel;
if (property == undefined) {
return "-";
}
let { layout } = this.props.boxModel;
property -= parseFloat(layout["border-left-width"]) +
parseFloat(layout["border-right-width"]) +
parseFloat(layout["padding-left"]) +

View File

@ -2990,8 +2990,8 @@ Element::List(FILE* out, int32_t aIndent,
static_cast<unsigned long long>(State().GetInternalValue()));
fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
if (IsCommonAncestorForRangeInSelection()) {
nsRange::RangeHashTable* ranges =
static_cast<nsRange::RangeHashTable*>(GetProperty(nsGkAtoms::range));
const nsTHashtable<nsPtrHashKey<nsRange>>* ranges =
GetExistingCommonAncestorRanges();
fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
}
fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));

View File

@ -658,6 +658,19 @@ nsNodeSupportsWeakRefTearoff::GetWeakReference(nsIWeakReference** aInstancePtr)
}
//----------------------------------------------------------------------
static const size_t MaxDOMSlotSizeAllowed =
#ifdef HAVE_64BIT_BUILD
128;
#else
64;
#endif
static_assert(sizeof(nsINode::nsSlots) <= MaxDOMSlotSizeAllowed,
"DOM slots cannot be grown without consideration");
static_assert(sizeof(FragmentOrElement::nsDOMSlots) <= MaxDOMSlotSizeAllowed,
"DOM slots cannot be grown without consideration");
FragmentOrElement::nsDOMSlots::nsDOMSlots()
: nsINode::nsSlots(),
mDataset(nullptr)

View File

@ -22,7 +22,12 @@ namespace dom {
StructuredCloneBlob::StructuredCloneBlob()
: StructuredCloneHolder(CloningSupported, TransferringNotSupported,
StructuredCloneScope::DifferentProcess)
{};
{}
StructuredCloneBlob::~StructuredCloneBlob()
{
UnregisterWeakMemoryReporter(this);
}
/* static */ already_AddRefed<StructuredCloneBlob>
@ -32,7 +37,7 @@ StructuredCloneBlob::Constructor(GlobalObject& aGlobal, JS::HandleValue aValue,
{
JSContext* cx = aGlobal.Context();
RefPtr<StructuredCloneBlob> holder = new StructuredCloneBlob();
RefPtr<StructuredCloneBlob> holder = StructuredCloneBlob::Create();
Maybe<JSAutoCompartment> ac;
JS::RootedValue value(cx, aValue);
@ -104,7 +109,7 @@ StructuredCloneBlob::ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader
{
JS::RootedObject obj(aCx);
{
RefPtr<StructuredCloneBlob> holder = new StructuredCloneBlob();
RefPtr<StructuredCloneBlob> holder = StructuredCloneBlob::Create();
if (!holder->ReadStructuredCloneInternal(aCx, aReader, aHolder) ||
!holder->WrapObject(aCx, nullptr, &obj)) {
@ -181,5 +186,20 @@ StructuredCloneBlob::WrapObject(JSContext* aCx, JS::HandleObject aGivenProto, JS
return StructuredCloneHolderBinding::Wrap(aCx, this, aGivenProto, aResult);
}
NS_IMETHODIMP
StructuredCloneBlob::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize)
{
MOZ_COLLECT_REPORT(
"explicit/dom/structured-clone-holder", KIND_HEAP, UNITS_BYTES,
MallocSizeOf(this) + SizeOfExcludingThis(MallocSizeOf),
"Memory used by StructuredCloneHolder DOM objects.");
return NS_OK;
}
NS_IMPL_ISUPPORTS(StructuredCloneBlob, nsIMemoryReporter)
} // namespace dom
} // namespace mozilla

View File

@ -9,22 +9,23 @@
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/StructuredCloneHolder.h"
#include "mozilla/dom/StructuredCloneHolderBinding.h"
#include "mozilla/RefCounted.h"
#include "jsapi.h"
#include "nsIMemoryReporter.h"
#include "nsISupports.h"
namespace mozilla {
namespace dom {
class StructuredCloneBlob : public StructuredCloneHolder
, public RefCounted<StructuredCloneBlob>
class StructuredCloneBlob final : public nsIMemoryReporter
, public StructuredCloneHolder
{
public:
MOZ_DECLARE_REFCOUNTED_TYPENAME(StructuredCloneBlob)
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
explicit StructuredCloneBlob();
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMEMORYREPORTER
static JSObject* ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader,
StructuredCloneHolder* aHolder);
@ -43,12 +44,18 @@ public:
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandleObject aResult);
protected:
template <typename T, detail::RefCountAtomicity>
friend class detail::RefCounted;
~StructuredCloneBlob() = default;
virtual ~StructuredCloneBlob();
private:
explicit StructuredCloneBlob();
static already_AddRefed<StructuredCloneBlob> Create()
{
RefPtr<StructuredCloneBlob> holder = new StructuredCloneBlob();
RegisterWeakMemoryReporter(holder);
return holder.forget();
}
bool ReadStructuredCloneInternal(JSContext* aCx, JSStructuredCloneReader* aReader,
StructuredCloneHolder* aHolder);
};

View File

@ -8,6 +8,7 @@
#include "jsapi.h"
#include "js/StructuredClone.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Move.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/BindingDeclarations.h"
@ -116,6 +117,15 @@ public:
return mBuffer->data();
}
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
size_t size = 0;
if (HasData()) {
size += mBuffer->sizeOfIncludingThis(aMallocSizeOf);
}
return size;
}
protected:
UniquePtr<JSAutoStructuredCloneBuffer> mBuffer;
@ -306,6 +316,12 @@ protected:
bool mSupportsCloning;
bool mSupportsTransferring;
// SizeOfExcludingThis is inherited from StructuredCloneHolderBase. It doesn't
// account for objects in the following arrays because a) they're not expected
// to be stored in long-lived StructuredCloneHolder objects, and b) in the
// case of BlobImpl objects, MemoryBlobImpls have their own memory reporters,
// and the other types do not hold significant amounts of memory alive.
// Used for cloning blobs in the structured cloning algorithm.
nsTArray<RefPtr<BlobImpl>> mBlobImplArray;

View File

@ -7,6 +7,7 @@
#ifndef TabGroup_h
#define TabGroup_h
#include "nsHashKeys.h"
#include "nsISupportsImpl.h"
#include "nsIPrincipal.h"
#include "nsTHashtable.h"
@ -43,6 +44,7 @@ class TabChild;
// window.opener. A DocGroup is a member of exactly one TabGroup.
class DocGroup;
class TabChild;
class TabGroup final : public SchedulerGroup
{

View File

@ -1291,6 +1291,8 @@ TimeoutManager::MaybeStartThrottleTimeout()
nsCOMPtr<nsITimerCallback> callback =
new ThrottleTimeoutsCallback(&mWindow);
mThrottleTimeoutsTimer->SetTarget(EventTarget());
mThrottleTimeoutsTimer->InitWithCallback(
callback, gTimeoutThrottlingDelay, nsITimer::TYPE_ONE_SHOT);
}

View File

@ -849,6 +849,13 @@ nsFrameMessageManager::GetDocShell(nsIDocShell** aDocShell)
return NS_OK;
}
NS_IMETHODIMP
nsFrameMessageManager::GetTabEventTarget(nsIEventTarget** aTarget)
{
*aTarget = nullptr;
return NS_OK;
}
NS_IMETHODIMP
nsFrameMessageManager::Btoa(const nsAString& aBinaryData,
nsAString& aAsciiBase64String)

View File

@ -1033,7 +1033,7 @@ nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMWindowOuter *aOuterWindow)
mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false),
mLargeAllocStatus(LargeAllocStatus::NONE),
mHasTriedToCacheTopInnerWindow(false),
mNumOfIndexedDBDatabases(0), mCleanedUp(false)
mNumOfIndexedDBDatabases(0)
{
if (aOuterWindow) {
mTimeoutManager =
@ -1620,6 +1620,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mNetworkUploadObserverEnabled(false),
mNetworkDownloadObserverEnabled(false),
#endif
mCleanedUp(false),
mDialogAbuseCount(0),
mAreDialogsEnabled(true),
#ifdef DEBUG
@ -2005,10 +2006,7 @@ nsGlobalWindow::CleanUp()
mMozSelfSupport = nullptr;
if (mPerformance) {
mPerformance->Shutdown();
mPerformance = nullptr;
}
mPerformance = nullptr;
#ifdef MOZ_WEBSPEECH
mSpeechSynthesis = nullptr;
@ -4363,10 +4361,9 @@ nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded()
{
MOZ_ASSERT(IsInnerWindow());
if (mPerformance || !mDoc || mCleanedUp) {
if (mPerformance || !mDoc) {
return;
}
RefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
bool timingEnabled = false;

View File

@ -2010,6 +2010,8 @@ protected:
bool mNetworkDownloadObserverEnabled;
#endif // MOZ_B2G
bool mCleanedUp;
nsCOMPtr<nsIDOMOfflineResourceList> mApplicationCache;
using XBLPrototypeHandlerTable = nsJSThingHashtable<nsPtrHashKey<nsXBLPrototypeHandler>, JSObject*>;

View File

@ -8,6 +8,7 @@
interface mozIDOMWindowProxy;
interface nsIDocShell;
interface nsIContent;
interface nsIEventTarget;
interface nsIFrameLoader;
interface nsIPrincipal;
@ -398,6 +399,12 @@ interface nsIContentFrameMessageManager : nsIMessageManagerGlobal
* The top level docshell or null.
*/
readonly attribute nsIDocShell docShell;
/**
* Returns the SchedulerEventTarget corresponding to the TabGroup
* for this frame.
*/
readonly attribute nsIEventTarget tabEventTarget;
};
[uuid(b39a3324-b574-4f85-8cdb-274d04f807ef)]

View File

@ -23,6 +23,7 @@
#include "js/TypeDecls.h" // for Handle, Value, JSObject, JSContext
#include "mozilla/dom/DOMString.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "nsTHashtable.h"
#include <iosfwd>
// Including 'windows.h' will #define GetClassInfo to something else.
@ -51,6 +52,7 @@ class nsIURI;
class nsNodeSupportsWeakRefTearoff;
class nsNodeWeakReference;
class nsDOMMutationObserver;
class nsRange;
namespace mozilla {
class EventListenerManager;
@ -1108,6 +1110,12 @@ public:
*/
nsNodeWeakReference* MOZ_NON_OWNING_REF mWeakReference;
/**
* A set of ranges in the common ancestor for the selection to which
* this node belongs to.
*/
mozilla::UniquePtr<nsTHashtable<nsPtrHashKey<nsRange>>> mCommonAncestorRanges;
/**
* Number of descendant nodes in the uncomposed document that have been
* explicitly set as editable.
@ -1898,6 +1906,27 @@ public:
CallerType aCallerType,
ErrorResult& aRv);
const nsTHashtable<nsPtrHashKey<nsRange>>* GetExistingCommonAncestorRanges() const
{
if (!HasSlots()) {
return nullptr;
}
mozilla::UniquePtr<nsTHashtable<nsPtrHashKey<nsRange>>>& ranges =
GetExistingSlots()->mCommonAncestorRanges;
return ranges.get();
}
nsTHashtable<nsPtrHashKey<nsRange>>* GetExistingCommonAncestorRanges()
{
nsINode::nsSlots* slots = GetExistingSlots();
return slots ? slots->mCommonAncestorRanges.get() : nullptr;
}
mozilla::UniquePtr<nsTHashtable<nsPtrHashKey<nsRange>>>& GetCommonAncestorRangesPtr()
{
return Slots()->mCommonAncestorRanges;
}
protected:
// Override this function to create a custom slots class.

View File

@ -199,6 +199,14 @@ nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
return NS_OK;
}
NS_IMETHODIMP
nsInProcessTabChildGlobal::GetTabEventTarget(nsIEventTarget** aTarget)
{
nsCOMPtr<nsIEventTarget> target = GetMainThreadEventTarget();
target.forget(aTarget);
return NS_OK;
}
void
nsInProcessTabChildGlobal::FireUnloadEvent()
{

View File

@ -77,6 +77,7 @@ public:
}
NS_IMETHOD GetContent(mozIDOMWindowProxy** aContent) override;
NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) override;
NS_IMETHOD GetTabEventTarget(nsIEventTarget** aTarget) override;
NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER

View File

@ -2090,10 +2090,15 @@ CCRunnerFired(TimeStamp aDeadline, void* aData)
// Our efforts to avoid a CC have failed, so we return to let the
// timer fire once more to trigger a CC.
// Clear content unbinder before the first CC slice.
Element::ClearContentUnbinder();
// And trigger deferred deletion too.
nsCycleCollector_doDeferredDeletion();
if (!aDeadline.IsNull() && TimeStamp::Now() < aDeadline) {
// Clear content unbinder before the first CC slice.
Element::ClearContentUnbinder();
if (TimeStamp::Now() < aDeadline) {
// And trigger deferred deletion too.
nsCycleCollector_doDeferredDeletion();
}
}
return didDoWork;
}
} else {

View File

@ -772,8 +772,6 @@ protected:
// The number of active IndexedDB databases. Inner window only.
uint32_t mNumOfIndexedDBDatabases;
bool mCleanedUp;
};
#define NS_PIDOMWINDOWINNER_IID \

View File

@ -205,8 +205,11 @@ nsRange::IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
nsTHashtable<nsPtrHashKey<Selection>> ancestorSelections;
uint32_t maxRangeCount = 0;
for (; n; n = GetNextRangeCommonAncestor(n->GetParentNode())) {
RangeHashTable* ranges =
static_cast<RangeHashTable*>(n->GetProperty(nsGkAtoms::range));
nsTHashtable<nsPtrHashKey<nsRange>>* ranges =
n->GetExistingCommonAncestorRanges();
if (!ranges) {
continue;
}
for (auto iter = ranges->ConstIter(); !iter.Done(); iter.Next()) {
nsRange* range = iter.Get()->GetKey();
if (range->IsInSelection() && !range->Collapsed()) {
@ -408,12 +411,10 @@ nsRange::RegisterCommonAncestor(nsINode* aNode)
MarkDescendants(aNode);
RangeHashTable* ranges =
static_cast<RangeHashTable*>(aNode->GetProperty(nsGkAtoms::range));
UniquePtr<nsTHashtable<nsPtrHashKey<nsRange>>>& ranges =
aNode->GetCommonAncestorRangesPtr();
if (!ranges) {
ranges = new RangeHashTable;
aNode->SetProperty(nsGkAtoms::range, ranges,
nsINode::DeleteProperty<nsRange::RangeHashTable>, true);
ranges = MakeUnique<nsRange::RangeHashTable>();
}
ranges->PutEntry(this);
aNode->SetCommonAncestorForRangeInSelection();
@ -424,13 +425,14 @@ nsRange::UnregisterCommonAncestor(nsINode* aNode)
{
NS_PRECONDITION(aNode, "bad arg");
NS_ASSERTION(aNode->IsCommonAncestorForRangeInSelection(), "wrong node");
RangeHashTable* ranges =
static_cast<RangeHashTable*>(aNode->GetProperty(nsGkAtoms::range));
nsTHashtable<nsPtrHashKey<nsRange>>* ranges =
aNode->GetExistingCommonAncestorRanges();
MOZ_ASSERT(ranges);
NS_ASSERTION(ranges->GetEntry(this), "unknown range");
if (ranges->Count() == 1) {
aNode->ClearCommonAncestorForRangeInSelection();
aNode->DeleteProperty(nsGkAtoms::range);
aNode->GetCommonAncestorRangesPtr().reset();
UnmarkDescendants(aNode);
} else {
ranges->RemoveEntry(this);
@ -3396,8 +3398,8 @@ nsRange::GetRegisteredCommonAncestor()
"GetRegisteredCommonAncestor only valid for range in selection");
nsINode* ancestor = GetNextRangeCommonAncestor(mStartContainer);
while (ancestor) {
RangeHashTable* ranges =
static_cast<RangeHashTable*>(ancestor->GetProperty(nsGkAtoms::range));
nsTHashtable<nsPtrHashKey<nsRange>>* ranges =
ancestor->GetExistingCommonAncestorRanges();
if (ranges->GetEntry(this)) {
break;
}

View File

@ -393,10 +393,10 @@ protected:
/**
* For a range for which IsInSelection() is true, return the common
* ancestor for the range. This method uses the selection bits and
* nsGkAtoms::range property on the nodes to quickly find the ancestor.
* That is, it's a faster version of GetCommonAncestor that only works
* for ranges in a Selection. The method will assert and the behavior
* is undefined if called on a range where IsInSelection() is false.
* node slots to quickly find the ancestor. That is, it's a faster
* version of GetCommonAncestor that only works for ranges in a
* Selection. The method will assert and the behavior is undefined if
* called on a range where IsInSelection() is false.
*/
nsINode* GetRegisteredCommonAncestor();

View File

@ -165,9 +165,8 @@ nsTextNode::List(FILE* out, int32_t aIndent) const
fprintf(out, "Text@%p", static_cast<const void*>(this));
fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
if (IsCommonAncestorForRangeInSelection()) {
typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
RangeHashTable* ranges =
static_cast<RangeHashTable*>(GetProperty(nsGkAtoms::range));
const nsTHashtable<nsPtrHashKey<nsRange>>* ranges =
GetExistingCommonAncestorRanges();
fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
}
fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));

View File

@ -4108,9 +4108,9 @@ void
EventStateManager::NotifyMouseOut(WidgetMouseEvent* aMouseEvent,
nsIContent* aMovingInto)
{
OverOutElementsWrapper* wrapper = GetWrapperByEventID(aMouseEvent);
RefPtr<OverOutElementsWrapper> wrapper = GetWrapperByEventID(aMouseEvent);
if (!wrapper->mLastOverElement)
if (!wrapper || !wrapper->mLastOverElement)
return;
// Before firing mouseout, check for recursion
if (wrapper->mLastOverElement == wrapper->mFirstOutEventElement)
@ -4176,9 +4176,9 @@ EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
{
NS_ASSERTION(aContent, "Mouse must be over something");
OverOutElementsWrapper* wrapper = GetWrapperByEventID(aMouseEvent);
RefPtr<OverOutElementsWrapper> wrapper = GetWrapperByEventID(aMouseEvent);
if (wrapper->mLastOverElement == aContent)
if (!wrapper || wrapper->mLastOverElement == aContent)
return;
// Before firing mouseover, check for recursion
@ -4348,7 +4348,7 @@ EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
targetElement = mDocument->GetRootElement();
}
if (targetElement) {
OverOutElementsWrapper* helper = GetWrapperByEventID(aMouseEvent);
RefPtr<OverOutElementsWrapper> helper = GetWrapperByEventID(aMouseEvent);
if (helper) {
helper->mLastOverElement = targetElement;
}
@ -4363,8 +4363,8 @@ EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
// This is actually the window mouse exit or pointer leave event. We're not moving
// into any new element.
OverOutElementsWrapper* helper = GetWrapperByEventID(aMouseEvent);
if (helper->mLastOverFrame &&
RefPtr<OverOutElementsWrapper> helper = GetWrapperByEventID(aMouseEvent);
if (helper && helper->mLastOverFrame &&
nsContentUtils::GetTopLevelWidget(aMouseEvent->mWidget) !=
nsContentUtils::GetTopLevelWidget(helper->mLastOverFrame->GetNearestWidget())) {
// the Mouse/PointerOut event widget doesn't have same top widget with

View File

@ -3520,6 +3520,14 @@ TabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
return NS_OK;
}
NS_IMETHODIMP
TabChildGlobal::GetTabEventTarget(nsIEventTarget** aTarget)
{
nsCOMPtr<nsIEventTarget> target = EventTargetFor(TaskCategory::Other);
target.forget(aTarget);
return NS_OK;
}
nsIPrincipal*
TabChildGlobal::GetPrincipal()
{

View File

@ -114,6 +114,7 @@ public:
}
NS_IMETHOD GetContent(mozIDOMWindowProxy** aContent) override;
NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) override;
NS_IMETHOD GetTabEventTarget(nsIEventTarget** aTarget) override;
nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,

View File

@ -384,7 +384,11 @@ PaymentRequest::Show(ErrorResult& aRv)
}
nsresult rv = manager->ShowPayment(mInternalId);
if (NS_WARN_IF(NS_FAILED(rv))) {
promise->MaybeReject(NS_ERROR_FAILURE);
if (rv == NS_ERROR_ABORT) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
} else {
promise->MaybeReject(NS_ERROR_DOM_NOT_ALLOWED_ERR);
}
mState = eClosed;
return promise.forget();
}

View File

@ -490,6 +490,9 @@ PaymentRequestManager::CanMakePayment(const nsAString& aRequestId)
nsresult
PaymentRequestManager::ShowPayment(const nsAString& aRequestId)
{
if (mShowingRequest) {
return NS_ERROR_ABORT;
}
RefPtr<PaymentRequest> request = GetPaymentRequestById(aRequestId);
if (!request) {
return NS_ERROR_FAILURE;
@ -497,8 +500,9 @@ PaymentRequestManager::ShowPayment(const nsAString& aRequestId)
nsAutoString requestId(aRequestId);
IPCPaymentShowActionRequest action(requestId);
return SendRequestPayment(request, action);
nsresult rv = SendRequestPayment(request, action);
mShowingRequest = request;
return rv;
}
nsresult
@ -593,6 +597,8 @@ PaymentRequestManager::RespondPayment(const IPCPaymentActionResponse& aResponse)
response.payerEmail(),
response.payerPhone());
if (!response.isAccepted()) {
MOZ_ASSERT(mShowingRequest == request);
mShowingRequest = nullptr;
mRequestQueue.RemoveElement(request);
nsresult rv = ReleasePaymentChild(request);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -609,6 +615,8 @@ PaymentRequestManager::RespondPayment(const IPCPaymentActionResponse& aResponse)
}
request->RespondAbortPayment(response.isSucceeded());
if (response.isSucceeded()) {
MOZ_ASSERT(mShowingRequest == request);
mShowingRequest = nullptr;
mRequestQueue.RemoveElement(request);
nsresult rv = ReleasePaymentChild(request);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -624,6 +632,8 @@ PaymentRequestManager::RespondPayment(const IPCPaymentActionResponse& aResponse)
return NS_ERROR_FAILURE;
}
request->RespondComplete();
MOZ_ASSERT(mShowingRequest == request);
mShowingRequest = nullptr;
mRequestQueue.RemoveElement(request);
nsresult rv = ReleasePaymentChild(request);
if (NS_WARN_IF(NS_FAILED(rv))) {

View File

@ -79,6 +79,7 @@ private:
// The container for the created PaymentRequests
nsTArray<RefPtr<PaymentRequest>> mRequestQueue;
nsRefPtrHashtable<nsRefPtrHashKey<PaymentRequest>, PaymentRequestChild> mPaymentChildHash;
RefPtr<PaymentRequest> mShowingRequest;
};
} // end of namespace dom

View File

@ -306,11 +306,46 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
* 2. Check third party payment app support by traversing all
* registered third party payment apps.
*/
case nsIPaymentActionRequest::CANMAKE_ACTION:
case nsIPaymentActionRequest::CANMAKE_ACTION: {
rv = CallTestingUIAction(requestId, type);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
break;
}
/*
* TODO: Launch/inform payment UI here once the UI module is implemented.
*/
case nsIPaymentActionRequest::SHOW_ACTION:
case nsIPaymentActionRequest::SHOW_ACTION: {
if (mShowingRequest) {
nsCOMPtr<nsIPaymentShowActionResponse> showResponse =
do_CreateInstance(NS_PAYMENT_SHOW_ACTION_RESPONSE_CONTRACT_ID);
MOZ_ASSERT(showResponse);
rv = showResponse->Init(requestId,
nsIPaymentActionResponse::PAYMENT_REJECTED,
EmptyString(),
EmptyString(),
EmptyString(),
EmptyString(),
EmptyString());
nsCOMPtr<nsIPaymentActionResponse> response = do_QueryInterface(showResponse);
MOZ_ASSERT(response);
rv = RespondPayment(response);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
rv = GetPaymentRequestById(requestId, getter_AddRefs(mShowingRequest));
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
rv = CallTestingUIAction(requestId, type);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
}
break;
}
case nsIPaymentActionRequest::ABORT_ACTION:
case nsIPaymentActionRequest::COMPLETE_ACTION: {
rv = CallTestingUIAction(requestId, type);
@ -391,11 +426,26 @@ PaymentRequestService::RespondPayment(nsIPaymentActionResponse* aResponse)
rv = response->IsSucceeded(&isSucceeded);
NS_ENSURE_SUCCESS(rv, rv);
if (isSucceeded) {
mShowingRequest = nullptr;
mRequestQueue.RemoveElement(request);
}
break;
}
case nsIPaymentActionResponse::SHOW_ACTION: {
nsCOMPtr<nsIPaymentShowActionResponse> response =
do_QueryInterface(aResponse);
MOZ_ASSERT(response);
bool isAccepted;
rv = response->IsAccepted(&isAccepted);
NS_ENSURE_SUCCESS(rv, rv);
if (!isAccepted) {
mShowingRequest = nullptr;
mRequestQueue.RemoveElement(request);
}
break;
}
case nsIPaymentActionResponse::COMPLETE_ACTION: {
mShowingRequest = nullptr;
mRequestQueue.RemoveElement(request);
break;
}

View File

@ -51,6 +51,8 @@ private:
nsInterfaceHashtable<nsStringHashKey, nsIPaymentActionCallback> mCallbackHashtable;
nsCOMPtr<nsIPaymentUIService> mTestingUIService;
nsCOMPtr<nsIPaymentRequest> mShowingRequest;
};
} // end of namespace dom

View File

@ -106,7 +106,7 @@ Performance::CreateForMainThread(nsPIDOMWindowInner* aWindow,
MOZ_ASSERT(NS_IsMainThread());
RefPtr<Performance> performance =
PerformanceMainThread::Create(aWindow, aDOMTiming, aChannel);
new PerformanceMainThread(aWindow, aDOMTiming, aChannel);
return performance.forget();
}
@ -277,13 +277,18 @@ Performance::Mark(const nsAString& aName, ErrorResult& aRv)
return;
}
// Don't add the entry if the buffer is full. XXX should be removed by bug 1159003.
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
return;
}
if (IsPerformanceTimingAttribute(aName)) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
RefPtr<PerformanceMark> performanceMark =
new PerformanceMark(GetParentObject(), aName, Now());
new PerformanceMark(GetAsISupports(), aName, Now());
InsertUserEntry(performanceMark);
if (profiler_is_active()) {
@ -339,6 +344,12 @@ Performance::Measure(const nsAString& aName,
return;
}
// Don't add the entry if the buffer is full. XXX should be removed by bug
// 1159003.
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
return;
}
DOMHighResTimeStamp startTime;
DOMHighResTimeStamp endTime;
@ -369,7 +380,7 @@ Performance::Measure(const nsAString& aName,
}
RefPtr<PerformanceMeasure> performanceMeasure =
new PerformanceMeasure(GetParentObject(), aName, startTime, endTime);
new PerformanceMeasure(GetAsISupports(), aName, startTime, endTime);
InsertUserEntry(performanceMeasure);
if (profiler_is_active()) {
@ -567,11 +578,5 @@ Performance::IsObserverEnabled(JSContext* aCx, JSObject* aGlobal)
return runnable->Dispatch() && runnable->IsEnabled();
}
void
Performance::MemoryPressure()
{
mUserEntries.Clear();
}
} // dom namespace
} // mozilla namespace

View File

@ -101,11 +101,6 @@ public:
virtual nsITimedChannel* GetChannel() const = 0;
void MemoryPressure();
// This method is currently called only on the main-thread.
virtual void Shutdown() {}
protected:
Performance();
explicit Performance(nsPIDOMWindowInner* aWindow);
@ -121,6 +116,8 @@ protected:
DOMHighResTimeStamp ResolveTimestampFromName(const nsAString& aName,
ErrorResult& aRv);
virtual nsISupports* GetAsISupports() = 0;
virtual void DispatchBufferFullEvent() = 0;
virtual TimeStamp CreationTimeStamp() const = 0;

View File

@ -7,7 +7,6 @@
#include "PerformanceMainThread.h"
#include "PerformanceNavigation.h"
#include "nsICacheInfoChannel.h"
#include "nsISupportsPrimitives.h"
namespace mozilla {
namespace dom {
@ -39,40 +38,18 @@ NS_IMPL_RELEASE_INHERITED(PerformanceMainThread, Performance)
// QueryInterface implementation for PerformanceMainThread
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceMainThread)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END_INHERITING(Performance)
already_AddRefed<PerformanceMainThread>
PerformanceMainThread::Create(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
nsITimedChannel* aChannel)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aWindow, "Parent window object should be provided");
RefPtr<PerformanceMainThread> performance =
new PerformanceMainThread(aWindow, aDOMTiming, aChannel);
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (NS_WARN_IF(!obs)) {
return nullptr;
}
nsresult rv = obs->AddObserver(performance, "memory-pressure", false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
return performance.forget();
}
PerformanceMainThread::PerformanceMainThread(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
nsITimedChannel* aChannel)
: Performance(aWindow)
, mDOMTiming(aDOMTiming)
, mChannel(aChannel)
{}
{
MOZ_ASSERT(aWindow, "Parent window object should be provided");
}
PerformanceMainThread::~PerformanceMainThread()
{
@ -360,28 +337,5 @@ PerformanceMainThread::CreationTime() const
return GetDOMTiming()->GetNavigationStart();
}
NS_IMETHODIMP
PerformanceMainThread::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
AssertIsOnMainThread();
if (!strcmp(aTopic, "memory-pressure")) {
MemoryPressure();
return NS_OK;
}
return NS_OK;
}
void
PerformanceMainThread::Shutdown()
{
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "memory-pressure");
}
}
} // dom namespace
} // mozilla namespace

View File

@ -13,18 +13,16 @@ namespace mozilla {
namespace dom {
class PerformanceMainThread final : public Performance
, public nsIObserver
{
public:
PerformanceMainThread(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
nsITimedChannel* aChannel);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIOBSERVER
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PerformanceMainThread,
Performance)
static already_AddRefed<PerformanceMainThread>
Create(nsPIDOMWindowInner* aWindow, nsDOMNavigationTiming* aDOMTiming,
nsITimedChannel* aChannel);
virtual PerformanceTiming* Timing() override;
virtual PerformanceNavigation* Navigation() override;
@ -49,15 +47,14 @@ public:
return mChannel;
}
void Shutdown() override;
protected:
PerformanceMainThread(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
nsITimedChannel* aChannel);
~PerformanceMainThread();
nsISupports* GetAsISupports() override
{
return this;
}
void InsertUserEntry(PerformanceEntry* aEntry) override;
bool IsPerformanceTimingAttribute(const nsAString& aName) override;

View File

@ -64,6 +64,11 @@ public:
protected:
~PerformanceWorker();
nsISupports* GetAsISupports() override
{
return nullptr;
}
void InsertUserEntry(PerformanceEntry* aEntry) override;
void DispatchBufferFullEvent() override

View File

@ -424,7 +424,7 @@ nsresult nsPluginFile::FreePluginInfo(nsPluginInfo& info)
PL_strfree(info.fFileName);
if (info.fVersion)
mozilla::SmprintfFree(info.fVersion);
free(info.fVersion);
ZeroMemory((void *)&info, sizeof(info));

View File

@ -33,7 +33,7 @@ static void LogFunctionAndJSStack(const char* funcname) {
"Call to %s. The JS stack is:\n%s\n",
funcname,
jsstack ? jsstack : "<no JS stack>");
JS_smprintf_free(jsstack);
js_free(jsstack);
}
// bug 839452
#define LOG_FUNCTION_AND_JS_STACK() \

View File

@ -22,6 +22,7 @@ support-files =
queryCaretRectUnix.html
queryCaretRectWin.html
selectAtPoint.html
selectAtPoint-innerframe.html
sizemode_attribute.xul
window_activation.xul
window_callback_wrapping.xul

View File

@ -0,0 +1,6 @@
<html>
<body style='margin: 0; padding: 0; font-family: monospace;' onload='window.parent.onFrameLoad();'>
<div id='sel2'>ttestselection2 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut.</div>
<br/><br/>
</body>
</html>">

View File

@ -267,7 +267,7 @@ body {
<br />
<iframe id="frame1" src="data:text/html,<html><body style='margin: 0; padding: 0; font-family: monospace;' onload='window.parent.onFrameLoad();'><div id='sel2'>ttestselection2 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut.</div><br/><br/></body></html>"></iframe>
<iframe id="frame1" src="selectAtPoint-innerframe.html"></iframe>
<br/>

View File

@ -6775,23 +6775,14 @@ WorkerPrivate::MemoryPressureInternal()
{
AssertIsOnWorkerThread();
if (mScope) {
RefPtr<Console> console = mScope->GetConsoleIfExists();
if (console) {
console->ClearStorage();
}
RefPtr<Performance> performance = mScope->GetPerformanceIfExists();
if (performance) {
performance->MemoryPressure();
}
RefPtr<Console> console = mScope ? mScope->GetConsoleIfExists() : nullptr;
if (console) {
console->ClearStorage();
}
if (mDebuggerScope) {
RefPtr<Console> console = mDebuggerScope->GetConsoleIfExists();
if (console) {
console->ClearStorage();
}
console = mDebuggerScope ? mDebuggerScope->GetConsoleIfExists() : nullptr;
if (console) {
console->ClearStorage();
}
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {

View File

@ -156,11 +156,6 @@ public:
Performance* GetPerformance();
Performance* GetPerformanceIfExists() const
{
return mPerformance;
}
already_AddRefed<Promise>
Fetch(const RequestOrUSVString& aInput, const RequestInit& aInit,
CallerType aCallerType, ErrorResult& aRv);

View File

@ -1105,6 +1105,13 @@ CompositorD3D11::EndFrame()
return;
}
if (XRE_IsParentProcess() && mDevice->GetDeviceRemovedReason() != S_OK) {
gfxCriticalNote << "GFX: D3D11 skip EndFrame with device-removed.";
Compositor::EndFrame();
mCurrentRT = nullptr;
return;
}
LayoutDeviceIntSize oldSize = mSize;
EnsureSize();
if (mSize.width <= 0 || mSize.height <= 0) {

View File

@ -1651,37 +1651,37 @@ MLGDeviceD3D11::DrawInstanced(uint32_t aVertexCountPerInstance, uint32_t aInstan
void
MLGDeviceD3D11::SetPSTextures(uint32_t aSlot, uint32_t aNumTextures, TextureSource* const* aTextures)
{
StackArray<ID3D11ShaderResourceView*, 2> textures(aNumTextures);
// TextureSource guarantees that the ID3D11ShaderResourceView will be cached,
// so we don't hold a RefPtr here.
StackArray<ID3D11ShaderResourceView*, 3> views(aNumTextures);
for (size_t i = 0; i < aNumTextures; i++) {
if (!aTextures[i]) {
gfxWarning() << "Null TextureRef in SetPSTextures";
continue;
}
ID3D11ShaderResourceView* view = nullptr;
if (TextureSourceD3D11* source = aTextures[i]->AsSourceD3D11()) {
ID3D11Texture2D* texture = source->GetD3D11Texture();
if (!texture) {
gfxWarning() << "No D3D11 texture present in SetPSTextures";
continue;
}
MaybeLockTexture(texture);
view = source->GetShaderResourceView();
} else {
gfxWarning() << "Unknown texture type in SetPSTextures";
continue;
}
if (!view) {
gfxWarning() << "Failed to get shader resource view for texture";
continue;
}
textures[i] = view;
views[i] = ResolveTextureSourceForShader(aTextures[i]);
}
mCtx->PSSetShaderResources(aSlot, aNumTextures, textures.data());
mCtx->PSSetShaderResources(aSlot, aNumTextures, views.data());
}
ID3D11ShaderResourceView*
MLGDeviceD3D11::ResolveTextureSourceForShader(TextureSource* aTexture)
{
if (!aTexture) {
return nullptr;
}
if (TextureSourceD3D11* source = aTexture->AsSourceD3D11()) {
ID3D11Texture2D* texture = source->GetD3D11Texture();
if (!texture) {
gfxWarning() << "No D3D11 texture present in SetPSTextures";
return nullptr;
}
MaybeLockTexture(texture);
return source->GetShaderResourceView();
}
gfxWarning() << "Unknown texture type in SetPSTextures";
return nullptr;
}
void

View File

@ -277,6 +277,10 @@ private:
void SetInputLayout(ID3D11InputLayout* aLayout);
void SetVertexShader(ID3D11VertexShader* aShader);
// Resolve a TextureSource to an ID3D11ShaderResourceView, locking the
// texture if needed. The lock is released at the end of the frame.
ID3D11ShaderResourceView* ResolveTextureSourceForShader(TextureSource* aSource);
private:
RefPtr<ID3D11Device> mDevice;
RefPtr<ID3D11DeviceContext> mCtx;

View File

@ -1662,7 +1662,7 @@ CompositorBridgeParent::RecvAdoptChild(const uint64_t& child)
CrossProcessCompositorBridgeParent* cpcp = sIndirectLayerTrees[child].mCrossProcessParent;
if (cpcp) {
TimeStamp now = TimeStamp::Now();
cpcp->DidComposite(child, now, now);
cpcp->DidCompositeLocked(child, now, now);
}
}
parent = sIndirectLayerTrees[child].mApzcTreeManagerParent;
@ -2005,7 +2005,7 @@ CompositorBridgeParent::NotifyDidComposite(uint64_t aTransactionId, TimeStamp& a
ForEachIndirectLayerTree([&] (LayerTreeState* lts, const uint64_t& aLayersId) -> void {
if (lts->mCrossProcessParent && lts->mParent == this) {
CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
cpcp->DidComposite(aLayersId, aCompositeStart, aCompositeEnd);
cpcp->DidCompositeLocked(aLayersId, aCompositeStart, aCompositeEnd);
}
});
}

View File

@ -361,6 +361,16 @@ CrossProcessCompositorBridgeParent::DidComposite(
uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd)
{
MonitorAutoLock lock(*sIndirectLayerTreesLock);
DidCompositeLocked(aId, aCompositeStart, aCompositeEnd);
}
void
CrossProcessCompositorBridgeParent::DidCompositeLocked(
uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd)
{
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
if (LayerTransactionParent *layerTree = sIndirectLayerTrees[aId].mLayerTree) {

View File

@ -107,6 +107,12 @@ public:
virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aParent) override;
virtual mozilla::ipc::IPCResult RecvRemotePluginsReady() override { return IPC_FAIL_NO_REASON(this); }
// Use DidCompositeLocked if you already hold a lock on
// sIndirectLayerTreesLock; Otherwise use DidComposite, which would request
// the lock automatically.
void DidCompositeLocked(uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd);
virtual void DidComposite(uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd) override;

View File

@ -69,7 +69,9 @@ imgRequest::imgRequest(imgLoader* aLoader, const ImageCacheKey& aCacheKey)
, mDecodeRequested(false)
, mNewPartPending(false)
, mHadInsecureRedirect(false)
{ }
{
LOG_FUNC(gImgLog, "imgRequest::imgRequest()");
}
imgRequest::~imgRequest()
{

View File

@ -122,7 +122,7 @@ imgRequestProxy::imgRequestProxy() :
mHadDispatch(false)
{
/* member initializers and constructor code */
LOG_FUNC(gImgLog, "imgRequestProxy::imgRequestProxy");
}
imgRequestProxy::~imgRequestProxy()
@ -169,6 +169,8 @@ imgRequestProxy::~imgRequestProxy()
mCanceled = true;
GetOwner()->RemoveProxy(this, NS_OK);
}
LOG_FUNC(gImgLog, "imgRequestProxy::~imgRequestProxy");
}
nsresult

View File

@ -168,6 +168,11 @@ MessageLoop* MessageLoop::current() {
return get_tls_ptr().Get();
}
// static
void MessageLoop::set_current(MessageLoop* loop) {
get_tls_ptr().Set(loop);
}
static mozilla::Atomic<int32_t> message_loop_id_seq(0);
MessageLoop::MessageLoop(Type type, nsIThread* aThread)

View File

@ -219,6 +219,8 @@ public:
// Returns the MessageLoop object for the current thread, or null if none.
static MessageLoop* current();
static void set_current(MessageLoop* loop);
// Enables or disables the recursive task processing. This happens in the case
// of recursive message loops. Some unwanted message loop may occurs when
// using common controls or printer functions. By default, recursive task

View File

@ -17,18 +17,14 @@
#include "mozilla/BufferList.h"
#include "mozilla/mozalloc.h"
#include "mozilla/TimeStamp.h"
#ifdef FUZZING
#include "base/singleton.h"
#include "mozilla/ipc/Faulty.h"
#endif
#if !defined(RELEASE_OR_BETA) || defined(DEBUG)
#if (!defined(RELEASE_OR_BETA) && !defined(FUZZING)) || defined(DEBUG)
#define MOZ_PICKLE_SENTINEL_CHECKING
#endif
class Pickle;
class PickleIterator {
public:
explicit PickleIterator(const Pickle& pickle);

View File

@ -72,6 +72,8 @@ ProcessLink::~ProcessLink()
void
ProcessLink::Open(mozilla::ipc::Transport* aTransport, MessageLoop *aIOLoop, Side aSide)
{
mChan->AssertWorkerThread();
NS_PRECONDITION(aTransport, "need transport layer");
// FIXME need to check for valid channel
@ -130,8 +132,12 @@ ProcessLink::Open(mozilla::ipc::Transport* aTransport, MessageLoop *aIOLoop, Sid
&ProcessLink::OnTakeConnectedChannel));
}
// Should not wait here if something goes wrong with the channel.
while (!mChan->Connected() && mChan->mChannelState != ChannelError) {
// Wait until one of the runnables above changes the state of the
// channel. Note that the state could be changed again after that (to
// ChannelClosing, for example, by the IO thread). We can rely on it not
// changing back to Closed: only the worker thread changes it to closed,
// and we're on the worker thread, blocked.
while (mChan->mChannelState == ChannelClosed) {
mChan->mMonitor->Wait();
}
}

View File

@ -9,6 +9,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/BufferList.h"
#include "mozilla/MemoryReporting.h"
#include <stdint.h>
@ -339,6 +340,16 @@ class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
JS::CloneDataPolicy cloneDataPolicy,
const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
return data_.SizeOfExcludingThis(mallocSizeOf);
}
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
}
private:
// Copy and assignment are not supported.
JSAutoStructuredCloneBuffer(const JSAutoStructuredCloneBuffer& other) = delete;

View File

@ -23,7 +23,6 @@ namespace JS {
_(GetProp_DefiniteSlot) \
_(GetProp_Unboxed) \
_(GetProp_CommonGetter) \
_(GetProp_Static) \
_(GetProp_InlineAccess) \
_(GetProp_Innerize) \
_(GetProp_InlineCache) \

View File

@ -9516,15 +9516,6 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUs
if (pn2->as<PropertyAccess>().isSuper()) {
if (!emitSuperPropOp(pn2, JSOP_GETPROP_SUPER, /* isCall = */ callop))
return false;
} else if ((pn->getOp() == JSOP_FUNCALL || pn->getOp() == JSOP_FUNAPPLY) &&
pn2->expr()->getKind() == PNK_FUNCTION &&
checkRunOnceContext()) {
// Top level lambdas whose .call or .apply methods are immediately
// invoked should be treated as run once lambdas.
emittingRunOnceLambda = true;
if (!emitPropOp(pn2, callop ? JSOP_CALLPROP : JSOP_GETPROP))
return false;
emittingRunOnceLambda = false;
} else {
if (!emitPropOp(pn2, callop ? JSOP_CALLPROP : JSOP_GETPROP))
return false;

View File

@ -362,9 +362,6 @@ js::gc::GCRuntime::traceRuntimeCommon(JSTracer* trc, TraceOrMarkRuntime traceOrM
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
c->traceRoots(trc, traceOrMark);
// Trace the Gecko Profiler.
rt->geckoProfiler().trace(trc);
// Trace helper thread roots.
HelperThreadState().trace(trc);

View File

@ -11,6 +11,8 @@
#include "jit/IonBuilder.h"
#include "jit/JitCompartment.h"
using namespace js;
namespace js {
ZoneGroup::ZoneGroup(JSRuntime* runtime)
@ -147,3 +149,26 @@ ZoneGroup::deleteEmptyZone(Zone* zone)
}
} // namespace js
JS::AutoRelinquishZoneGroups::AutoRelinquishZoneGroups(JSContext* cx)
: cx(cx)
{
MOZ_ASSERT(cx == TlsContext.get());
AutoEnterOOMUnsafeRegion oomUnsafe;
for (ZoneGroupsIter group(cx->runtime()); !group.done(); group.next()) {
while (group->ownerContext().context() == cx) {
group->leave();
if (!enterList.append(group))
oomUnsafe.crash("AutoRelinquishZoneGroups");
}
}
}
JS::AutoRelinquishZoneGroups::~AutoRelinquishZoneGroups()
{
for (size_t i = 0; i < enterList.length(); i++) {
ZoneGroup* group = static_cast<ZoneGroup*>(enterList[i]);
group->enter(cx);
}
}

View File

@ -1,28 +0,0 @@
// Test bailouts from loading particular non-singleton static objects.
function wrap(fun) {
function wrapper() {
return fun.apply(this, arguments);
}
return wrapper;
}
var adder = wrap(function(a, b) { return a + b; });
var subber = wrap(function(a, b) { return a - b; });
var tmp = adder;
adder = subber;
adder = tmp;
function foo() {
var i = 0;
var a = 0;
for (var i = 0; i < 10000; i++) {
a = adder(a, 1);
a = subber(a, 1);
}
return a;
}
assertEq(foo(), 0);
adder = subber;
assertEq(foo(), -20000);

View File

@ -0,0 +1,34 @@
// Test that we don't attach ICs to idempotent caches that are incompatible
// with the cache result type.
var missingObjs = [{a:1},Object.create({a:2}),{}];
function testMissing(limit)
{
var res = 0;
for (var i = 0; i < 1000; i++) {
for (var j = 0; j < missingObjs.length; j++) {
var obj = missingObjs[j];
if (j < limit)
res += obj.a;
}
}
return res;
}
assertEq(testMissing(2), 3000);
assertEq(testMissing(3), NaN);
var lengthObjs = [{length:{a:1}},Object.create({length:{a:2}}),[0,1]];
function testArrayLength(limit)
{
var res = 0;
for (var i = 0; i < 1000; i++) {
for (var j = 0; j < lengthObjs.length; j++) {
var obj = lengthObjs[j];
if (j < limit)
res += obj.length.a;
}
}
return res;
}
assertEq(testArrayLength(2), 3000);
assertEq(testArrayLength(3), NaN);

View File

@ -2003,7 +2003,6 @@ jit::FinishBailoutToBaseline(BaselineBailoutInfo* bailoutInfo)
case Bailout_Debugger:
case Bailout_UninitializedThis:
case Bailout_BadDerivedConstructorReturn:
case Bailout_LoadStaticObject:
// Do nothing.
break;

View File

@ -4808,7 +4808,8 @@ BaselineCompiler::emit_JSOP_RESUME()
Label skip;
AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler().addressOfEnabled());
masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &skip);
masm.loadPtr(AbsoluteAddress(cx->addressOfProfilingActivation()), scratchReg);
masm.loadJSContext(scratchReg);
masm.loadPtr(Address(scratchReg, JSContext::offsetOfProfilingActivation()), scratchReg);
masm.storePtr(masm.getStackPointer(),
Address(scratchReg, JitActivation::offsetOfLastProfilingFrame()));
masm.bind(&skip);

View File

@ -810,8 +810,10 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_
if (stub->state().canAttachStub()) {
ICStubEngine engine = ICStubEngine::Baseline;
GetPropIRGenerator gen(cx, script, pc, CacheKind::GetElem, stub->state().mode(),
&isTemporarilyUnoptimizable, lhs, rhs, lhs, CanAttachGetter::Yes);
GetPropIRGenerator gen(cx, script, pc,
CacheKind::GetElem, stub->state().mode(),
&isTemporarilyUnoptimizable, lhs, rhs, lhs,
GetPropertyResultFlags::All);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Monitored,
@ -884,7 +886,7 @@ DoGetElemSuperFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback*
ICStubEngine engine = ICStubEngine::Baseline;
GetPropIRGenerator gen(cx, script, pc, CacheKind::GetElemSuper, stub->state().mode(),
&isTemporarilyUnoptimizable, lhs, rhs, receiver,
CanAttachGetter::Yes);
GetPropertyResultFlags::All);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Monitored,

View File

@ -1040,7 +1040,7 @@ bool
BaselineInspector::megamorphicGetterSetterFunction(jsbytecode* pc, bool isGetter,
JSFunction** getterOrSetter)
{
if (!hasBaselineScript() || *pc == JSOP_SETALIASEDVAR)
if (!hasBaselineScript())
return false;
*getterOrSetter = nullptr;
@ -1191,7 +1191,7 @@ BaselineInspector::commonSetPropFunction(jsbytecode* pc, JSObject** holder, Shap
ReceiverVector& receivers,
ObjectGroupVector& convertUnboxedGroups)
{
if (!hasBaselineScript() || *pc == JSOP_SETALIASEDVAR)
if (!hasBaselineScript())
return false;
MOZ_ASSERT(receivers.empty());

View File

@ -1266,8 +1266,10 @@ jit::MarkActiveBaselineScripts(Zone* zone)
if (zone->isAtomsZone())
return;
JSContext* cx = TlsContext.get();
for (JitActivationIterator iter(cx, zone->group()->ownerContext()); !iter.done(); ++iter) {
if (iter->compartment()->zone() == zone)
MarkActiveBaselineScripts(cx, iter);
for (const CooperatingContext& target : cx->runtime()->cooperatingContexts()) {
for (JitActivationIterator iter(cx, target); !iter.done(); ++iter) {
if (iter->compartment()->zone() == zone)
MarkActiveBaselineScripts(cx, iter);
}
}
}

View File

@ -48,13 +48,13 @@ GetPropIRGenerator::GetPropIRGenerator(JSContext* cx, HandleScript script, jsbyt
CacheKind cacheKind, ICState::Mode mode,
bool* isTemporarilyUnoptimizable, HandleValue val,
HandleValue idVal, HandleValue receiver,
CanAttachGetter canAttachGetter)
GetPropertyResultFlags resultFlags)
: IRGenerator(cx, script, pc, cacheKind, mode),
val_(val),
idVal_(idVal),
receiver_(receiver),
isTemporarilyUnoptimizable_(isTemporarilyUnoptimizable),
canAttachGetter_(canAttachGetter),
resultFlags_(resultFlags),
preliminaryObjectAction_(PreliminaryObjectAction::None)
{}
@ -247,11 +247,9 @@ GetPropIRGenerator::tryAttachStub()
bool
GetPropIRGenerator::tryAttachIdempotentStub()
{
// For idempotent ICs, only attach stubs for plain data properties.
// This ensures (1) the lookup has no side-effects and (2) Ion has complete
// static type information and we don't have to monitor the result. Because
// of (2), we don't support for instance missing properties or array
// lengths, as TI does not account for these cases.
// For idempotent ICs, only attach stubs which we can be sure have no side
// effects and produce a result which the MIR in the calling code is able
// to handle, since we do not have a pc to explicitly monitor the result.
MOZ_ASSERT(idempotent());
@ -263,6 +261,10 @@ GetPropIRGenerator::tryAttachIdempotentStub()
if (tryAttachNative(obj, objId, id))
return true;
// Object lengths are supported only if int32 results are allowed.
if ((resultFlags_ & GetPropertyResultFlags::AllowInt32) && tryAttachObjectLength(obj, objId, id))
return true;
// Also support native data properties on DOMProxy prototypes.
if (GetProxyStubType(cx_, obj, id) == ProxyStubType::DOMUnshadowed)
return tryAttachDOMProxyUnshadowed(obj, objId, id);
@ -272,22 +274,23 @@ GetPropIRGenerator::tryAttachIdempotentStub()
static bool
IsCacheableNoProperty(JSContext* cx, JSObject* obj, JSObject* holder, Shape* shape, jsid id,
jsbytecode* pc)
jsbytecode* pc, GetPropertyResultFlags resultFlags)
{
if (shape)
return false;
MOZ_ASSERT(!holder);
if (!pc) {
// This is an idempotent IC, don't attach a missing-property stub.
// See tryAttachStub.
// Idempotent ICs may only attach missing-property stubs if undefined
// results are explicitly allowed, since no monitoring is done of the
// cache result.
if (!pc && !(resultFlags & GetPropertyResultFlags::AllowUndefined))
return false;
}
// If we're doing a name lookup, we have to throw a ReferenceError. If
// extra warnings are enabled, we may have to report a warning.
if (*pc == JSOP_GETBOUNDNAME || cx->compartment()->behaviors().extraWarnings(cx))
// Note that Ion does not generate idempotent caches for JSOP_GETBOUNDNAME.
if ((pc && *pc == JSOP_GETBOUNDNAME) || cx->compartment()->behaviors().extraWarnings(cx))
return false;
return CheckHasNoSuchProperty(cx, obj, id);
@ -302,7 +305,7 @@ enum NativeGetPropCacheability {
static NativeGetPropCacheability
CanAttachNativeGetProp(JSContext* cx, HandleObject obj, HandleId id,
MutableHandleNativeObject holder, MutableHandleShape shape,
jsbytecode* pc, CanAttachGetter canAttachGetter,
jsbytecode* pc, GetPropertyResultFlags resultFlags,
bool* isTemporarilyUnoptimizable)
{
MOZ_ASSERT(JSID_IS_STRING(id) || JSID_IS_SYMBOL(id));
@ -327,22 +330,17 @@ CanAttachNativeGetProp(JSContext* cx, HandleObject obj, HandleId id,
if (IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, prop))
return CanAttachReadSlot;
// Idempotent ICs only support plain data properties, see
// tryAttachIdempotentStub.
if (!pc)
return CanAttachNone;
if (IsCacheableNoProperty(cx, obj, holder, shape, id, pc))
if (IsCacheableNoProperty(cx, obj, holder, shape, id, pc, resultFlags))
return CanAttachReadSlot;
if (canAttachGetter == CanAttachGetter::No)
return CanAttachNone;
// Idempotent ICs cannot call getters, see tryAttachIdempotentStub.
if (pc && (resultFlags & GetPropertyResultFlags::Monitored)) {
if (IsCacheableGetPropCallScripted(obj, holder, shape, isTemporarilyUnoptimizable))
return CanAttachCallGetter;
if (IsCacheableGetPropCallScripted(obj, holder, shape, isTemporarilyUnoptimizable))
return CanAttachCallGetter;
if (IsCacheableGetPropCallNative(obj, holder, shape))
return CanAttachCallGetter;
if (IsCacheableGetPropCallNative(obj, holder, shape))
return CanAttachCallGetter;
}
return CanAttachNone;
}
@ -582,10 +580,8 @@ GetPropIRGenerator::tryAttachNative(HandleObject obj, ObjOperandId objId, Handle
RootedNativeObject holder(cx_);
NativeGetPropCacheability type = CanAttachNativeGetProp(cx_, obj, id, &holder, &shape, pc_,
canAttachGetter_,
resultFlags_,
isTemporarilyUnoptimizable_);
MOZ_ASSERT_IF(idempotent(),
type == CanAttachNone || (type == CanAttachReadSlot && holder));
switch (type) {
case CanAttachNone:
return false;
@ -613,6 +609,7 @@ GetPropIRGenerator::tryAttachNative(HandleObject obj, ObjOperandId objId, Handle
return true;
case CanAttachCallGetter: {
// |super.prop| accesses use a |this| value that differs from lookup object
MOZ_ASSERT(!idempotent());
ObjOperandId receiverId = isSuper() ? writer.guardIsObject(getSuperReceiverValueId())
: objId;
maybeEmitIdGuard(id);
@ -651,7 +648,7 @@ GetPropIRGenerator::tryAttachWindowProxy(HandleObject obj, ObjOperandId objId, H
RootedShape shape(cx_);
RootedNativeObject holder(cx_);
NativeGetPropCacheability type = CanAttachNativeGetProp(cx_, windowObj, id, &holder, &shape, pc_,
canAttachGetter_,
resultFlags_,
isTemporarilyUnoptimizable_);
switch (type) {
case CanAttachNone:
@ -738,8 +735,8 @@ GetPropIRGenerator::tryAttachCrossCompartmentWrapper(HandleObject obj, ObjOperan
RootedShape shape(cx_);
RootedNativeObject holder(cx_);
NativeGetPropCacheability canCache =
CanAttachNativeGetProp(cx_, unwrapped, id, &holder, &shape, pc_, canAttachGetter_,
isTemporarilyUnoptimizable_);
CanAttachNativeGetProp(cx_, unwrapped, id, &holder, &shape, pc_,
resultFlags_, isTemporarilyUnoptimizable_);
if (canCache != CanAttachReadSlot)
return false;
@ -963,7 +960,7 @@ GetPropIRGenerator::tryAttachDOMProxyExpando(HandleObject obj, ObjOperandId objI
RootedShape propShape(cx_);
NativeGetPropCacheability canCache =
CanAttachNativeGetProp(cx_, expandoObj, id, &holder, &propShape, pc_,
canAttachGetter_, isTemporarilyUnoptimizable_);
resultFlags_, isTemporarilyUnoptimizable_);
if (canCache != CanAttachReadSlot && canCache != CanAttachCallGetter)
return false;
if (!holder)
@ -1054,10 +1051,8 @@ GetPropIRGenerator::tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId o
RootedNativeObject holder(cx_);
RootedShape shape(cx_);
NativeGetPropCacheability canCache = CanAttachNativeGetProp(cx_, checkObj, id, &holder, &shape,
pc_, canAttachGetter_,
pc_, resultFlags_,
isTemporarilyUnoptimizable_);
MOZ_ASSERT_IF(idempotent(),
canCache == CanAttachNone || (canCache == CanAttachReadSlot && holder));
if (canCache == CanAttachNone)
return false;
@ -1394,7 +1389,7 @@ GetPropIRGenerator::tryAttachPrimitive(ValOperandId valId, HandleId id)
RootedShape shape(cx_);
RootedNativeObject holder(cx_);
NativeGetPropCacheability type = CanAttachNativeGetProp(cx_, proto, id, &holder, &shape, pc_,
canAttachGetter_,
resultFlags_,
isTemporarilyUnoptimizable_);
if (type != CanAttachReadSlot)
return false;

View File

@ -1147,7 +1147,38 @@ class MOZ_RAII IRGenerator
CacheKind cacheKind() const { return cacheKind_; }
};
enum class CanAttachGetter { Yes, No };
// Flags used to describe what values a GetProperty cache may produce.
enum class GetPropertyResultFlags {
None = 0,
// Values produced by this cache will go through a type barrier,
// so the cache may produce any type of value that is compatible with its
// result operand.
Monitored = 1 << 0,
// Whether particular primitives may be produced by this cache.
AllowUndefined = 1 << 1,
AllowInt32 = 1 << 2,
AllowDouble = 1 << 3,
All = Monitored | AllowUndefined | AllowInt32 | AllowDouble
};
static inline bool operator&(GetPropertyResultFlags a, GetPropertyResultFlags b)
{
return static_cast<int>(a) & static_cast<int>(b);
}
static inline GetPropertyResultFlags operator|(GetPropertyResultFlags a, GetPropertyResultFlags b)
{
return static_cast<GetPropertyResultFlags>(static_cast<int>(a) | static_cast<int>(b));
}
static inline GetPropertyResultFlags& operator|=(GetPropertyResultFlags& lhs, GetPropertyResultFlags b)
{
lhs = lhs | b;
return lhs;
}
// GetPropIRGenerator generates CacheIR for a GetProp IC.
class MOZ_RAII GetPropIRGenerator : public IRGenerator
@ -1156,7 +1187,7 @@ class MOZ_RAII GetPropIRGenerator : public IRGenerator
HandleValue idVal_;
HandleValue receiver_;
bool* isTemporarilyUnoptimizable_;
CanAttachGetter canAttachGetter_;
GetPropertyResultFlags resultFlags_;
enum class PreliminaryObjectAction { None, Unlink, NotePreliminary };
PreliminaryObjectAction preliminaryObjectAction_;
@ -1233,7 +1264,8 @@ class MOZ_RAII GetPropIRGenerator : public IRGenerator
public:
GetPropIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, CacheKind cacheKind,
ICState::Mode mode, bool* isTemporarilyUnoptimizable, HandleValue val,
HandleValue idVal, HandleValue receiver, CanAttachGetter canAttachGetter);
HandleValue idVal, HandleValue receiver,
GetPropertyResultFlags resultFlags);
bool tryAttachStub();
bool tryAttachIdempotentStub();

View File

@ -10285,7 +10285,7 @@ void
CodeGenerator::addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs,
TypedOrValueRegister value, const ConstantOrRegister& id,
TypedOrValueRegister output, Register maybeTemp,
bool monitoredResult, bool allowDoubleResult,
GetPropertyResultFlags resultFlags,
jsbytecode* profilerLeavePc)
{
CacheKind kind = CacheKind::GetElem;
@ -10295,8 +10295,7 @@ CodeGenerator::addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs,
if (idString->isAtom() && !idString->asAtom().isIndex(&dummy))
kind = CacheKind::GetProp;
}
IonGetPropertyIC cache(kind, liveRegs, value, id, output, maybeTemp, monitoredResult,
allowDoubleResult);
IonGetPropertyIC cache(kind, liveRegs, value, id, output, maybeTemp, resultFlags);
addIC(ins, allocateIC(cache));
}
@ -10333,6 +10332,35 @@ CodeGenerator::toConstantOrRegister(LInstruction* lir, size_t n, MIRType type)
return TypedOrValueRegister(type, ToAnyRegister(value));
}
static GetPropertyResultFlags
IonGetPropertyICFlags(const MGetPropertyCache* mir)
{
GetPropertyResultFlags flags = GetPropertyResultFlags::None;
if (mir->monitoredResult())
flags |= GetPropertyResultFlags::Monitored;
if (mir->type() == MIRType::Value) {
if (TemporaryTypeSet* types = mir->resultTypeSet()) {
if (types->hasType(TypeSet::UndefinedType()))
flags |= GetPropertyResultFlags::AllowUndefined;
if (types->hasType(TypeSet::Int32Type()))
flags |= GetPropertyResultFlags::AllowInt32;
if (types->hasType(TypeSet::DoubleType()))
flags |= GetPropertyResultFlags::AllowDouble;
} else {
flags |= GetPropertyResultFlags::AllowUndefined
| GetPropertyResultFlags::AllowInt32
| GetPropertyResultFlags::AllowDouble;
}
} else if (mir->type() == MIRType::Int32) {
flags |= GetPropertyResultFlags::AllowInt32;
} else if (mir->type() == MIRType::Double) {
flags |= GetPropertyResultFlags::AllowInt32 | GetPropertyResultFlags::AllowDouble;
}
return flags;
}
void
CodeGenerator::visitGetPropertyCacheV(LGetPropertyCacheV* ins)
{
@ -10340,12 +10368,11 @@ CodeGenerator::visitGetPropertyCacheV(LGetPropertyCacheV* ins)
TypedOrValueRegister value =
toConstantOrRegister(ins, LGetPropertyCacheV::Value, ins->mir()->value()->type()).reg();
ConstantOrRegister id = toConstantOrRegister(ins, LGetPropertyCacheV::Id, ins->mir()->idval()->type());
bool monitoredResult = ins->mir()->monitoredResult();
TypedOrValueRegister output = TypedOrValueRegister(GetValueOutput(ins));
Register maybeTemp = ins->temp()->isBogusTemp() ? InvalidReg : ToRegister(ins->temp());
addGetPropertyCache(ins, liveRegs, value, id, output, maybeTemp, monitoredResult,
ins->mir()->allowDoubleResult(), ins->mir()->profilerLeavePc());
addGetPropertyCache(ins, liveRegs, value, id, output, maybeTemp,
IonGetPropertyICFlags(ins->mir()), ins->mir()->profilerLeavePc());
}
void
@ -10355,12 +10382,11 @@ CodeGenerator::visitGetPropertyCacheT(LGetPropertyCacheT* ins)
TypedOrValueRegister value =
toConstantOrRegister(ins, LGetPropertyCacheV::Value, ins->mir()->value()->type()).reg();
ConstantOrRegister id = toConstantOrRegister(ins, LGetPropertyCacheT::Id, ins->mir()->idval()->type());
bool monitoredResult = ins->mir()->monitoredResult();
TypedOrValueRegister output(ins->mir()->type(), ToAnyRegister(ins->getDef(0)));
Register maybeTemp = ins->temp()->isBogusTemp() ? InvalidReg : ToRegister(ins->temp());
addGetPropertyCache(ins, liveRegs, value, id, output, maybeTemp, monitoredResult,
ins->mir()->allowDoubleResult(), ins->mir()->profilerLeavePc());
addGetPropertyCache(ins, liveRegs, value, id, output, maybeTemp,
IonGetPropertyICFlags(ins->mir()), ins->mir()->profilerLeavePc());
}
void

View File

@ -7,6 +7,7 @@
#ifndef jit_CodeGenerator_h
#define jit_CodeGenerator_h
#include "jit/CacheIR.h"
#include "jit/IonCaches.h"
#if defined(JS_ION_PERF)
# include "jit/PerfSpewer.h"
@ -468,8 +469,8 @@ class CodeGenerator final : public CodeGeneratorSpecific
private:
void addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs,
TypedOrValueRegister value, const ConstantOrRegister& id,
TypedOrValueRegister output, Register maybeTemp, bool monitoredResult,
bool allowDoubleResult, jsbytecode* profilerLeavePc);
TypedOrValueRegister output, Register maybeTemp,
GetPropertyResultFlags flags, jsbytecode* profilerLeavePc);
void addSetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs, Register objReg,
Register temp, FloatRegister tempDouble,
FloatRegister tempF32, const ConstantOrRegister& id,

View File

@ -37,7 +37,7 @@ CompileRuntime::jitRuntime()
return runtime()->jitRuntime();
}
GeckoProfiler&
GeckoProfilerRuntime&
CompileRuntime::geckoProfiler()
{
return runtime()->geckoProfiler();

View File

@ -34,7 +34,7 @@ class CompileRuntime
const JitRuntime* jitRuntime();
// Compilation does not occur off thread when the Gecko Profiler is enabled.
GeckoProfiler& geckoProfiler();
GeckoProfilerRuntime& geckoProfiler();
bool jitSupportsFloatingPoint();
bool hadOutOfMemory();

View File

@ -3125,10 +3125,12 @@ jit::InvalidateAll(FreeOp* fop, Zone* zone)
if (zone->isAtomsZone())
return;
JSContext* cx = TlsContext.get();
for (JitActivationIterator iter(cx, zone->group()->ownerContext()); !iter.done(); ++iter) {
if (iter->compartment()->zone() == zone) {
JitSpew(JitSpew_IonInvalidate, "Invalidating all frames for GC");
InvalidateActivation(fop, iter, true);
for (const CooperatingContext& target : cx->runtime()->cooperatingContexts()) {
for (JitActivationIterator iter(cx, target); !iter.done(); ++iter) {
if (iter->compartment()->zone() == zone) {
JitSpew(JitSpew_IonInvalidate, "Invalidating all frames for GC");
InvalidateActivation(fop, iter, true);
}
}
}
}
@ -3179,8 +3181,10 @@ jit::Invalidate(TypeZone& types, FreeOp* fop,
JSRuntime::AutoProhibitActiveContextChange apacc(fop->runtime());
JSContext* cx = TlsContext.get();
for (JitActivationIterator iter(cx, types.zone()->group()->ownerContext()); !iter.done(); ++iter)
InvalidateActivation(fop, iter, false);
for (const CooperatingContext& target : cx->runtime()->cooperatingContexts()) {
for (JitActivationIterator iter(cx, target); !iter.done(); ++iter)
InvalidateActivation(fop, iter, false);
}
// Drop the references added above. If a script was never active, its
// IonScript will be immediately destroyed. Otherwise, it will be held live

View File

@ -7,6 +7,7 @@
#include "jit/IonBuilder.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/SizePrintfMacros.h"
#include "builtin/Eval.h"
@ -836,10 +837,12 @@ IonBuilder::build()
insertRecompileCheck();
MOZ_TRY(traverseBytecode());
auto clearLastPriorResumePoint = mozilla::MakeScopeExit([&] {
// Discard unreferenced & pre-allocated resume points.
replaceMaybeFallbackFunctionGetter(nullptr);
});
// Discard unreferenced & pre-allocated resume points.
replaceMaybeFallbackFunctionGetter(nullptr);
MOZ_TRY(traverseBytecode());
if (script_->hasBaselineScript() &&
inlinedBytecodeLength_ > script_->baselineScript()->inlinedBytecodeLength())
@ -998,10 +1001,13 @@ IonBuilder::buildInline(IonBuilder* callerBuilder, MResumePoint* callerResumePoi
// initialized.
MOZ_TRY(initEnvironmentChain(callInfo.fun()));
auto clearLastPriorResumePoint = mozilla::MakeScopeExit([&] {
// Discard unreferenced & pre-allocated resume points.
replaceMaybeFallbackFunctionGetter(nullptr);
});
MOZ_TRY(traverseBytecode());
// Discard unreferenced & pre-allocated resume points.
replaceMaybeFallbackFunctionGetter(nullptr);
MOZ_ASSERT(iterators_.empty(), "Iterators should be added to outer builder");
@ -7275,6 +7281,17 @@ IonBuilder::ensureDefiniteTypeSet(MDefinition* def, TemporaryTypeSet* types)
return filter;
}
static size_t
NumFixedSlots(JSObject* object)
{
// Note: we can't use object->numFixedSlots() here, as this will read the
// shape and can race with the active thread if we are building off thread.
// The allocation kind and object class (which goes through the type) can
// be read freely, however.
gc::AllocKind kind = object->asTenured().getAllocKind();
return gc::GetGCKindSlots(kind, object->getClass());
}
static bool
IsUninitializedGlobalLexicalSlot(JSObject* obj, PropertyName* name)
{
@ -7296,48 +7313,32 @@ IonBuilder::getStaticName(bool* emitted, JSObject* staticObject, PropertyName* n
bool isGlobalLexical = staticObject->is<LexicalEnvironmentObject>() &&
staticObject->as<LexicalEnvironmentObject>().isGlobal();
MOZ_ASSERT(isGlobalLexical ||
staticObject->is<GlobalObject>() ||
staticObject->is<CallObject>() ||
staticObject->is<ModuleEnvironmentObject>());
MOZ_ASSERT(staticObject->isSingleton());
// Always emit the lexical check. This could be optimized, but is
// currently not for simplicity's sake.
if (lexicalCheck)
return Ok();
// Only optimize accesses on native objects.
if (!staticObject->isNative())
return Ok();
// Only optimize accesses on own data properties.
Shape* propertyShape = staticObject->as<NativeObject>().lastProperty()->searchLinear(NameToId(name));
if (!propertyShape || !propertyShape->isDataDescriptor() || !propertyShape->hasSlot())
return Ok();
uint32_t slot = propertyShape->slot();
TypeSet::ObjectKey* staticKey = TypeSet::ObjectKey::get(staticObject);
if (analysisContext)
staticKey->ensureTrackedProperty(analysisContext, NameToId(name));
// Make sure the property is a normal data property. This is not done for
// call objects, as they are not tracked by TI and their data properties
// cannot be dynamically reconfigured.
Maybe<HeapTypeSetKey> property;
if (!staticObject->is<CallObject>()) {
if (staticKey->unknownProperties())
return Ok();
if (staticKey->unknownProperties())
return Ok();
property.emplace(staticKey->property(id));
if (property.ref().nonData(constraints()) ||
!property.ref().maybeTypes() ||
!property.ref().maybeTypes()->definiteProperty())
{
// We can't be sure the slot will match at runtime, so include a
// shape guard on the object.
MInstruction* obj = MConstant::NewConstraintlessObject(alloc(), staticObject);
current->add(obj);
addShapeGuard(obj, staticObject->as<NativeObject>().lastProperty(), Bailout_ShapeGuard);
} else {
MOZ_ASSERT(slot == property.ref().maybeTypes()->definiteSlot());
}
HeapTypeSetKey property = staticKey->property(id);
if (!property.maybeTypes() ||
!property.maybeTypes()->definiteProperty() ||
property.nonData(constraints()))
{
// The property has been reconfigured as non-configurable, non-enumerable
// or non-writable.
return Ok();
}
// Don't optimize global lexical bindings if they aren't initialized at
@ -7363,37 +7364,13 @@ IonBuilder::getStaticName(bool* emitted, JSObject* staticObject, PropertyName* n
// Try to inline properties that have never been overwritten.
Value constantValue;
if (property.isSome() && property.ref().constant(constraints(), &constantValue)) {
if (property.constant(constraints(), &constantValue)) {
pushConstant(constantValue);
return Ok();
}
}
MOZ_TRY(loadStaticSlot(staticObject, barrier, types, slot));
// If the static object has a function object stored in this property,
// test that the result is that specific function. This is yet another
// technique for trying to force a property load to be a specific value,
// and is included because other mechanisms (property types and observed
// types) do not always work, especially in polymorphic framework code.
// We restrict this optimization to function properties, as they are less
// likely to change over time and are more likely to require precise
// information for inlining decisions.
if (!outermostBuilder()->script()->hadFrequentBailouts()) {
Value v = staticObject->as<NativeObject>().getSlot(slot);
if (v.isObject() &&
v.toObject().is<JSFunction>() &&
v.toObject().as<JSFunction>().isInterpreted())
{
JSObject* result = checkNurseryObject(&v.toObject().as<JSFunction>());
MDefinition* load = current->pop();
MInstruction* expected = MConstant::NewConstraintlessObject(alloc(), result);
expected->setResultTypeSet(MakeSingletonTypeSet(constraints(), result));
current->add(expected);
current->add(MGuardObjectIdentity::New(alloc(), load, expected, false, Bailout_LoadStaticObject));
current->push(expected);
}
}
MOZ_TRY(loadStaticSlot(staticObject, barrier, types, property.maybeTypes()->definiteSlot()));
return Ok();
}
@ -7421,7 +7398,7 @@ IonBuilder::loadStaticSlot(JSObject* staticObject, BarrierKind barrier, Temporar
if (barrier != BarrierKind::NoBarrier)
rvalType = MIRType::Value;
return loadSlot(obj, slot, staticObject->as<NativeObject>().numFixedSlots(), rvalType, barrier, types);
return loadSlot(obj, slot, NumFixedSlots(staticObject), rvalType, barrier, types);
}
// Whether a write of the given value may need a post-write barrier for GC purposes.
@ -7486,8 +7463,7 @@ IonBuilder::setStaticName(JSObject* staticObject, PropertyName* name)
slotType = knownType;
bool needsPreBarrier = property.needsBarrier(constraints());
return storeSlot(obj, property.maybeTypes()->definiteSlot(),
staticObject->as<NativeObject>().numFixedSlots(),
return storeSlot(obj, property.maybeTypes()->definiteSlot(), NumFixedSlots(staticObject),
value, needsPreBarrier, slotType);
}
@ -10428,12 +10404,6 @@ IonBuilder::jsop_getprop(PropertyName* name)
if (emitted)
return Ok();
// Try to optimize for loads from a specific object.
trackOptimizationAttempt(TrackedStrategy::GetProp_Static);
MOZ_TRY(getPropTryStaticAccess(&emitted, obj, name, barrier, types));
if (emitted)
return Ok();
// Try to emit a monomorphic/polymorphic access based on baseline caches.
trackOptimizationAttempt(TrackedStrategy::GetProp_InlineAccess);
MOZ_TRY(getPropTryInlineAccess(&emitted, obj, name, barrier, types));
@ -11233,17 +11203,6 @@ PropertyShapesHaveSameSlot(const BaselineInspector::ReceiverVector& receivers, j
return firstShape;
}
AbortReasonOr<Ok>
IonBuilder::getPropTryStaticAccess(bool* emitted, MDefinition* obj, PropertyName* name,
BarrierKind barrier, TemporaryTypeSet* types)
{
if (!obj->isConstant() || obj->type() != MIRType::Object)
return Ok();
obj->setImplicitlyUsedUnchecked();
return getStaticName(emitted, &obj->toConstant()->toObject(), name);
}
AbortReasonOr<Ok>
IonBuilder::getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName* name,
BarrierKind barrier, TemporaryTypeSet* types)
@ -12677,49 +12636,11 @@ IonBuilder::walkEnvironmentChain(unsigned hops)
return env;
}
static bool
SearchEnvironmentChainForCallObject(JSObject* environment, JSScript* script, JSObject** pcall)
{
while (environment && !environment->is<GlobalObject>()) {
if (environment->is<CallObject>() &&
environment->as<CallObject>().callee().nonLazyScript() == script)
{
*pcall = environment;
return true;
}
environment = environment->enclosingEnvironment();
}
return false;
}
bool
IonBuilder::hasStaticEnvironmentObject(EnvironmentCoordinate ec, JSObject** pcall)
{
JSScript* outerScript = EnvironmentCoordinateFunctionScript(script(), pc);
if (!outerScript)
return false;
// JSOP_SETALIASEDVAR only emits a cache when the outer script is a run
// once script. To avoid problems with the generic jsop_setprop() paths,
// only use static environment objects when a baseline cache exists.
if (*pc == JSOP_SETALIASEDVAR && !outerScript->treatAsRunOnce())
return false;
// If the callee is a specific JSFunction then there is a specific
// environment object on its chain we can use.
if (inlineCallInfo_) {
MDefinition* calleeDef = inlineCallInfo_->fun();
if (calleeDef->isConstant()) {
JSFunction* callee = &calleeDef->toConstant()->toObject().template as<JSFunction>();
JSObject* environment = callee->environment();
if (SearchEnvironmentChainForCallObject(environment, outerScript, pcall))
return true;
}
}
// Otherwise, if the outer script will only run once then we can go looking
// for its call object.
if (!outerScript->treatAsRunOnce())
if (!outerScript || !outerScript->treatAsRunOnce())
return false;
TypeSet::ObjectKey* funKey =
@ -12740,8 +12661,16 @@ IonBuilder::hasStaticEnvironmentObject(EnvironmentCoordinate ec, JSObject** pcal
envDef->setImplicitlyUsedUnchecked();
JSObject* environment = script()->functionNonDelazifying()->environment();
if (SearchEnvironmentChainForCallObject(environment, outerScript, pcall))
return true;
while (environment && !environment->is<GlobalObject>()) {
if (environment->is<CallObject>() &&
environment->as<CallObject>().callee().nonLazyScript() == outerScript)
{
MOZ_ASSERT(environment->isSingleton());
*pcall = environment;
return true;
}
environment = environment->enclosingEnvironment();
}
// Look for the call object on the current frame, if we are compiling the
// outer script itself. Don't do this if we are at entry to the outer
@ -12750,8 +12679,14 @@ IonBuilder::hasStaticEnvironmentObject(EnvironmentCoordinate ec, JSObject** pcal
if (script() == outerScript && baselineFrame_ && info().osrPc()) {
JSObject* singletonScope = baselineFrame_->singletonEnvChain;
if (SearchEnvironmentChainForCallObject(singletonScope, outerScript, pcall))
if (singletonScope &&
singletonScope->is<CallObject>() &&
singletonScope->as<CallObject>().callee().nonLazyScript() == outerScript)
{
MOZ_ASSERT(singletonScope->isSingleton());
*pcall = singletonScope;
return true;
}
}
return true;

View File

@ -246,8 +246,6 @@ class IonBuilder
BarrierKind barrier, TemporaryTypeSet* types);
AbortReasonOr<Ok> getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName* name,
TemporaryTypeSet* types, bool innerized = false);
AbortReasonOr<Ok> getPropTryStaticAccess(bool* emitted, MDefinition* obj, PropertyName* name,
BarrierKind barrier, TemporaryTypeSet* types);
AbortReasonOr<Ok> getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName* name,
BarrierKind barrier, TemporaryTypeSet* types);
AbortReasonOr<Ok> getPropTryTypedObject(bool* emitted, MDefinition* obj, PropertyName* name);

View File

@ -135,12 +135,11 @@ IonGetPropertyIC::update(JSContext* cx, HandleScript outerScript, IonGetProperty
// needs a type barrier. Unfortunately, PropertyReadNeedsTypeBarrier
// does not account for getters, so we should only attach a getter
// stub if we inserted a type barrier.
CanAttachGetter canAttachGetter =
ic->monitoredResult() ? CanAttachGetter::Yes : CanAttachGetter::No;
jsbytecode* pc = ic->idempotent() ? nullptr : ic->pc();
bool isTemporarilyUnoptimizable = false;
GetPropIRGenerator gen(cx, outerScript, pc, ic->kind(), ic->state().mode(),
&isTemporarilyUnoptimizable, val, idVal, val, canAttachGetter);
&isTemporarilyUnoptimizable, val, idVal, val,
ic->resultFlags());
if (ic->idempotent() ? gen.tryAttachIdempotentStub() : gen.tryAttachStub())
ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);

View File

@ -178,6 +178,7 @@ class IonIC
class IonGetPropertyIC : public IonIC
{
private:
LiveRegisterSet liveRegs_;
TypedOrValueRegister value_;
@ -185,30 +186,29 @@ class IonGetPropertyIC : public IonIC
TypedOrValueRegister output_;
Register maybeTemp_; // Might be InvalidReg.
bool monitoredResult_ : 1;
bool allowDoubleResult_ : 1;
GetPropertyResultFlags resultFlags_;
public:
IonGetPropertyIC(CacheKind kind, LiveRegisterSet liveRegs, TypedOrValueRegister value,
const ConstantOrRegister& id, TypedOrValueRegister output, Register maybeTemp,
bool monitoredResult, bool allowDoubleResult)
GetPropertyResultFlags resultFlags)
: IonIC(kind),
liveRegs_(liveRegs),
value_(value),
id_(id),
output_(output),
maybeTemp_(maybeTemp),
monitoredResult_(monitoredResult),
allowDoubleResult_(allowDoubleResult)
resultFlags_(resultFlags)
{ }
bool monitoredResult() const { return monitoredResult_; }
TypedOrValueRegister value() const { return value_; }
ConstantOrRegister id() const { return id_; }
TypedOrValueRegister output() const { return output_; }
Register maybeTemp() const { return maybeTemp_; }
LiveRegisterSet liveRegs() const { return liveRegs_; }
bool allowDoubleResult() const { return allowDoubleResult_; }
GetPropertyResultFlags resultFlags() const { return resultFlags_; }
bool monitoredResult() const { return resultFlags_ & GetPropertyResultFlags::Monitored; }
bool allowDoubleResult() const { return resultFlags_ & GetPropertyResultFlags::AllowDouble; }
static MOZ_MUST_USE bool update(JSContext* cx, HandleScript outerScript, IonGetPropertyIC* ic,
HandleValue val, HandleValue idVal, MutableHandleValue res);

View File

@ -9,7 +9,7 @@
namespace js {
class GeckoProfiler;
class GeckoProfilerRuntime;
namespace jit {
@ -20,7 +20,7 @@ typedef GeckoProfilerInstrumentation<MacroAssembler, Register> BaseInstrumentati
class IonInstrumentation : public BaseInstrumentation
{
public:
IonInstrumentation(GeckoProfiler* profiler, jsbytecode** pc)
IonInstrumentation(GeckoProfilerRuntime* profiler, jsbytecode** pc)
: BaseInstrumentation(profiler)
{
MOZ_ASSERT(pc != nullptr);

View File

@ -142,9 +142,6 @@ enum BailoutKind
// Can also signal division by 0 (returns inf, a double).
Bailout_DoubleOutput,
// Load of a value from a static object retrieved an unexpected value.
Bailout_LoadStaticObject,
// END Invalid assumptions bailouts
@ -236,8 +233,6 @@ BailoutKindString(BailoutKind kind)
return "Bailout_NonStringInputInvalidate";
case Bailout_DoubleOutput:
return "Bailout_DoubleOutput";
case Bailout_LoadStaticObject:
return "Bailout_LoadStaticObject";
// Other bailouts.
case Bailout_ArgumentCheck:

View File

@ -3900,7 +3900,7 @@ LIRGenerator::visitGuardObjectIdentity(MGuardObjectIdentity* ins)
{
LGuardObjectIdentity* guard = new(alloc()) LGuardObjectIdentity(useRegister(ins->object()),
useRegister(ins->expected()));
assignSnapshot(guard, ins->bailoutKind());
assignSnapshot(guard, Bailout_ObjectIdentityOrTypeGuard);
add(guard, ins);
redefine(ins, ins->object());
}

View File

@ -6197,18 +6197,9 @@ jit::PropertyReadNeedsTypeBarrier(JSContext* propertycx,
TypeSet::TypeList types;
if (!property.maybeTypes()->enumerateTypes(&types))
break;
// If there is a single possible type for the property,
// optimistically add it to the observed set. Don't do this
// for the special uninitialized lexical type, which will
// never actually be observed here and will cause problems
// downstream during compilation.
if (types.length() == 1 &&
(!types[0].isPrimitive() ||
types[0].primitive() != JSVAL_TYPE_MAGIC))
{
if (types.length() == 1) {
// Note: the return value here is ignored.
observed->addType(types[0], GetJitContext()->temp->lifoAlloc());
break;
}
break;
}

View File

@ -11490,13 +11490,10 @@ class MGuardObjectIdentity
public SingleObjectPolicy::Data
{
bool bailOnEquality_;
BailoutKind bailoutKind_;
MGuardObjectIdentity(MDefinition* obj, MDefinition* expected, bool bailOnEquality,
BailoutKind bailoutKind = Bailout_ObjectIdentityOrTypeGuard)
MGuardObjectIdentity(MDefinition* obj, MDefinition* expected, bool bailOnEquality)
: MBinaryInstruction(obj, expected),
bailOnEquality_(bailOnEquality),
bailoutKind_(bailoutKind)
bailOnEquality_(bailOnEquality)
{
setGuard();
setMovable();
@ -11511,16 +11508,11 @@ class MGuardObjectIdentity
bool bailOnEquality() const {
return bailOnEquality_;
}
BailoutKind bailoutKind() const {
return bailoutKind_;
}
bool congruentTo(const MDefinition* ins) const override {
if (!ins->isGuardObjectIdentity())
return false;
if (bailOnEquality() != ins->toGuardObjectIdentity()->bailOnEquality())
return false;
if (bailoutKind() != ins->toGuardObjectIdentity()->bailoutKind())
return false;
return congruentIfOperandsEqual(ins);
}
AliasSet getAliasSet() const override {

View File

@ -2069,7 +2069,8 @@ DoGetPropFallback(JSContext* cx, BaselineFrame* frame, ICGetProp_Fallback* stub_
if (stub->state().canAttachStub()) {
RootedValue idVal(cx, StringValue(name));
GetPropIRGenerator gen(cx, script, pc, CacheKind::GetProp, stub->state().mode(),
&isTemporarilyUnoptimizable, val, idVal, val, CanAttachGetter::Yes);
&isTemporarilyUnoptimizable, val, idVal, val,
GetPropertyResultFlags::All);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Monitored,
@ -2140,7 +2141,7 @@ DoGetPropSuperFallback(JSContext* cx, BaselineFrame* frame, ICGetProp_Fallback*
RootedValue idVal(cx, StringValue(name));
GetPropIRGenerator gen(cx, script, pc, CacheKind::GetPropSuper, stub->state().mode(),
&isTemporarilyUnoptimizable, val, idVal, receiver,
CanAttachGetter::Yes);
GetPropertyResultFlags::All);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Monitored,

View File

@ -33,7 +33,7 @@ static const FloatRegisterSet NonVolatileFloatRegs =
(1ULL << FloatRegisters::d15));
static void
GenerateReturn(MacroAssembler& masm, int returnCode, GeckoProfiler* prof)
GenerateReturn(MacroAssembler& masm, int returnCode)
{
// Restore non-volatile floating point registers.
masm.transferMultipleByRuns(NonVolatileFloatRegs, IsLoad, StackPointer, IA);
@ -377,7 +377,7 @@ JitRuntime::generateEnterJIT(JSContext* cx, EnterJitType type)
// JSReturnReg_Data, EDtrAddr(r5, EDtrOffImm(0)));
// Restore non-volatile registers and return.
GenerateReturn(masm, true, &cx->runtime()->geckoProfiler());
GenerateReturn(masm, true);
Linker linker(masm);
AutoFlushICache afc("EnterJIT");

View File

@ -1030,6 +1030,23 @@ JS_ResumeCooperativeContext(JSContext* cx);
extern JS_PUBLIC_API(JSContext*)
JS_NewCooperativeContext(JSContext* siblingContext);
namespace JS {
// Class to relinquish exclusive access to all zone groups in use by this
// thread. This allows other cooperative threads to enter the zone groups
// and modify their contents.
struct AutoRelinquishZoneGroups
{
explicit AutoRelinquishZoneGroups(JSContext* cx);
~AutoRelinquishZoneGroups();
private:
JSContext* cx;
mozilla::Vector<void*> enterList;
};
} // namespace JS
// Destroy a context allocated with JS_NewContext or JS_NewCooperativeContext.
// The context must be the current active context in the runtime, and after
// this call the runtime will have no active context.

View File

@ -1323,7 +1323,7 @@ js::array_join(JSContext* cx, unsigned argc, Value* vp)
if (!CheckRecursionLimit(cx))
return false;
AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.join");
AutoGeckoProfilerEntry pseudoFrame(cx, "Array.prototype.join");
CallArgs args = CallArgsFromVp(argc, vp);
// Step 1.
@ -1583,7 +1583,7 @@ DefineBoxedOrUnboxedFunctor3(ArrayReverseDenseKernel,
bool
js::array_reverse(JSContext* cx, unsigned argc, Value* vp)
{
AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.reverse");
AutoGeckoProfilerEntry pseudoFrame(cx, "Array.prototype.reverse");
CallArgs args = CallArgsFromVp(argc, vp);
// Step 1.
@ -2288,7 +2288,7 @@ js::NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v)
bool
js::array_push(JSContext* cx, unsigned argc, Value* vp)
{
AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.push");
AutoGeckoProfilerEntry pseudoFrame(cx, "Array.prototype.push");
CallArgs args = CallArgsFromVp(argc, vp);
// Step 1.
@ -2345,7 +2345,7 @@ js::array_push(JSContext* cx, unsigned argc, Value* vp)
bool
js::array_pop(JSContext* cx, unsigned argc, Value* vp)
{
AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.pop");
AutoGeckoProfilerEntry pseudoFrame(cx, "Array.prototype.pop");
CallArgs args = CallArgsFromVp(argc, vp);
// Step 1.
@ -2450,7 +2450,7 @@ DefineBoxedOrUnboxedFunctor3(ArrayShiftDenseKernel,
bool
js::array_shift(JSContext* cx, unsigned argc, Value* vp)
{
AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.shift");
AutoGeckoProfilerEntry pseudoFrame(cx, "Array.prototype.shift");
CallArgs args = CallArgsFromVp(argc, vp);
// Step 1.
@ -2526,7 +2526,7 @@ js::array_shift(JSContext* cx, unsigned argc, Value* vp)
bool
js::array_unshift(JSContext* cx, unsigned argc, Value* vp)
{
AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.unshift");
AutoGeckoProfilerEntry pseudoFrame(cx, "Array.prototype.unshift");
CallArgs args = CallArgsFromVp(argc, vp);
// Step 1.
@ -2769,7 +2769,7 @@ CopyArrayElements(JSContext* cx, HandleObject obj, uint64_t begin, uint64_t coun
static bool
array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueIsUsed)
{
AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.splice");
AutoGeckoProfilerEntry pseudoFrame(cx, "Array.prototype.splice");
CallArgs args = CallArgsFromVp(argc, vp);
/* Step 1. */
@ -3277,7 +3277,7 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint64_t begin, uint64_t end
bool
js::array_slice(JSContext* cx, unsigned argc, Value* vp)
{
AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.slice");
AutoGeckoProfilerEntry pseudoFrame(cx, "Array.prototype.slice");
CallArgs args = CallArgsFromVp(argc, vp);
/* Step 1. */

View File

@ -1590,6 +1590,7 @@ void
JSContext::trace(JSTracer* trc)
{
cycleDetectorVector().trace(trc);
geckoProfiler().trace(trc);
if (trc->isMarkingTracer() && compartment_)
compartment_->mark();

View File

@ -390,9 +390,6 @@ struct JSContext : public JS::RootingContext,
js::Activation* profilingActivation() const {
return profilingActivation_;
}
void* addressOfProfilingActivation() {
return (void*) &profilingActivation_;
}
static size_t offsetOfProfilingActivation() {
return offsetof(JSContext, profilingActivation_);
}
@ -603,6 +600,12 @@ struct JSContext : public JS::RootingContext,
suppressProfilerSampling = false;
}
private:
/* Gecko profiling metadata */
js::UnprotectedData<js::GeckoProfilerThread> geckoProfiler_;
public:
js::GeckoProfilerThread& geckoProfiler() { return geckoProfiler_.ref(); }
#if defined(XP_DARWIN)
js::wasm::MachExceptionHandler wasmMachExceptionHandler;
#endif

View File

@ -6216,7 +6216,7 @@ AutoTraceSession::AutoTraceSession(JSRuntime* rt, JS::HeapState heapState)
: lock(rt),
runtime(rt),
prevState(TlsContext.get()->heapState),
pseudoFrame(rt, HeapStateToLabel(heapState), ProfileEntry::Category::GC)
pseudoFrame(TlsContext.get(), HeapStateToLabel(heapState), ProfileEntry::Category::GC)
{
MOZ_ASSERT(prevState == JS::HeapState::Idle);
MOZ_ASSERT(heapState != JS::HeapState::Idle);

View File

@ -29,11 +29,6 @@ JS_PUBLIC_API(JS::UniqueChars) JS_smprintf(const char* fmt, ...)
return JS::UniqueChars(result.release());
}
JS_PUBLIC_API(void) JS_smprintf_free(char* mem)
{
mozilla::SmprintfFree<js::SystemAllocPolicy>(mem);
}
JS_PUBLIC_API(JS::UniqueChars) JS_sprintf_append(JS::UniqueChars&& last, const char* fmt, ...)
{
va_list ap;

View File

@ -20,8 +20,6 @@
extern JS_PUBLIC_API(JS::UniqueChars) JS_smprintf(const char* fmt, ...)
MOZ_FORMAT_PRINTF(1, 2);
extern JS_PUBLIC_API(void) JS_smprintf_free(char* mem);
extern JS_PUBLIC_API(JS::UniqueChars) JS_sprintf_append(JS::UniqueChars&& last,
const char* fmt, ...)
MOZ_FORMAT_PRINTF(2, 3);

Some files were not shown because too many files have changed in this diff Show More