зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge on a CLOSED TREE
--HG-- extra : rebase_source : 33d0709730d68206491b4facb0645c798ff943e3
This commit is contained in:
Коммит
bf215dbbd8
|
@ -56,10 +56,3 @@ path:.cron.yml
|
|||
|
||||
# for the wrench-deps toolchain task
|
||||
path:gfx/wr/Cargo.lock
|
||||
|
||||
# for the mar-tools toolchain task
|
||||
path:mfbt/
|
||||
path:modules/libmar/
|
||||
path:other-licenses/bsdiff/
|
||||
path:other-licenses/nsis/Contrib/CityHash/cityhash/
|
||||
path:toolkit/mozapps/update/updater
|
||||
|
|
|
@ -307,10 +307,6 @@ void BrowsingContext::CacheChildren(bool aFromIPC) {
|
|||
|
||||
bool BrowsingContext::IsCached() { return sCachedBrowsingContexts->has(Id()); }
|
||||
|
||||
bool BrowsingContext::HasOpener() const {
|
||||
return sBrowsingContexts->has(mOpenerId);
|
||||
}
|
||||
|
||||
void BrowsingContext::GetChildren(
|
||||
nsTArray<RefPtr<BrowsingContext>>& aChildren) {
|
||||
MOZ_ALWAYS_TRUE(aChildren.AppendElements(mChildren));
|
||||
|
|
|
@ -121,7 +121,6 @@ class BrowsingContext : public nsWrapperCache,
|
|||
// null if it's not.
|
||||
nsIDocShell* GetDocShell() { return mDocShell; }
|
||||
void SetDocShell(nsIDocShell* aDocShell);
|
||||
void ClearDocShell() { mDocShell = nullptr; }
|
||||
|
||||
// Get the outer window object for this BrowsingContext if it is in-process
|
||||
// and still has a docshell, or null otherwise.
|
||||
|
@ -162,8 +161,6 @@ class BrowsingContext : public nsWrapperCache,
|
|||
SetOpenerId(aOpener ? aOpener->Id() : 0);
|
||||
}
|
||||
|
||||
bool HasOpener() const;
|
||||
|
||||
void GetChildren(nsTArray<RefPtr<BrowsingContext>>& aChildren);
|
||||
|
||||
BrowsingContextGroup* Group() { return mGroup; }
|
||||
|
|
|
@ -152,8 +152,8 @@ typedef ScrollableLayerGuid::ViewID ViewID;
|
|||
// we'd need to re-institute a fixed version of bug 98158.
|
||||
#define MAX_DEPTH_CONTENT_FRAMES 10
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsFrameLoader, mBrowsingContext,
|
||||
mMessageManager, mChildMessageManager,
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsFrameLoader, mDocShell, mMessageManager,
|
||||
mChildMessageManager, mOpener,
|
||||
mParentSHistory, mRemoteBrowser)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
|
||||
|
@ -165,11 +165,11 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameLoader)
|
|||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
|
||||
nsFrameLoader::nsFrameLoader(Element* aOwner, nsPIDOMWindowOuter* aOpener,
|
||||
bool aNetworkCreated)
|
||||
: mBrowsingContext(aBrowsingContext),
|
||||
mOwnerContent(aOwner),
|
||||
: mOwnerContent(aOwner),
|
||||
mDetachedSubdocFrame(nullptr),
|
||||
mOpener(aOpener),
|
||||
mRemoteBrowser(nullptr),
|
||||
mChildID(0),
|
||||
mDepthTooGreat(false),
|
||||
|
@ -185,15 +185,15 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
|
|||
mIsRemoteFrame(false),
|
||||
mObservingOwnerContent(false) {
|
||||
mIsRemoteFrame = ShouldUseRemoteProcess();
|
||||
MOZ_ASSERT(!mIsRemoteFrame || !mBrowsingContext->HasOpener(),
|
||||
MOZ_ASSERT(!mIsRemoteFrame || !aOpener,
|
||||
"Cannot pass aOpener for a remote frame!");
|
||||
}
|
||||
|
||||
nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
|
||||
nsFrameLoader::nsFrameLoader(Element* aOwner,
|
||||
const mozilla::dom::RemotenessOptions& aOptions)
|
||||
: mBrowsingContext(aBrowsingContext),
|
||||
mOwnerContent(aOwner),
|
||||
: mOwnerContent(aOwner),
|
||||
mDetachedSubdocFrame(nullptr),
|
||||
mOpener(nullptr),
|
||||
mRemoteBrowser(nullptr),
|
||||
mChildID(0),
|
||||
mDepthTooGreat(false),
|
||||
|
@ -212,6 +212,14 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
|
|||
(!aOptions.mRemoteType.Value().IsVoid())) {
|
||||
mIsRemoteFrame = true;
|
||||
}
|
||||
bool hasOpener =
|
||||
aOptions.mOpener.WasPassed() && !aOptions.mOpener.Value().IsNull();
|
||||
MOZ_ASSERT(!mIsRemoteFrame || !hasOpener,
|
||||
"Cannot pass aOpener for a remote frame!");
|
||||
if (hasOpener) {
|
||||
// This seems slightly unwieldy.
|
||||
mOpener = aOptions.mOpener.Value().Value().get()->GetDOMWindow();
|
||||
}
|
||||
}
|
||||
|
||||
nsFrameLoader::~nsFrameLoader() {
|
||||
|
@ -221,70 +229,9 @@ nsFrameLoader::~nsFrameLoader() {
|
|||
MOZ_RELEASE_ASSERT(mDestroyCalled);
|
||||
}
|
||||
|
||||
static void GetFrameName(Element* aOwnerContent, nsAString& aFrameName) {
|
||||
int32_t namespaceID = aOwnerContent->GetNameSpaceID();
|
||||
if (namespaceID == kNameSpaceID_XHTML && !aOwnerContent->IsInHTMLDocument()) {
|
||||
aOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, aFrameName);
|
||||
} else {
|
||||
aOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, aFrameName);
|
||||
// XXX if no NAME then use ID, after a transition period this will be
|
||||
// changed so that XUL only uses ID too (bug 254284).
|
||||
if (aFrameName.IsEmpty() && namespaceID == kNameSpaceID_XUL) {
|
||||
aOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, aFrameName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static already_AddRefed<BrowsingContext> CreateBrowsingContext(
|
||||
Element* aOwner, BrowsingContext* aOpener) {
|
||||
Document* doc = aOwner->OwnerDoc();
|
||||
// Get our parent docshell off the document of mOwnerContent
|
||||
// XXXbz this is such a total hack.... We really need to have a
|
||||
// better setup for doing this.
|
||||
|
||||
// Determine our parent nsDocShell
|
||||
RefPtr<nsDocShell> parentDocShell = nsDocShell::Cast(doc->GetDocShell());
|
||||
|
||||
if (NS_WARN_IF(!parentDocShell)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<BrowsingContext> parentContext = parentDocShell->GetBrowsingContext();
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(parentContext, "docShell must have BrowsingContext");
|
||||
|
||||
// Determine the frame name for the new browsing context.
|
||||
nsAutoString frameName;
|
||||
GetFrameName(aOwner, frameName);
|
||||
|
||||
// Check if our new context is chrome or content
|
||||
bool isContent =
|
||||
parentContext->IsContent() ||
|
||||
aOwner->AttrValueIs(
|
||||
kNameSpaceID_None,
|
||||
aOwner->IsXULElement() ? nsGkAtoms::type : nsGkAtoms::mozframetype,
|
||||
nsGkAtoms::content, eIgnoreCase);
|
||||
|
||||
// Force mozbrowser frames to always be content, even if the mozbrowser
|
||||
// interfaces are disabled.
|
||||
nsCOMPtr<nsIMozBrowserFrame> mozbrowser = aOwner->GetAsMozBrowserFrame();
|
||||
if (!isContent && mozbrowser) {
|
||||
mozbrowser->GetMozbrowser(&isContent);
|
||||
}
|
||||
|
||||
// If we're content but our parent isn't, we're going to want to
|
||||
// start a new browsing context tree.
|
||||
if (isContent && !parentContext->IsContent()) {
|
||||
parentContext = nullptr;
|
||||
}
|
||||
|
||||
BrowsingContext::Type type = isContent ? BrowsingContext::Type::Content
|
||||
: BrowsingContext::Type::Chrome;
|
||||
|
||||
return BrowsingContext::Create(parentContext, aOpener, frameName, type);
|
||||
}
|
||||
|
||||
nsFrameLoader* nsFrameLoader::Create(Element* aOwner, BrowsingContext* aOpener,
|
||||
/* static */
|
||||
nsFrameLoader* nsFrameLoader::Create(Element* aOwner,
|
||||
nsPIDOMWindowOuter* aOpener,
|
||||
bool aNetworkCreated) {
|
||||
NS_ENSURE_TRUE(aOwner, nullptr);
|
||||
Document* doc = aOwner->OwnerDoc();
|
||||
|
@ -314,8 +261,7 @@ nsFrameLoader* nsFrameLoader::Create(Element* aOwner, BrowsingContext* aOpener,
|
|||
doc->IsStaticDocument()),
|
||||
nullptr);
|
||||
|
||||
RefPtr<BrowsingContext> context = CreateBrowsingContext(aOwner, aOpener);
|
||||
return new nsFrameLoader(aOwner, context, aNetworkCreated);
|
||||
return new nsFrameLoader(aOwner, aOpener, aNetworkCreated);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -325,21 +271,7 @@ nsFrameLoader* nsFrameLoader::Create(
|
|||
NS_ENSURE_TRUE(aOwner, nullptr);
|
||||
// This version of Create is only called for Remoteness updates, so we can
|
||||
// assume we need a FrameLoader here and skip the check in the other Create.
|
||||
|
||||
bool hasOpener =
|
||||
aOptions.mOpener.WasPassed() && !aOptions.mOpener.Value().IsNull();
|
||||
MOZ_ASSERT(!aOptions.mRemoteType.WasPassed() ||
|
||||
aOptions.mRemoteType.Value().IsVoid() || !hasOpener,
|
||||
"Cannot pass aOpener for a remote frame!");
|
||||
|
||||
// This seems slightly unwieldy.
|
||||
RefPtr<BrowsingContext> opener;
|
||||
if (hasOpener) {
|
||||
opener = aOptions.mOpener.Value().Value().get();
|
||||
}
|
||||
RefPtr<BrowsingContext> context = CreateBrowsingContext(aOwner, opener);
|
||||
|
||||
return new nsFrameLoader(aOwner, context, aOptions);
|
||||
return new nsFrameLoader(aOwner, aOptions);
|
||||
}
|
||||
|
||||
void nsFrameLoader::LoadFrame(bool aOriginalSrc) {
|
||||
|
@ -497,8 +429,8 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() {
|
|||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
MOZ_ASSERT(GetDocShell(),
|
||||
"MaybeCreateDocShell succeeded with a null docShell");
|
||||
NS_ASSERTION(mDocShell,
|
||||
"MaybeCreateDocShell succeeded with a null mDocShell");
|
||||
|
||||
// Just to be safe, recheck uri.
|
||||
rv = CheckURILoad(mURIToLoad, mTriggeringPrincipal);
|
||||
|
@ -600,7 +532,7 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() {
|
|||
mNeedsAsyncDestroy = true;
|
||||
loadState->SetLoadFlags(flags);
|
||||
loadState->SetFirstParty(false);
|
||||
rv = GetDocShell()->LoadURI(loadState);
|
||||
rv = mDocShell->LoadURI(loadState);
|
||||
mNeedsAsyncDestroy = tmpState;
|
||||
mURIToLoad = nullptr;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -659,11 +591,11 @@ nsDocShell* nsFrameLoader::GetDocShell(ErrorResult& aRv) {
|
|||
aRv.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(GetDocShell(),
|
||||
"MaybeCreateDocShell succeeded, but null docShell");
|
||||
NS_ASSERTION(mDocShell,
|
||||
"MaybeCreateDocShell succeeded, but null mDocShell");
|
||||
}
|
||||
|
||||
return GetDocShell();
|
||||
return mDocShell;
|
||||
}
|
||||
|
||||
static void SetTreeOwnerAndChromeEventHandlerOnDocshellTree(
|
||||
|
@ -809,20 +741,20 @@ bool nsFrameLoader::Show(int32_t marginWidth, int32_t marginHeight,
|
|||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(GetDocShell(), "MaybeCreateDocShell succeeded, but null docShell");
|
||||
if (!GetDocShell()) {
|
||||
NS_ASSERTION(mDocShell, "MaybeCreateDocShell succeeded, but null mDocShell");
|
||||
if (!mDocShell) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GetDocShell()->SetMarginWidth(marginWidth);
|
||||
GetDocShell()->SetMarginHeight(marginHeight);
|
||||
mDocShell->SetMarginWidth(marginWidth);
|
||||
mDocShell->SetMarginHeight(marginHeight);
|
||||
|
||||
GetDocShell()->SetDefaultScrollbarPreferences(
|
||||
nsIScrollable::ScrollOrientation_X, scrollbarPrefX);
|
||||
GetDocShell()->SetDefaultScrollbarPreferences(
|
||||
nsIScrollable::ScrollOrientation_Y, scrollbarPrefY);
|
||||
mDocShell->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,
|
||||
scrollbarPrefX);
|
||||
mDocShell->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,
|
||||
scrollbarPrefY);
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = GetDocShell()->GetPresShell();
|
||||
nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
|
||||
if (presShell) {
|
||||
// Ensure root scroll frame is reflowed in case scroll preferences or
|
||||
// margins have changed
|
||||
|
@ -837,7 +769,7 @@ bool nsFrameLoader::Show(int32_t marginWidth, int32_t marginHeight,
|
|||
nsView* view = frame->EnsureInnerView();
|
||||
if (!view) return false;
|
||||
|
||||
RefPtr<nsDocShell> baseWindow = GetDocShell();
|
||||
RefPtr<nsDocShell> baseWindow = mDocShell;
|
||||
baseWindow->InitWindow(nullptr, view->GetWidget(), 0, 0, size.width,
|
||||
size.height);
|
||||
// This is kinda whacky, this "Create()" call doesn't really
|
||||
|
@ -845,13 +777,13 @@ bool nsFrameLoader::Show(int32_t marginWidth, int32_t marginHeight,
|
|||
// "Create"...
|
||||
baseWindow->Create();
|
||||
baseWindow->SetVisibility(true);
|
||||
NS_ENSURE_TRUE(GetDocShell(), false);
|
||||
NS_ENSURE_TRUE(mDocShell, false);
|
||||
|
||||
// Trigger editor re-initialization if midas is turned on in the
|
||||
// sub-document. This shouldn't be necessary, but given the way our
|
||||
// editor works, it is. See
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=284245
|
||||
presShell = GetDocShell()->GetPresShell();
|
||||
presShell = mDocShell->GetPresShell();
|
||||
if (presShell) {
|
||||
Document* doc = presShell->GetDocument();
|
||||
nsHTMLDocument* htmlDoc =
|
||||
|
@ -864,7 +796,7 @@ bool nsFrameLoader::Show(int32_t marginWidth, int32_t marginHeight,
|
|||
if (designMode.EqualsLiteral("on")) {
|
||||
// Hold on to the editor object to let the document reattach to the
|
||||
// same editor object, instead of creating a new one.
|
||||
RefPtr<HTMLEditor> htmlEditor = GetDocShell()->GetHTMLEditor();
|
||||
RefPtr<HTMLEditor> htmlEditor = mDocShell->GetHTMLEditor();
|
||||
Unused << htmlEditor;
|
||||
htmlDoc->SetDesignMode(NS_LITERAL_STRING("off"), Nothing(),
|
||||
IgnoreErrors());
|
||||
|
@ -874,9 +806,9 @@ bool nsFrameLoader::Show(int32_t marginWidth, int32_t marginHeight,
|
|||
} else {
|
||||
// Re-initialize the presentation for contenteditable documents
|
||||
bool editable = false, hasEditingSession = false;
|
||||
GetDocShell()->GetEditable(&editable);
|
||||
GetDocShell()->GetHasEditingSession(&hasEditingSession);
|
||||
RefPtr<HTMLEditor> htmlEditor = GetDocShell()->GetHTMLEditor();
|
||||
mDocShell->GetEditable(&editable);
|
||||
mDocShell->GetHasEditingSession(&hasEditingSession);
|
||||
RefPtr<HTMLEditor> htmlEditor = mDocShell->GetHTMLEditor();
|
||||
if (editable && hasEditingSession && htmlEditor) {
|
||||
htmlEditor->PostCreate();
|
||||
}
|
||||
|
@ -896,24 +828,20 @@ bool nsFrameLoader::Show(int32_t marginWidth, int32_t marginHeight,
|
|||
void nsFrameLoader::MarginsChanged(uint32_t aMarginWidth,
|
||||
uint32_t aMarginHeight) {
|
||||
// We assume that the margins are always zero for remote frames.
|
||||
if (IsRemoteFrame()) {
|
||||
return;
|
||||
}
|
||||
if (IsRemoteFrame()) return;
|
||||
|
||||
// If there's no docshell, we're probably not up and running yet.
|
||||
// nsFrameLoader::Show() will take care of setting the right
|
||||
// margins.
|
||||
if (!GetDocShell()) {
|
||||
return;
|
||||
}
|
||||
if (!mDocShell) return;
|
||||
|
||||
// Set the margins
|
||||
GetDocShell()->SetMarginWidth(aMarginWidth);
|
||||
GetDocShell()->SetMarginHeight(aMarginHeight);
|
||||
mDocShell->SetMarginWidth(aMarginWidth);
|
||||
mDocShell->SetMarginHeight(aMarginHeight);
|
||||
|
||||
// There's a cached property declaration block
|
||||
// that needs to be updated
|
||||
if (Document* doc = GetDocShell()->GetDocument()) {
|
||||
if (Document* doc = mDocShell->GetDocument()) {
|
||||
for (nsINode* cur = doc; cur; cur = cur->GetNextNode()) {
|
||||
if (cur->IsHTMLElement(nsGkAtoms::body)) {
|
||||
static_cast<HTMLBodyElement*>(cur)->ClearMappedServoStyle();
|
||||
|
@ -923,7 +851,7 @@ void nsFrameLoader::MarginsChanged(uint32_t aMarginWidth,
|
|||
|
||||
// Trigger a restyle if there's a prescontext
|
||||
// FIXME: This could do something much less expensive.
|
||||
if (nsPresContext* presContext = GetDocShell()->GetPresContext()) {
|
||||
if (nsPresContext* presContext = mDocShell->GetPresContext()) {
|
||||
// rebuild, because now the same nsMappedAttributes* will produce
|
||||
// a different style
|
||||
presContext->RebuildAllStyleData(nsChangeHint(0),
|
||||
|
@ -1012,15 +940,13 @@ void nsFrameLoader::Hide() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!GetDocShell()) {
|
||||
return;
|
||||
}
|
||||
if (!mDocShell) return;
|
||||
|
||||
nsCOMPtr<nsIContentViewer> contentViewer;
|
||||
GetDocShell()->GetContentViewer(getter_AddRefs(contentViewer));
|
||||
mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
|
||||
if (contentViewer) contentViewer->SetSticky(false);
|
||||
|
||||
RefPtr<nsDocShell> baseWin = GetDocShell();
|
||||
RefPtr<nsDocShell> baseWin = mDocShell;
|
||||
baseWin->SetVisibility(false);
|
||||
baseWin->SetParentWidget(nullptr);
|
||||
}
|
||||
|
@ -1731,26 +1657,26 @@ void nsFrameLoader::StartDestroy() {
|
|||
|
||||
// Seems like this is a dynamic frame removal.
|
||||
if (dynamicSubframeRemoval) {
|
||||
if (GetDocShell()) {
|
||||
GetDocShell()->RemoveFromSessionHistory();
|
||||
if (mDocShell) {
|
||||
mDocShell->RemoveFromSessionHistory();
|
||||
}
|
||||
}
|
||||
|
||||
// Let the tree owner know we're gone.
|
||||
if (mIsTopLevelContent) {
|
||||
if (GetDocShell()) {
|
||||
if (mDocShell) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
GetDocShell()->GetParent(getter_AddRefs(parentItem));
|
||||
mDocShell->GetParent(getter_AddRefs(parentItem));
|
||||
nsCOMPtr<nsIDocShellTreeOwner> owner = do_GetInterface(parentItem);
|
||||
if (owner) {
|
||||
owner->ContentShellRemoved(GetDocShell());
|
||||
owner->ContentShellRemoved(mDocShell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Let our window know that we are gone
|
||||
if (GetDocShell()) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win_private(GetDocShell()->GetWindow());
|
||||
if (mDocShell) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win_private(mDocShell->GetWindow());
|
||||
if (win_private) {
|
||||
win_private->SetFrameElementInternal(nullptr);
|
||||
}
|
||||
|
@ -1830,11 +1756,10 @@ void nsFrameLoader::DestroyDocShell() {
|
|||
}
|
||||
|
||||
// Destroy the docshell.
|
||||
if (GetDocShell()) {
|
||||
GetDocShell()->Destroy();
|
||||
if (mDocShell) {
|
||||
mDocShell->Destroy();
|
||||
}
|
||||
|
||||
mBrowsingContext = nullptr;
|
||||
mDocShell = nullptr;
|
||||
|
||||
if (mChildMessageManager) {
|
||||
// Stop handling events in the in-process frame script.
|
||||
|
@ -1966,8 +1891,37 @@ bool nsFrameLoader::ShouldUseRemoteProcess() {
|
|||
nsGkAtoms::_true, eCaseMatters);
|
||||
}
|
||||
|
||||
static already_AddRefed<BrowsingContext> CreateBrowsingContext(
|
||||
BrowsingContext* aParentContext, BrowsingContext* aOpenerContext,
|
||||
const nsAString& aName, bool aIsContent) {
|
||||
// If we're content but our parent isn't, we're going to want to start a new
|
||||
// browsing context tree.
|
||||
if (aIsContent && aParentContext && !aParentContext->IsContent()) {
|
||||
aParentContext = nullptr;
|
||||
}
|
||||
|
||||
BrowsingContext::Type type = aIsContent ? BrowsingContext::Type::Content
|
||||
: BrowsingContext::Type::Chrome;
|
||||
|
||||
return BrowsingContext::Create(aParentContext, aOpenerContext, aName, type);
|
||||
}
|
||||
|
||||
static void GetFrameName(Element* aOwnerContent, nsAString& aFrameName) {
|
||||
int32_t namespaceID = aOwnerContent->GetNameSpaceID();
|
||||
if (namespaceID == kNameSpaceID_XHTML && !aOwnerContent->IsInHTMLDocument()) {
|
||||
aOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, aFrameName);
|
||||
} else {
|
||||
aOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, aFrameName);
|
||||
// XXX if no NAME then use ID, after a transition period this will be
|
||||
// changed so that XUL only uses ID too (bug 254284).
|
||||
if (aFrameName.IsEmpty() && namespaceID == kNameSpaceID_XUL) {
|
||||
aOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, aFrameName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsFrameLoader::MaybeCreateDocShell() {
|
||||
if (GetDocShell()) {
|
||||
if (mDocShell) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (IsRemoteFrame()) {
|
||||
|
@ -1996,20 +1950,43 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// Determine our parent nsDocShell
|
||||
RefPtr<nsDocShell> parentDocShell = nsDocShell::Cast(doc->GetDocShell());
|
||||
if (NS_WARN_IF(!parentDocShell)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// nsDocShell::Create will attach itself to the passed browsing
|
||||
// context inside of nsDocShell::Create
|
||||
RefPtr<nsDocShell> docShell = nsDocShell::Create(mBrowsingContext);
|
||||
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
||||
RefPtr<BrowsingContext> parentBC = parentDocShell->GetBrowsingContext();
|
||||
MOZ_ASSERT(parentBC, "docShell must have BrowsingContext");
|
||||
|
||||
mIsTopLevelContent =
|
||||
mBrowsingContext->IsContent() && !mBrowsingContext->GetParent();
|
||||
// Determine the frame name for the new browsing context.
|
||||
nsAutoString frameName;
|
||||
GetFrameName(mOwnerContent, frameName);
|
||||
|
||||
// Check if our new context is chrome or content
|
||||
bool isContent = parentBC->IsContent() ||
|
||||
mOwnerContent->AttrValueIs(kNameSpaceID_None, TypeAttrName(),
|
||||
nsGkAtoms::content, eIgnoreCase);
|
||||
|
||||
// Force mozbrowser frames to always be content, even if the mozbrowser
|
||||
// interfaces are disabled.
|
||||
nsCOMPtr<nsIMozBrowserFrame> mozbrowser =
|
||||
mOwnerContent->GetAsMozBrowserFrame();
|
||||
if (!isContent && mozbrowser) {
|
||||
mozbrowser->GetMozbrowser(&isContent);
|
||||
}
|
||||
|
||||
RefPtr<BrowsingContext> openerBC =
|
||||
mOpener ? mOpener->GetBrowsingContext() : nullptr;
|
||||
RefPtr<BrowsingContext> browsingContext =
|
||||
CreateBrowsingContext(parentBC, openerBC, frameName, isContent);
|
||||
|
||||
mDocShell = nsDocShell::Create(browsingContext);
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
||||
|
||||
mIsTopLevelContent = isContent && !parentBC->IsContent();
|
||||
if (!mNetworkCreated && !mIsTopLevelContent) {
|
||||
docShell->SetCreatedDynamically(true);
|
||||
mDocShell->SetCreatedDynamically(true);
|
||||
}
|
||||
|
||||
if (mIsTopLevelContent) {
|
||||
|
@ -2018,20 +1995,19 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
|
|||
//
|
||||
// XXX(nika): Consider removing the DocShellTree in the future, for
|
||||
// consistency between local and remote frames..
|
||||
parentDocShell->AddChild(docShell);
|
||||
parentDocShell->AddChild(mDocShell);
|
||||
}
|
||||
|
||||
// Now that we are part of the DocShellTree, attach our DocShell to our
|
||||
// parent's TreeOwner.
|
||||
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
|
||||
parentDocShell->GetTreeOwner(getter_AddRefs(parentTreeOwner));
|
||||
AddTreeItemToTreeOwner(docShell, parentTreeOwner);
|
||||
AddTreeItemToTreeOwner(mDocShell, parentTreeOwner);
|
||||
|
||||
// Make sure all nsDocShells have links back to the content element in the
|
||||
// nearest enclosing chrome shell.
|
||||
RefPtr<EventTarget> chromeEventHandler;
|
||||
bool parentIsContent = parentDocShell->GetBrowsingContext()->IsContent();
|
||||
if (parentIsContent) {
|
||||
if (parentBC->IsContent()) {
|
||||
// Our parent shell is a content shell. Get the chrome event handler from it
|
||||
// and use that for our shell as well.
|
||||
parentDocShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
|
||||
|
@ -2041,15 +2017,15 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
|
|||
chromeEventHandler = mOwnerContent;
|
||||
}
|
||||
|
||||
docShell->SetChromeEventHandler(chromeEventHandler);
|
||||
mDocShell->SetChromeEventHandler(chromeEventHandler);
|
||||
|
||||
// This is nasty, this code (the docShell->GetWindow() below)
|
||||
// This is nasty, this code (the mDocShell->GetWindow() below)
|
||||
// *must* come *after* the above call to
|
||||
// docShell->SetChromeEventHandler() for the global window to get
|
||||
// mDocShell->SetChromeEventHandler() for the global window to get
|
||||
// the right chrome event handler.
|
||||
|
||||
// Tell the window about the frame that hosts it.
|
||||
nsCOMPtr<nsPIDOMWindowOuter> newWindow = docShell->GetWindow();
|
||||
nsCOMPtr<nsPIDOMWindowOuter> newWindow = mDocShell->GetWindow();
|
||||
if (NS_WARN_IF(!newWindow)) {
|
||||
// Do not call Destroy() here. See bug 472312.
|
||||
NS_WARNING("Something wrong when creating the docshell for a frameloader!");
|
||||
|
@ -2058,10 +2034,13 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
|
|||
|
||||
newWindow->SetFrameElementInternal(mOwnerContent);
|
||||
|
||||
// Set the opener window if we have one provided here XXX(nika): We
|
||||
// should tell our BrowsingContext this as we create it.
|
||||
// TODO(farre): Remove this when nsGlobalWindowOuter::GetOpenerWindowOuter
|
||||
// starts using BrowsingContext::GetOpener.
|
||||
if (RefPtr<BrowsingContext> opener = mBrowsingContext->GetOpener()) {
|
||||
newWindow->SetOpenerWindow(opener->GetDOMWindow(), true);
|
||||
if (mOpener) {
|
||||
newWindow->SetOpenerWindow(mOpener, true);
|
||||
mOpener = nullptr;
|
||||
}
|
||||
|
||||
// Allow scripts to close the docshell if specified.
|
||||
|
@ -2075,6 +2054,7 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
|
|||
// This is kinda whacky, this call doesn't really create anything,
|
||||
// but it must be called to make sure things are properly
|
||||
// initialized.
|
||||
RefPtr<nsDocShell> docShell = mDocShell;
|
||||
if (NS_FAILED(docShell->Create())) {
|
||||
// Do not call Destroy() here. See bug 472312.
|
||||
NS_WARNING("Something wrong when creating the docshell for a frameloader!");
|
||||
|
@ -2087,13 +2067,13 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
|
|||
if (mIsTopLevelContent && mOwnerContent->IsXULElement(nsGkAtoms::browser) &&
|
||||
!mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disablehistory)) {
|
||||
// XXX(nika): Set this up more explicitly?
|
||||
nsresult rv = docShell->InitSessionHistory();
|
||||
nsresult rv = mDocShell->InitSessionHistory();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mParentSHistory = new ParentSHistory(this);
|
||||
}
|
||||
|
||||
OriginAttributes attrs;
|
||||
if (parentDocShell->ItemType() == docShell->ItemType()) {
|
||||
if (parentDocShell->ItemType() == mDocShell->ItemType()) {
|
||||
attrs = parentDocShell->GetOriginAttributes();
|
||||
}
|
||||
|
||||
|
@ -2104,7 +2084,7 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
|
|||
//
|
||||
// For example, firstPartyDomain is computed from top-level document, it
|
||||
// doesn't exist in the top-level docshell.
|
||||
if (parentIsContent &&
|
||||
if (parentBC->IsContent() &&
|
||||
!nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()) &&
|
||||
!OwnerIsMozBrowserFrame()) {
|
||||
OriginAttributes oa = doc->NodePrincipal()->OriginAttributesRef();
|
||||
|
@ -2132,18 +2112,18 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
|
|||
if (OwnerIsMozBrowserFrame()) {
|
||||
attrs.mAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
attrs.mInIsolatedMozBrowser = OwnerIsIsolatedMozBrowserFrame();
|
||||
docShell->SetFrameType(nsIDocShell::FRAME_TYPE_BROWSER);
|
||||
mDocShell->SetFrameType(nsIDocShell::FRAME_TYPE_BROWSER);
|
||||
} else {
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentCheck;
|
||||
docShell->GetSameTypeParent(getter_AddRefs(parentCheck));
|
||||
mDocShell->GetSameTypeParent(getter_AddRefs(parentCheck));
|
||||
if (!!parentCheck) {
|
||||
docShell->SetIsFrame();
|
||||
mDocShell->SetIsFrame();
|
||||
}
|
||||
}
|
||||
|
||||
// Apply sandbox flags even if our owner is not an iframe, as this copies
|
||||
// flags from our owning content's owning document.
|
||||
// Note: ApplySandboxFlags should be called after docShell->SetFrameType
|
||||
// Note: ApplySandboxFlags should be called after mDocShell->SetFrameType
|
||||
// because we need to get the correct presentation URL in ApplySandboxFlags.
|
||||
uint32_t sandboxFlags = 0;
|
||||
HTMLIFrameElement* iframe = HTMLIFrameElement::FromNode(mOwnerContent);
|
||||
|
@ -2169,16 +2149,16 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
|
|||
// For inproc frames, set the docshell properties.
|
||||
nsAutoString name;
|
||||
if (mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name)) {
|
||||
docShell->SetName(name);
|
||||
mDocShell->SetName(name);
|
||||
}
|
||||
docShell->SetFullscreenAllowed(
|
||||
mDocShell->SetFullscreenAllowed(
|
||||
mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
|
||||
mOwnerContent->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::mozallowfullscreen));
|
||||
bool isPrivate = mOwnerContent->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::mozprivatebrowsing);
|
||||
if (isPrivate) {
|
||||
if (docShell->GetHasLoadedNonBlankURI()) {
|
||||
if (mDocShell->GetHasLoadedNonBlankURI()) {
|
||||
nsContentUtils::ReportToConsoleNonLocalized(
|
||||
NS_LITERAL_STRING("We should not switch to Private Browsing after "
|
||||
"loading a document."),
|
||||
|
@ -2192,28 +2172,30 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
|
|||
}
|
||||
}
|
||||
|
||||
docShell->SetOriginAttributes(attrs);
|
||||
nsDocShell::Cast(mDocShell)->SetOriginAttributes(attrs);
|
||||
|
||||
// Typically there will be a window, however for some cases such as printing
|
||||
// the document is cloned with a docshell that has no window. We check
|
||||
// that the window exists to ensure we don't try to gather ancestors for
|
||||
// those cases.
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = doc->GetWindow();
|
||||
if (!docShell->GetIsMozBrowser() &&
|
||||
parentDocShell->ItemType() == docShell->ItemType() &&
|
||||
if (!mDocShell->GetIsMozBrowser() &&
|
||||
parentDocShell->ItemType() == mDocShell->ItemType() &&
|
||||
!doc->IsStaticDocument() && win) {
|
||||
// Propagate through the ancestor principals.
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>> ancestorPrincipals;
|
||||
// Make a copy, so we can modify it.
|
||||
ancestorPrincipals = doc->AncestorPrincipals();
|
||||
ancestorPrincipals.InsertElementAt(0, doc->NodePrincipal());
|
||||
docShell->SetAncestorPrincipals(std::move(ancestorPrincipals));
|
||||
nsDocShell::Cast(mDocShell)->SetAncestorPrincipals(
|
||||
std::move(ancestorPrincipals));
|
||||
|
||||
// Repeat for outer window IDs.
|
||||
nsTArray<uint64_t> ancestorOuterWindowIDs;
|
||||
ancestorOuterWindowIDs = doc->AncestorOuterWindowIDs();
|
||||
ancestorOuterWindowIDs.InsertElementAt(0, win->WindowID());
|
||||
docShell->SetAncestorOuterWindowIDs(std::move(ancestorOuterWindowIDs));
|
||||
nsDocShell::Cast(mDocShell)->SetAncestorOuterWindowIDs(
|
||||
std::move(ancestorOuterWindowIDs));
|
||||
}
|
||||
|
||||
ReallyLoadFrameScripts();
|
||||
|
@ -2270,19 +2252,19 @@ nsresult nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI) {
|
|||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
MOZ_ASSERT(GetDocShell(), "MaybeCreateDocShell succeeded, but null docShell");
|
||||
if (!GetDocShell()) {
|
||||
NS_ASSERTION(mDocShell, "MaybeCreateDocShell succeeded, but null mDocShell");
|
||||
if (!mDocShell) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Check that we're still in the docshell tree.
|
||||
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
||||
GetDocShell()->GetTreeOwner(getter_AddRefs(treeOwner));
|
||||
mDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
|
||||
NS_WARNING_ASSERTION(treeOwner,
|
||||
"Trying to load a new url to a docshell without owner!");
|
||||
NS_ENSURE_STATE(treeOwner);
|
||||
|
||||
if (GetDocShell()->ItemType() != nsIDocShellTreeItem::typeContent) {
|
||||
if (mDocShell->ItemType() != nsIDocShellTreeItem::typeContent) {
|
||||
// No need to do recursion-protection here XXXbz why not?? Do we really
|
||||
// trust people not to screw up with non-content docshells?
|
||||
return NS_OK;
|
||||
|
@ -2291,7 +2273,7 @@ nsresult nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI) {
|
|||
// Bug 8065: Don't exceed some maximum depth in content frames
|
||||
// (MAX_DEPTH_CONTENT_FRAMES)
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
|
||||
GetDocShell()->GetSameTypeParent(getter_AddRefs(parentAsItem));
|
||||
mDocShell->GetSameTypeParent(getter_AddRefs(parentAsItem));
|
||||
int32_t depth = 0;
|
||||
while (parentAsItem) {
|
||||
++depth;
|
||||
|
@ -2323,7 +2305,7 @@ nsresult nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI) {
|
|||
}
|
||||
}
|
||||
int32_t matchCount = 0;
|
||||
GetDocShell()->GetSameTypeParent(getter_AddRefs(parentAsItem));
|
||||
mDocShell->GetSameTypeParent(getter_AddRefs(parentAsItem));
|
||||
while (parentAsItem) {
|
||||
// Check the parent URI with the URI we're loading
|
||||
nsCOMPtr<nsIWebNavigation> parentAsNav(do_QueryInterface(parentAsItem));
|
||||
|
@ -2601,15 +2583,27 @@ bool nsFrameLoader::TryRemoteBrowser() {
|
|||
|
||||
// If we're in a content process, create a BrowserBridgeChild actor.
|
||||
if (XRE_IsContentProcess()) {
|
||||
// Determine the frame name for the new browsing context.
|
||||
nsAutoString frameName;
|
||||
GetFrameName(mOwnerContent, frameName);
|
||||
|
||||
RefPtr<BrowsingContext> parentBC;
|
||||
parentDocShell->GetBrowsingContext(getter_AddRefs(parentBC));
|
||||
MOZ_ASSERT(parentBC, "docShell must have BrowsingContext");
|
||||
|
||||
// XXX(nika): due to limitations with Browsing Context Groups and multiple
|
||||
// processes, we can't link up aParent yet! (Bug 1532661)
|
||||
RefPtr<BrowsingContext> browsingContext =
|
||||
CreateBrowsingContext(parentBC, nullptr, frameName, true);
|
||||
|
||||
mBrowserBridgeChild = BrowserBridgeChild::Create(
|
||||
this, context, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
|
||||
mBrowsingContext);
|
||||
this, context, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), browsingContext);
|
||||
return !!mBrowserBridgeChild;
|
||||
}
|
||||
|
||||
mRemoteBrowser = ContentParent::CreateBrowser(
|
||||
context, ownerElement, mBrowsingContext, openerContentParent,
|
||||
sameTabGroupAs, nextTabParentId);
|
||||
mRemoteBrowser =
|
||||
ContentParent::CreateBrowser(context, ownerElement, openerContentParent,
|
||||
sameTabGroupAs, nextTabParentId);
|
||||
if (!mRemoteBrowser) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2668,7 +2662,7 @@ bool nsFrameLoader::TryRemoteBrowser() {
|
|||
|
||||
bool nsFrameLoader::IsRemoteFrame() {
|
||||
if (mIsRemoteFrame) {
|
||||
MOZ_ASSERT(!GetDocShell(), "Found a remote frame with a DocShell");
|
||||
MOZ_ASSERT(!mDocShell, "Found a remote frame with a DocShell");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -2741,13 +2735,13 @@ void nsFrameLoader::ActivateFrameEvent(const nsAString& aType, bool aCapture,
|
|||
|
||||
nsresult nsFrameLoader::CreateStaticClone(nsFrameLoader* aDest) {
|
||||
aDest->MaybeCreateDocShell();
|
||||
NS_ENSURE_STATE(aDest->GetDocShell());
|
||||
NS_ENSURE_STATE(aDest->mDocShell);
|
||||
|
||||
nsCOMPtr<Document> kungFuDeathGrip = aDest->GetDocShell()->GetDocument();
|
||||
nsCOMPtr<Document> kungFuDeathGrip = aDest->mDocShell->GetDocument();
|
||||
Unused << kungFuDeathGrip;
|
||||
|
||||
nsCOMPtr<nsIContentViewer> viewer;
|
||||
aDest->GetDocShell()->GetContentViewer(getter_AddRefs(viewer));
|
||||
aDest->mDocShell->GetContentViewer(getter_AddRefs(viewer));
|
||||
NS_ENSURE_STATE(viewer);
|
||||
|
||||
nsIDocShell* origDocShell = GetDocShell(IgnoreErrors());
|
||||
|
@ -2756,7 +2750,7 @@ nsresult nsFrameLoader::CreateStaticClone(nsFrameLoader* aDest) {
|
|||
nsCOMPtr<Document> doc = origDocShell->GetDocument();
|
||||
NS_ENSURE_STATE(doc);
|
||||
|
||||
nsCOMPtr<Document> clonedDoc = doc->CreateStaticClone(aDest->GetDocShell());
|
||||
nsCOMPtr<Document> clonedDoc = doc->CreateStaticClone(aDest->mDocShell);
|
||||
|
||||
viewer->SetDocument(clonedDoc);
|
||||
return NS_OK;
|
||||
|
@ -2894,13 +2888,13 @@ nsresult nsFrameLoader::EnsureMessageManager() {
|
|||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
MOZ_ASSERT(GetDocShell(),
|
||||
"MaybeCreateDocShell succeeded, but null docShell");
|
||||
if (!GetDocShell()) {
|
||||
NS_ASSERTION(mDocShell,
|
||||
"MaybeCreateDocShell succeeded, but null mDocShell");
|
||||
if (!mDocShell) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mChildMessageManager = InProcessTabChildMessageManager::Create(
|
||||
GetDocShell(), mOwnerContent, mMessageManager);
|
||||
mDocShell, mOwnerContent, mMessageManager);
|
||||
NS_ENSURE_TRUE(mChildMessageManager, NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -2946,7 +2940,7 @@ nsIFrame* nsFrameLoader::GetDetachedSubdocFrame(
|
|||
}
|
||||
|
||||
void nsFrameLoader::ApplySandboxFlags(uint32_t sandboxFlags) {
|
||||
if (GetDocShell()) {
|
||||
if (mDocShell) {
|
||||
uint32_t parentSandboxFlags = mOwnerContent->OwnerDoc()->GetSandboxFlags();
|
||||
|
||||
// The child can only add restrictions, never remove them.
|
||||
|
@ -2956,11 +2950,11 @@ void nsFrameLoader::ApplySandboxFlags(uint32_t sandboxFlags) {
|
|||
// sandboxed auxiliary navigation flag to sandboxFlags. See
|
||||
// https://w3c.github.io/presentation-api/#creating-a-receiving-browsing-context
|
||||
nsAutoString presentationURL;
|
||||
nsContentUtils::GetPresentationURL(GetDocShell(), presentationURL);
|
||||
nsContentUtils::GetPresentationURL(mDocShell, presentationURL);
|
||||
if (!presentationURL.IsEmpty()) {
|
||||
sandboxFlags |= SANDBOXED_AUXILIARY_NAVIGATION;
|
||||
}
|
||||
GetDocShell()->SetSandboxFlags(sandboxFlags);
|
||||
mDocShell->SetSandboxFlags(sandboxFlags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2986,13 +2980,13 @@ void nsFrameLoader::AttributeChanged(mozilla::dom::Element* aElement,
|
|||
// Notify our enclosing chrome that our type has changed. We only do this
|
||||
// if our parent is chrome, since in all other cases we're random content
|
||||
// subframes and the treeowner shouldn't worry about us.
|
||||
if (!GetDocShell()) {
|
||||
if (!mDocShell) {
|
||||
MaybeUpdatePrimaryTabParent(eTabParentChanged);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
GetDocShell()->GetParent(getter_AddRefs(parentItem));
|
||||
mDocShell->GetParent(getter_AddRefs(parentItem));
|
||||
if (!parentItem) {
|
||||
return;
|
||||
}
|
||||
|
@ -3014,16 +3008,14 @@ void nsFrameLoader::AttributeChanged(mozilla::dom::Element* aElement,
|
|||
// when a content panel is no longer primary, hide any open popups it may have
|
||||
if (!is_primary) {
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm) {
|
||||
pm->HidePopupsInDocShell(GetDocShell());
|
||||
}
|
||||
if (pm) pm->HidePopupsInDocShell(mDocShell);
|
||||
}
|
||||
#endif
|
||||
|
||||
parentTreeOwner->ContentShellRemoved(GetDocShell());
|
||||
parentTreeOwner->ContentShellRemoved(mDocShell);
|
||||
if (aElement->AttrValueIs(kNameSpaceID_None, TypeAttrName(),
|
||||
nsGkAtoms::content, eIgnoreCase)) {
|
||||
parentTreeOwner->ContentShellAdded(GetDocShell(), is_primary);
|
||||
parentTreeOwner->ContentShellAdded(mDocShell, is_primary);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3128,8 +3120,7 @@ already_AddRefed<mozilla::dom::Promise> nsFrameLoader::DrawSnapshot(
|
|||
gfx::CrossProcessPaint::StartRemote(mRemoteBrowser->GetTabId(), rect,
|
||||
aScale, color, promise);
|
||||
} else {
|
||||
gfx::CrossProcessPaint::StartLocal(GetDocShell(), rect, aScale, color,
|
||||
promise);
|
||||
gfx::CrossProcessPaint::StartLocal(mDocShell, rect, aScale, color, promise);
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
|
@ -3164,7 +3155,7 @@ already_AddRefed<BrowsingContext> nsFrameLoader::GetBrowsingContext() {
|
|||
browsingContext = mBrowserBridgeChild->GetBrowsingContext();
|
||||
}
|
||||
} else if (GetDocShell(IgnoreErrors())) {
|
||||
browsingContext = GetDocShell()->GetBrowsingContext();
|
||||
browsingContext = nsDocShell::Cast(mDocShell)->GetBrowsingContext();
|
||||
}
|
||||
return browsingContext.forget();
|
||||
}
|
||||
|
@ -3211,8 +3202,7 @@ void nsFrameLoader::StartPersistence(
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<Document> rootDoc =
|
||||
GetDocShell() ? GetDocShell()->GetDocument() : nullptr;
|
||||
nsCOMPtr<Document> rootDoc = mDocShell ? mDocShell->GetDocument() : nullptr;
|
||||
nsCOMPtr<Document> foundDoc;
|
||||
if (aOuterWindowID) {
|
||||
foundDoc = nsContentUtils::GetSubdocumentWithOuterWindowId(rootDoc,
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "nsIURI.h"
|
||||
#include "nsFrameMessageManager.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ParentSHistory.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
@ -50,6 +49,7 @@ namespace mozilla {
|
|||
class OriginAttributes;
|
||||
|
||||
namespace dom {
|
||||
class BrowsingContext;
|
||||
class ChromeMessageSender;
|
||||
class ContentParent;
|
||||
class InProcessTabChildMessageManager;
|
||||
|
@ -99,7 +99,7 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||
public:
|
||||
// Called by Frame Elements to create a new FrameLoader.
|
||||
static nsFrameLoader* Create(mozilla::dom::Element* aOwner,
|
||||
mozilla::dom::BrowsingContext* aOpener,
|
||||
nsPIDOMWindowOuter* aOpener,
|
||||
bool aNetworkCreated);
|
||||
|
||||
// Called by nsFrameLoaderOwner::ChangeRemoteness when switching out
|
||||
|
@ -118,9 +118,7 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||
void StartDestroy();
|
||||
void DestroyDocShell();
|
||||
void DestroyComplete();
|
||||
nsIDocShell* GetExistingDocShell() const {
|
||||
return mBrowsingContext ? mBrowsingContext->GetDocShell() : nullptr;
|
||||
}
|
||||
nsIDocShell* GetExistingDocShell() { return mDocShell; }
|
||||
mozilla::dom::InProcessTabChildMessageManager* GetTabChildMessageManager()
|
||||
const {
|
||||
return mChildMessageManager;
|
||||
|
@ -370,11 +368,9 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
private:
|
||||
nsFrameLoader(mozilla::dom::Element* aOwner,
|
||||
mozilla::dom::BrowsingContext* aBrowsingContext,
|
||||
nsFrameLoader(mozilla::dom::Element* aOwner, nsPIDOMWindowOuter* aOpener,
|
||||
bool aNetworkCreated);
|
||||
nsFrameLoader(mozilla::dom::Element* aOwner,
|
||||
mozilla::dom::BrowsingContext* aBrowsingContext,
|
||||
const mozilla::dom::RemotenessOptions& aOptions);
|
||||
~nsFrameLoader();
|
||||
|
||||
|
@ -404,10 +400,6 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||
nsresult MaybeCreateDocShell();
|
||||
nsresult EnsureMessageManager();
|
||||
nsresult ReallyLoadFrameScripts();
|
||||
nsDocShell* GetDocShell() const {
|
||||
return mBrowsingContext ? nsDocShell::Cast(mBrowsingContext->GetDocShell())
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
// Updates the subdocument position and size. This gets called only
|
||||
// when we have our own in-process DocShell.
|
||||
|
@ -451,7 +443,7 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||
|
||||
nsresult PopulateUserContextIdFromAttribute(mozilla::OriginAttributes& aAttr);
|
||||
|
||||
RefPtr<mozilla::dom::BrowsingContext> mBrowsingContext;
|
||||
RefPtr<nsDocShell> mDocShell;
|
||||
nsCOMPtr<nsIURI> mURIToLoad;
|
||||
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
|
||||
nsCOMPtr<nsIContentSecurityPolicy> mCsp;
|
||||
|
@ -472,6 +464,9 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||
// a reframe, so that we know not to restore the presentation.
|
||||
RefPtr<Document> mContainerDocWhileDetached;
|
||||
|
||||
// An opener window which should be used when the docshell is created.
|
||||
nsCOMPtr<nsPIDOMWindowOuter> mOpener;
|
||||
|
||||
RefPtr<TabParent> mRemoteBrowser;
|
||||
uint64_t mChildID;
|
||||
|
||||
|
|
|
@ -2468,7 +2468,6 @@ void nsGlobalWindowOuter::DetachFromDocShell() {
|
|||
}
|
||||
|
||||
mDocShell = nullptr;
|
||||
mBrowsingContext->ClearDocShell();
|
||||
|
||||
if (mFrames) {
|
||||
mFrames->SetDocShell(nullptr);
|
||||
|
|
|
@ -133,7 +133,9 @@ void nsGenericHTMLFrameElement::EnsureFrameLoader() {
|
|||
|
||||
// Strangely enough, this method doesn't actually ensure that the
|
||||
// frameloader exists. It's more of a best-effort kind of thing.
|
||||
mFrameLoader = nsFrameLoader::Create(this, mOpenerWindow, mNetworkCreated);
|
||||
mFrameLoader = nsFrameLoader::Create(
|
||||
this, mOpenerWindow ? mOpenerWindow->GetDOMWindow() : nullptr,
|
||||
mNetworkCreated);
|
||||
}
|
||||
|
||||
nsresult nsGenericHTMLFrameElement::CreateRemoteFrameLoader(
|
||||
|
|
|
@ -1087,7 +1087,6 @@ mozilla::ipc::IPCResult ContentParent::RecvLaunchRDDProcess(
|
|||
/*static*/
|
||||
TabParent* ContentParent::CreateBrowser(const TabContext& aContext,
|
||||
Element* aFrameElement,
|
||||
BrowsingContext* aBrowsingContext,
|
||||
ContentParent* aOpenerContentParent,
|
||||
TabParent* aSameTabGroupAs,
|
||||
uint64_t aNextTabParentId) {
|
||||
|
@ -1148,9 +1147,16 @@ TabParent* ContentParent::CreateBrowser(const TabContext& aContext,
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: This BrowsingContext should be provided by the nsFrameLoader.
|
||||
// (bug 1523636)
|
||||
RefPtr<CanonicalBrowsingContext> browsingContext =
|
||||
BrowsingContext::Create(nullptr, nullptr, EmptyString(),
|
||||
BrowsingContext::Type::Content)
|
||||
.downcast<CanonicalBrowsingContext>();
|
||||
|
||||
// Ensure that our content process is subscribed to our newly created
|
||||
// BrowsingContextGroup.
|
||||
aBrowsingContext->Group()->EnsureSubscribed(constructorSender);
|
||||
browsingContext->Group()->EnsureSubscribed(constructorSender);
|
||||
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
cpm->RegisterRemoteFrame(tabId, ContentParentId(0), openerTabId,
|
||||
|
@ -1182,19 +1188,17 @@ TabParent* ContentParent::CreateBrowser(const TabContext& aContext,
|
|||
if (tabId == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<TabParent> tp =
|
||||
new TabParent(constructorSender, tabId, aContext,
|
||||
aBrowsingContext->Canonical(), chromeFlags);
|
||||
RefPtr<TabParent> tp = new TabParent(constructorSender, tabId, aContext,
|
||||
browsingContext, chromeFlags);
|
||||
|
||||
aBrowsingContext->Canonical()->SetOwnerProcessId(
|
||||
constructorSender->ChildID());
|
||||
browsingContext->SetOwnerProcessId(constructorSender->ChildID());
|
||||
|
||||
PBrowserParent* browser = constructorSender->SendPBrowserConstructor(
|
||||
// DeallocPBrowserParent() releases this ref.
|
||||
tp.forget().take(), tabId,
|
||||
aSameTabGroupAs ? aSameTabGroupAs->GetTabId() : TabId(0),
|
||||
aContext.AsIPCTabContext(), chromeFlags, constructorSender->ChildID(),
|
||||
aBrowsingContext, constructorSender->IsForBrowser());
|
||||
browsingContext, constructorSender->IsForBrowser());
|
||||
|
||||
if (remoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
|
||||
// Tell the TabChild object that it was created due to a Large-Allocation
|
||||
|
|
|
@ -208,7 +208,6 @@ class ContentParent final : public PContentParent,
|
|||
*/
|
||||
static TabParent* CreateBrowser(const TabContext& aContext,
|
||||
Element* aFrameElement,
|
||||
BrowsingContext* aBrowsingContext,
|
||||
ContentParent* aOpenerContentParent,
|
||||
TabParent* aSameTabGroupAs,
|
||||
uint64_t aNextTabParentId);
|
||||
|
|
|
@ -47,9 +47,6 @@ add_task(async function() {
|
|||
let frameLoader = SpecialPowers.wrap(iframe).frameLoader;
|
||||
is(frameLoader.docShell, null);
|
||||
is(frameLoader.tabParent, null);
|
||||
let browsingContext = frameLoader.browsingContext;
|
||||
isnot(browsingContext, null);
|
||||
is(browsingContext.docShell, null);
|
||||
|
||||
await contentCreated;
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class SVGViewportElement;
|
|||
|
||||
class UserSpaceMetrics {
|
||||
public:
|
||||
virtual ~UserSpaceMetrics() {}
|
||||
virtual ~UserSpaceMetrics() = default;
|
||||
|
||||
virtual float GetEmLength() const = 0;
|
||||
virtual float GetExLength() const = 0;
|
||||
|
|
|
@ -42,7 +42,7 @@ class SVGAnimatedLengthList {
|
|||
friend class dom::DOMSVGLengthList;
|
||||
|
||||
public:
|
||||
SVGAnimatedLengthList() {}
|
||||
SVGAnimatedLengthList() = default;
|
||||
|
||||
/**
|
||||
* Because it's so important that mBaseVal and its DOMSVGLengthList wrapper
|
||||
|
|
|
@ -44,7 +44,7 @@ class SVGAnimatedPathSegList final {
|
|||
friend class DOMSVGPathSegList;
|
||||
|
||||
public:
|
||||
SVGAnimatedPathSegList() {}
|
||||
SVGAnimatedPathSegList() = default;
|
||||
|
||||
/**
|
||||
* Because it's so important that mBaseVal and its DOMSVGPathSegList wrapper
|
||||
|
|
|
@ -43,7 +43,7 @@ class SVGAnimatedPointList {
|
|||
friend class DOMSVGPointList;
|
||||
|
||||
public:
|
||||
SVGAnimatedPointList() {}
|
||||
SVGAnimatedPointList() = default;
|
||||
|
||||
/**
|
||||
* Because it's so important that mBaseVal and its DOMSVGPointList wrapper
|
||||
|
|
|
@ -34,7 +34,7 @@ class SVGComponentTransferFunctionElement
|
|||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
|
||||
: SVGComponentTransferFunctionElementBase(std::move(aNodeInfo)) {}
|
||||
|
||||
virtual ~SVGComponentTransferFunctionElement() {}
|
||||
virtual ~SVGComponentTransferFunctionElement() = default;
|
||||
|
||||
public:
|
||||
typedef gfx::ComponentTransferAttributes ComponentTransferAttributes;
|
||||
|
|
|
@ -55,7 +55,7 @@ class SVGFE : public SVGFEBase {
|
|||
|
||||
explicit SVGFE(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
|
||||
: SVGFEBase(std::move(aNodeInfo)) {}
|
||||
virtual ~SVGFE() {}
|
||||
virtual ~SVGFE() = default;
|
||||
|
||||
public:
|
||||
typedef mozilla::gfx::PrimitiveAttributes PrimitiveAttributes;
|
||||
|
@ -183,7 +183,7 @@ class SVGFELightingElement : public SVGFELightingElementBase {
|
|||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
|
||||
: SVGFELightingElementBase(std::move(aNodeInfo)) {}
|
||||
|
||||
virtual ~SVGFELightingElement() {}
|
||||
virtual ~SVGFELightingElement() = default;
|
||||
|
||||
public:
|
||||
// interfaces:
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace dom {
|
|||
|
||||
class SVGIRect : public nsISupports, public nsWrapperCache {
|
||||
public:
|
||||
virtual ~SVGIRect() {}
|
||||
virtual ~SVGIRect() = default;
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override {
|
||||
|
|
|
@ -41,7 +41,7 @@ class SVGIntegerPairSMILType : public SMILType {
|
|||
|
||||
private:
|
||||
// Private constructor: prevent instances beyond my singleton.
|
||||
constexpr SVGIntegerPairSMILType() {}
|
||||
constexpr SVGIntegerPairSMILType() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -39,8 +39,8 @@ class SVGLengthList {
|
|||
friend class SVGAnimatedLengthList;
|
||||
|
||||
public:
|
||||
SVGLengthList() {}
|
||||
~SVGLengthList() {}
|
||||
SVGLengthList() = default;
|
||||
~SVGLengthList() = default;
|
||||
|
||||
// Only methods that don't make/permit modification to this list are public.
|
||||
// Only our friend classes can access methods that may change us.
|
||||
|
|
|
@ -91,7 +91,7 @@ class SVGLengthListSMILType : public SMILType {
|
|||
|
||||
private:
|
||||
// Private constructor: prevent instances beyond my singleton.
|
||||
constexpr SVGLengthListSMILType() {}
|
||||
constexpr SVGLengthListSMILType() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -63,7 +63,7 @@ class SVGMatrix final : public nsWrapperCache {
|
|||
* Ctors for SVGMatrix objects created independently of a DOMSVGTransform.
|
||||
*/
|
||||
// Default ctor for gfxMatrix will produce identity mx
|
||||
SVGMatrix() {}
|
||||
SVGMatrix() = default;
|
||||
|
||||
explicit SVGMatrix(const gfxMatrix& aMatrix) : mMatrix(aMatrix) {}
|
||||
|
||||
|
@ -103,7 +103,7 @@ class SVGMatrix final : public nsWrapperCache {
|
|||
already_AddRefed<SVGMatrix> SkewY(float angle, ErrorResult& rv);
|
||||
|
||||
private:
|
||||
~SVGMatrix() {}
|
||||
~SVGMatrix() = default;
|
||||
|
||||
void SetMatrix(const gfxMatrix& aMatrix) {
|
||||
if (mTransform) {
|
||||
|
|
|
@ -71,7 +71,7 @@ class SVGMotionSMILType : public SMILType {
|
|||
|
||||
private:
|
||||
// Private constructor: prevent instances beyond my singleton.
|
||||
constexpr SVGMotionSMILType() {}
|
||||
constexpr SVGMotionSMILType() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -37,8 +37,8 @@ class SVGNumberList {
|
|||
friend class SVGAnimatedNumberList;
|
||||
|
||||
public:
|
||||
SVGNumberList() {}
|
||||
~SVGNumberList() {}
|
||||
SVGNumberList() = default;
|
||||
~SVGNumberList() = default;
|
||||
|
||||
// Only methods that don't make/permit modification to this list are public.
|
||||
// Only our friend classes can access methods that may change us.
|
||||
|
|
|
@ -45,7 +45,7 @@ class SVGNumberListSMILType : public SMILType {
|
|||
|
||||
private:
|
||||
// Private constructor: prevent instances beyond my singleton.
|
||||
constexpr SVGNumberListSMILType() {}
|
||||
constexpr SVGNumberListSMILType() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -38,7 +38,7 @@ class SVGNumberPairSMILType : public SMILType {
|
|||
|
||||
private:
|
||||
// Private constructor: prevent instances beyond my singleton.
|
||||
constexpr SVGNumberPairSMILType() {}
|
||||
constexpr SVGNumberPairSMILType() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -58,7 +58,7 @@ class SVGOrientSMILType : public SMILType {
|
|||
|
||||
private:
|
||||
// Private constructor: prevent instances beyond my singleton.
|
||||
constexpr SVGOrientSMILType() {}
|
||||
constexpr SVGOrientSMILType() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -91,8 +91,8 @@ class SVGPathData {
|
|||
public:
|
||||
typedef const float* const_iterator;
|
||||
|
||||
SVGPathData() {}
|
||||
~SVGPathData() {}
|
||||
SVGPathData() = default;
|
||||
~SVGPathData() = default;
|
||||
|
||||
// Only methods that don't make/permit modification to this list are public.
|
||||
// Only our friend classes can access methods that may change us.
|
||||
|
|
|
@ -48,7 +48,7 @@ class SVGPathSegListSMILType : public SMILType {
|
|||
|
||||
private:
|
||||
// Private constructor: prevent instances beyond my singleton.
|
||||
constexpr SVGPathSegListSMILType() {}
|
||||
constexpr SVGPathSegListSMILType() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -73,7 +73,7 @@ struct SVGPathTraversalState {
|
|||
*/
|
||||
class SVGPathSegUtils {
|
||||
private:
|
||||
SVGPathSegUtils() {} // private to prevent instances
|
||||
SVGPathSegUtils() = default; // private to prevent instances
|
||||
|
||||
public:
|
||||
static void GetValueAsString(const float* aSeg, nsAString& aValue);
|
||||
|
|
|
@ -37,8 +37,8 @@ class SVGPointList {
|
|||
friend class DOMSVGPoint;
|
||||
|
||||
public:
|
||||
SVGPointList() {}
|
||||
~SVGPointList() {}
|
||||
SVGPointList() = default;
|
||||
~SVGPointList() = default;
|
||||
|
||||
// Only methods that don't make/permit modification to this list are public.
|
||||
// Only our friend classes can access methods that may change us.
|
||||
|
|
|
@ -45,7 +45,7 @@ class SVGPointListSMILType : public SMILType {
|
|||
|
||||
private:
|
||||
// Private constructor: prevent instances beyond my singleton.
|
||||
constexpr SVGPointListSMILType() {}
|
||||
constexpr SVGPointListSMILType() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -46,7 +46,7 @@ class SVGRect final : public SVGIRect {
|
|||
virtual nsIContent* GetParentObject() const override { return mParent; }
|
||||
|
||||
protected:
|
||||
~SVGRect() {}
|
||||
~SVGRect() = default;
|
||||
|
||||
nsCOMPtr<nsIContent> mParent;
|
||||
float mX, mY, mWidth, mHeight;
|
||||
|
|
|
@ -65,7 +65,7 @@ class DOMSVGTranslatePoint final : public nsISVGPoint {
|
|||
RefPtr<SVGSVGElement> mElement;
|
||||
|
||||
private:
|
||||
~DOMSVGTranslatePoint() {}
|
||||
~DOMSVGTranslatePoint() = default;
|
||||
};
|
||||
|
||||
typedef SVGViewportElement SVGSVGElementBase;
|
||||
|
|
|
@ -22,7 +22,7 @@ class SVGStringList {
|
|||
|
||||
public:
|
||||
SVGStringList() : mIsSet(false), mIsCommaSeparated(false) {}
|
||||
~SVGStringList() {}
|
||||
~SVGStringList() = default;
|
||||
|
||||
void SetIsCommaSeparated(bool aIsCommaSeparated) {
|
||||
mIsCommaSeparated = aIsCommaSeparated;
|
||||
|
|
|
@ -105,7 +105,7 @@ class SVGTests : public nsISupports {
|
|||
}
|
||||
|
||||
protected:
|
||||
virtual ~SVGTests() {}
|
||||
virtual ~SVGTests() = default;
|
||||
|
||||
private:
|
||||
enum { FEATURES, EXTENSIONS, LANGUAGE };
|
||||
|
|
|
@ -32,8 +32,8 @@ class SVGTransformList {
|
|||
friend class dom::DOMSVGTransform;
|
||||
|
||||
public:
|
||||
SVGTransformList() {}
|
||||
~SVGTransformList() {}
|
||||
SVGTransformList() = default;
|
||||
~SVGTransformList() = default;
|
||||
|
||||
// Only methods that don't make/permit modification to this list are public.
|
||||
// Only our friend classes can access methods that may change us.
|
||||
|
|
|
@ -116,7 +116,7 @@ class SVGTransformListSMILType : public SMILType {
|
|||
|
||||
private:
|
||||
// Private constructor: prevent instances beyond my singleton.
|
||||
constexpr SVGTransformListSMILType() {}
|
||||
constexpr SVGTransformListSMILType() = default;
|
||||
};
|
||||
|
||||
} // end namespace mozilla
|
||||
|
|
|
@ -27,7 +27,7 @@ class SVGTransformableElement : public SVGElement {
|
|||
public:
|
||||
explicit SVGTransformableElement(already_AddRefed<dom::NodeInfo>&& aNodeInfo)
|
||||
: SVGElement(std::move(aNodeInfo)) {}
|
||||
virtual ~SVGTransformableElement() {}
|
||||
virtual ~SVGTransformableElement() = default;
|
||||
|
||||
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override = 0;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class SVGViewBoxSMILType : public SMILType {
|
|||
|
||||
private:
|
||||
// Private constructor: prevent instances beyond my singleton.
|
||||
constexpr SVGViewBoxSMILType() {}
|
||||
constexpr SVGViewBoxSMILType() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -25,9 +25,9 @@ class nsSVGViewportFrame;
|
|||
|
||||
namespace mozilla {
|
||||
class AutoPreserveAspectRatioOverride;
|
||||
class DOMSVGAnimatedPreserveAspectRatio;
|
||||
|
||||
namespace dom {
|
||||
class DOMSVGAnimatedPreserveAspectRatio;
|
||||
class SVGAnimatedRect;
|
||||
class SVGViewElement;
|
||||
class SVGViewportElement;
|
||||
|
|
|
@ -92,7 +92,8 @@ void XULFrameElement::LoadSrc() {
|
|||
// session history handling works like dynamic html:iframes.
|
||||
// Usually xul elements are used in chrome, which doesn't have
|
||||
// session history at all.
|
||||
mFrameLoader = nsFrameLoader::Create(this, opener, false);
|
||||
mFrameLoader = nsFrameLoader::Create(
|
||||
this, opener ? opener->GetDOMWindow() : nullptr, false);
|
||||
if (NS_WARN_IF(!mFrameLoader)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -923,6 +923,7 @@ void gfxPlatform::Init() {
|
|||
#else
|
||||
# error "No gfxPlatform implementation available"
|
||||
#endif
|
||||
gPlatform->PopulateScreenInfo();
|
||||
gPlatform->InitAcceleration();
|
||||
gPlatform->InitWebRenderConfig();
|
||||
// When using WebRender, we defer initialization of the D3D11 devices until
|
||||
|
@ -960,7 +961,6 @@ void gfxPlatform::Init() {
|
|||
|
||||
InitLayersIPC();
|
||||
|
||||
gPlatform->PopulateScreenInfo();
|
||||
gPlatform->ComputeTileSize();
|
||||
|
||||
#ifdef MOZ_ENABLE_FREETYPE
|
||||
|
@ -2511,7 +2511,7 @@ static bool CalculateWrQualifiedPrefValue() {
|
|||
}
|
||||
|
||||
static FeatureState& WebRenderHardwareQualificationStatus(
|
||||
bool aHasBattery, nsCString& aOutFailureId) {
|
||||
const IntSize& aScreenSize, bool aHasBattery, nsCString& aOutFailureId) {
|
||||
FeatureState& featureWebRenderQualified =
|
||||
gfxConfig::GetFeature(Feature::WEBRENDER_QUALIFIED);
|
||||
featureWebRenderQualified.EnableByDefault();
|
||||
|
@ -2576,7 +2576,8 @@ static FeatureState& WebRenderHardwareQualificationStatus(
|
|||
FeatureStatus::Blocked, "Device too old",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_DEVICE_TOO_OLD"));
|
||||
}
|
||||
} else if (adapterVendorID == u"0x8086") { // Intel
|
||||
} else if (adapterVendorID == u"0x8086" ||
|
||||
adapterVendorID == u"mesa/i965") { // Intel
|
||||
const uint16_t supportedDevices[] = {
|
||||
0x191d, // HD Graphics P530
|
||||
0x192d, // Iris Pro Graphics P555
|
||||
|
@ -2605,6 +2606,18 @@ static FeatureState& WebRenderHardwareQualificationStatus(
|
|||
featureWebRenderQualified.Disable(
|
||||
FeatureStatus::Blocked, "Device too old",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_DEVICE_TOO_OLD"));
|
||||
} else if (adapterVendorID == u"mesa/i965") {
|
||||
const int32_t maxPixels = 3440 * 1440; // UWQHD
|
||||
int32_t pixels = aScreenSize.width * aScreenSize.height;
|
||||
if (pixels > maxPixels) {
|
||||
featureWebRenderQualified.Disable(
|
||||
FeatureStatus::Blocked, "Screen size too large",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_SCREEN_SIZE_TOO_LARGE"));
|
||||
} else if (pixels <= 0) {
|
||||
featureWebRenderQualified.Disable(
|
||||
FeatureStatus::Blocked, "Screen size unknown",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_SCREEN_SIZE_UNKNOWN"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
|
@ -2653,7 +2666,8 @@ void gfxPlatform::InitWebRenderConfig() {
|
|||
|
||||
nsCString failureId;
|
||||
FeatureState& featureWebRenderQualified =
|
||||
WebRenderHardwareQualificationStatus(HasBattery(), failureId);
|
||||
WebRenderHardwareQualificationStatus(GetScreenSize(), HasBattery(),
|
||||
failureId);
|
||||
FeatureState& featureWebRender = gfxConfig::GetFeature(Feature::WEBRENDER);
|
||||
|
||||
featureWebRender.DisableByDefault(
|
||||
|
@ -2748,6 +2762,16 @@ void gfxPlatform::InitWebRenderConfig() {
|
|||
WebRenderDebugPrefChangeCallback, WR_DEBUG_PREF);
|
||||
}
|
||||
}
|
||||
#if defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID)
|
||||
else if (gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) {
|
||||
// Hardware compositing should be disabled by default if we aren't using
|
||||
// WebRender. We had to check if it is enabled at all, because it may
|
||||
// already have been forced disabled (e.g. safe mode, headless). It may
|
||||
// still be forced on by the user, and if so, this should have no effect.
|
||||
gfxConfig::Disable(Feature::HW_COMPOSITING, FeatureStatus::Blocked,
|
||||
"Acceleration blocked by platform");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (Preferences::GetBool("gfx.webrender.dcomp-win.enabled", false)) {
|
||||
|
|
|
@ -736,7 +736,7 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
|
|||
gfxPlatform();
|
||||
virtual ~gfxPlatform();
|
||||
|
||||
virtual bool HasBattery() { return true; }
|
||||
virtual bool HasBattery() { return false; }
|
||||
|
||||
virtual void InitAcceleration();
|
||||
virtual void InitWebRenderConfig();
|
||||
|
|
|
@ -330,7 +330,7 @@ uint32_t gfxPlatformGtk::MaxGenericSubstitions() {
|
|||
}
|
||||
|
||||
bool gfxPlatformGtk::AccelerateLayersByDefault() {
|
||||
return gfxPrefs::WebRenderAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
void gfxPlatformGtk::GetPlatformCMSOutputProfile(void*& mem, size_t& size) {
|
||||
|
|
|
@ -307,6 +307,14 @@ typedef enum JSGCParamKey {
|
|||
*/
|
||||
JSGC_MIN_NURSERY_BYTES = 31,
|
||||
|
||||
/*
|
||||
* The minimum time to allow between triggering last ditch GCs in seconds.
|
||||
*
|
||||
* Default: 60 seconds
|
||||
* Pref: None
|
||||
*/
|
||||
JSGC_MIN_LAST_DITCH_GC_PERIOD = 32,
|
||||
|
||||
} JSGCParamKey;
|
||||
|
||||
/*
|
||||
|
|
|
@ -488,7 +488,8 @@ static bool MinorGC(JSContext* cx, unsigned argc, Value* vp) {
|
|||
_("allocationThreshold", JSGC_ALLOCATION_THRESHOLD, true) \
|
||||
_("minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT, true) \
|
||||
_("maxEmptyChunkCount", JSGC_MAX_EMPTY_CHUNK_COUNT, true) \
|
||||
_("compactingEnabled", JSGC_COMPACTING_ENABLED, true)
|
||||
_("compactingEnabled", JSGC_COMPACTING_ENABLED, true) \
|
||||
_("minLastDitchGCPeriod", JSGC_MIN_LAST_DITCH_GC_PERIOD, true)
|
||||
|
||||
static const struct ParamInfo {
|
||||
const char* name;
|
||||
|
|
|
@ -41,7 +41,7 @@ LoopControl::LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
|
|||
|
||||
LoopControl* enclosingLoop = findNearest<LoopControl>(enclosing());
|
||||
|
||||
stackDepth_ = bce->stackDepth;
|
||||
stackDepth_ = bce->bytecodeSection().stackDepth();
|
||||
loopDepth_ = enclosingLoop ? enclosingLoop->loopDepth_ + 1 : 1;
|
||||
|
||||
int loopSlots;
|
||||
|
@ -81,7 +81,7 @@ bool LoopControl::emitContinueTarget(BytecodeEmitter* bce) {
|
|||
bool LoopControl::emitSpecialBreakForDone(BytecodeEmitter* bce) {
|
||||
// This doesn't pop stack values, nor handle any other controls.
|
||||
// Should be called on the toplevel of the loop.
|
||||
MOZ_ASSERT(bce->stackDepth == stackDepth_);
|
||||
MOZ_ASSERT(bce->bytecodeSection().stackDepth() == stackDepth_);
|
||||
MOZ_ASSERT(bce->innermostNestableControl == this);
|
||||
|
||||
if (!bce->newSrcNote(SRC_BREAK)) {
|
||||
|
@ -109,7 +109,7 @@ bool LoopControl::emitLoopHead(BytecodeEmitter* bce,
|
|||
}
|
||||
}
|
||||
|
||||
head_ = {bce->offset()};
|
||||
head_ = {bce->bytecodeSection().offset()};
|
||||
ptrdiff_t off;
|
||||
if (!bce->emitJumpTargetOp(JSOP_LOOPHEAD, &off)) {
|
||||
return false;
|
||||
|
@ -126,7 +126,7 @@ bool LoopControl::emitLoopEntry(BytecodeEmitter* bce,
|
|||
}
|
||||
}
|
||||
|
||||
JumpTarget entry = {bce->offset()};
|
||||
JumpTarget entry = {bce->bytecodeSection().offset()};
|
||||
bce->patchJumpsToTarget(entryJump_, entry);
|
||||
|
||||
MOZ_ASSERT(loopDepth_ > 0);
|
||||
|
@ -135,7 +135,8 @@ bool LoopControl::emitLoopEntry(BytecodeEmitter* bce,
|
|||
if (!bce->emitJumpTargetOp(JSOP_LOOPENTRY, &off)) {
|
||||
return false;
|
||||
}
|
||||
SetLoopEntryDepthHintAndFlags(bce->code(off), loopDepth_, canIonOsr_);
|
||||
SetLoopEntryDepthHintAndFlags(bce->bytecodeSection().code(off), loopDepth_,
|
||||
canIonOsr_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -91,6 +91,24 @@ static bool ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn) {
|
|||
kind == ParseNodeKind::Function;
|
||||
}
|
||||
|
||||
BytecodeEmitter::BytecodeSection::BytecodeSection(JSContext* cx,
|
||||
uint32_t lineNum)
|
||||
: code_(cx),
|
||||
notes_(cx),
|
||||
tryNoteList_(cx),
|
||||
scopeNoteList_(cx),
|
||||
resumeOffsetList_(cx),
|
||||
currentLine_(lineNum) {}
|
||||
|
||||
BytecodeEmitter::PerScriptData::PerScriptData(JSContext* cx)
|
||||
: scopeList_(cx),
|
||||
numberList_(cx),
|
||||
atomIndices_(cx->frontendCollectionPool()) {}
|
||||
|
||||
bool BytecodeEmitter::PerScriptData::init(JSContext* cx) {
|
||||
return atomIndices_.acquire(cx);
|
||||
}
|
||||
|
||||
BytecodeEmitter::BytecodeEmitter(
|
||||
BytecodeEmitter* parent, SharedContext* sc, HandleScript script,
|
||||
Handle<LazyScript*> lazyScript, uint32_t lineNum, EmitterMode emitterMode,
|
||||
|
@ -100,23 +118,17 @@ BytecodeEmitter::BytecodeEmitter(
|
|||
parent(parent),
|
||||
script(cx, script),
|
||||
lazyScript(cx, lazyScript),
|
||||
code_(cx),
|
||||
notes_(cx),
|
||||
currentLine_(lineNum),
|
||||
bytecodeSection_(cx, lineNum),
|
||||
perScriptData_(cx),
|
||||
fieldInitializers_(fieldInitializers),
|
||||
atomIndices(cx->frontendCollectionPool()),
|
||||
firstLine(lineNum),
|
||||
numberList(cx),
|
||||
scopeList(cx),
|
||||
tryNoteList(cx),
|
||||
scopeNoteList(cx),
|
||||
resumeOffsetList(cx),
|
||||
emitterMode(emitterMode) {
|
||||
MOZ_ASSERT_IF(emitterMode == LazyFunction, lazyScript);
|
||||
|
||||
if (sc->isFunctionBox()) {
|
||||
// Functions have IC entries for type monitoring |this| and arguments.
|
||||
numICEntries = sc->asFunctionBox()->function()->nargs() + 1;
|
||||
bytecodeSection().setNumICEntries(sc->asFunctionBox()->function()->nargs() +
|
||||
1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,7 +160,7 @@ void BytecodeEmitter::initFromBodyPosition(TokenPos bodyPosition) {
|
|||
setFunctionBodyEndPos(bodyPosition.end);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::init() { return atomIndices.acquire(cx); }
|
||||
bool BytecodeEmitter::init() { return perScriptData_.init(cx); }
|
||||
|
||||
template <typename T>
|
||||
T* BytecodeEmitter::findInnermostNestableControl() const {
|
||||
|
@ -194,9 +206,7 @@ bool BytecodeEmitter::markStepBreakpoint() {
|
|||
// We track the location of the most recent separator for use in
|
||||
// markSimpleBreakpoint. Note that this means that the position must already
|
||||
// be set before markStepBreakpoint is called.
|
||||
lastSeparatorOffet_ = code().length();
|
||||
lastSeparatorLine_ = currentLine_;
|
||||
lastSeparatorColumn_ = lastColumn_;
|
||||
bytecodeSection().updateSeparatorPosition();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -210,10 +220,7 @@ bool BytecodeEmitter::markSimpleBreakpoint() {
|
|||
// expression start, we need to skip marking it breakable in order to avoid
|
||||
// having two breakpoints with the same line/column position.
|
||||
// Note: This assumes that the position for the call has already been set.
|
||||
bool isDuplicateLocation =
|
||||
lastSeparatorLine_ == currentLine_ && lastSeparatorColumn_ == lastColumn_;
|
||||
|
||||
if (!isDuplicateLocation) {
|
||||
if (!bytecodeSection().isDuplicateLocation()) {
|
||||
if (!newSrcNote(SRC_BREAKPOINT)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -223,9 +230,9 @@ bool BytecodeEmitter::markSimpleBreakpoint() {
|
|||
}
|
||||
|
||||
bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset) {
|
||||
*offset = code().length();
|
||||
*offset = bytecodeSection().code().length();
|
||||
|
||||
if (!code().growByUninitialized(delta)) {
|
||||
if (!bytecodeSection().code().growByUninitialized(delta)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
@ -233,30 +240,30 @@ bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset) {
|
|||
// If op is JOF_TYPESET (see the type barriers comment in TypeInference.h),
|
||||
// reserve a type set to store its result.
|
||||
if (CodeSpec[op].format & JOF_TYPESET) {
|
||||
if (typesetCount < JSScript::MaxBytecodeTypeSets) {
|
||||
typesetCount++;
|
||||
if (bytecodeSection().typesetCount() < JSScript::MaxBytecodeTypeSets) {
|
||||
bytecodeSection().addTypesetCount();
|
||||
}
|
||||
}
|
||||
|
||||
if (BytecodeOpHasIC(op)) {
|
||||
numICEntries++;
|
||||
bytecodeSection().addNumICEntries();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BytecodeEmitter::updateDepth(ptrdiff_t target) {
|
||||
void BytecodeEmitter::BytecodeSection::updateDepth(ptrdiff_t target) {
|
||||
jsbytecode* pc = code(target);
|
||||
|
||||
int nuses = StackUses(pc);
|
||||
int ndefs = StackDefs(pc);
|
||||
|
||||
stackDepth -= nuses;
|
||||
MOZ_ASSERT(stackDepth >= 0);
|
||||
stackDepth += ndefs;
|
||||
stackDepth_ -= nuses;
|
||||
MOZ_ASSERT(stackDepth_ >= 0);
|
||||
stackDepth_ += ndefs;
|
||||
|
||||
if ((uint32_t)stackDepth > maxStackDepth) {
|
||||
maxStackDepth = stackDepth;
|
||||
if ((uint32_t)stackDepth_ > maxStackDepth_) {
|
||||
maxStackDepth_ = stackDepth_;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,9 +287,9 @@ bool BytecodeEmitter::emit1(JSOp op) {
|
|||
return false;
|
||||
}
|
||||
|
||||
jsbytecode* code = this->code(offset);
|
||||
jsbytecode* code = bytecodeSection().code(offset);
|
||||
code[0] = jsbytecode(op);
|
||||
updateDepth(offset);
|
||||
bytecodeSection().updateDepth(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -294,10 +301,10 @@ bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) {
|
|||
return false;
|
||||
}
|
||||
|
||||
jsbytecode* code = this->code(offset);
|
||||
jsbytecode* code = bytecodeSection().code(offset);
|
||||
code[0] = jsbytecode(op);
|
||||
code[1] = jsbytecode(op1);
|
||||
updateDepth(offset);
|
||||
bytecodeSection().updateDepth(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -313,11 +320,11 @@ bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) {
|
|||
return false;
|
||||
}
|
||||
|
||||
jsbytecode* code = this->code(offset);
|
||||
jsbytecode* code = bytecodeSection().code(offset);
|
||||
code[0] = jsbytecode(op);
|
||||
code[1] = op1;
|
||||
code[2] = op2;
|
||||
updateDepth(offset);
|
||||
bytecodeSection().updateDepth(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -330,7 +337,7 @@ bool BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset) {
|
|||
return false;
|
||||
}
|
||||
|
||||
jsbytecode* code = this->code(off);
|
||||
jsbytecode* code = bytecodeSection().code(off);
|
||||
code[0] = jsbytecode(op);
|
||||
/* The remaining |extra| bytes are set by the caller */
|
||||
|
||||
|
@ -339,7 +346,7 @@ bool BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset) {
|
|||
* operand yet to be stored in the extra bytes after op.
|
||||
*/
|
||||
if (CodeSpec[op].nuses >= 0) {
|
||||
updateDepth(off);
|
||||
bytecodeSection().updateDepth(off);
|
||||
}
|
||||
|
||||
if (offset) {
|
||||
|
@ -351,7 +358,7 @@ bool BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset) {
|
|||
bool BytecodeEmitter::emitJumpTargetOp(JSOp op, ptrdiff_t* off) {
|
||||
MOZ_ASSERT(BytecodeIsJumpTarget(op));
|
||||
|
||||
size_t numEntries = numICEntries;
|
||||
size_t numEntries = bytecodeSection().numICEntries();
|
||||
if (MOZ_UNLIKELY(numEntries > UINT32_MAX)) {
|
||||
reportError(nullptr, JSMSG_NEED_DIET, js_script_str);
|
||||
return false;
|
||||
|
@ -361,21 +368,22 @@ bool BytecodeEmitter::emitJumpTargetOp(JSOp op, ptrdiff_t* off) {
|
|||
return false;
|
||||
}
|
||||
|
||||
SET_ICINDEX(code(*off), numEntries);
|
||||
SET_ICINDEX(bytecodeSection().code(*off), numEntries);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) {
|
||||
ptrdiff_t off = offset();
|
||||
ptrdiff_t off = bytecodeSection().offset();
|
||||
|
||||
// Alias consecutive jump targets.
|
||||
if (off == lastTarget.offset + ptrdiff_t(JSOP_JUMPTARGET_LENGTH)) {
|
||||
target->offset = lastTarget.offset;
|
||||
if (off == bytecodeSection().lastTargetOffset() +
|
||||
ptrdiff_t(JSOP_JUMPTARGET_LENGTH)) {
|
||||
target->offset = bytecodeSection().lastTargetOffset();
|
||||
return true;
|
||||
}
|
||||
|
||||
target->offset = off;
|
||||
lastTarget.offset = off;
|
||||
bytecodeSection().setLastTargetOffset(off);
|
||||
|
||||
ptrdiff_t opOff;
|
||||
return emitJumpTargetOp(JSOP_JUMPTARGET, &opOff);
|
||||
|
@ -387,11 +395,11 @@ bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) {
|
|||
return false;
|
||||
}
|
||||
|
||||
jsbytecode* code = this->code(offset);
|
||||
jsbytecode* code = bytecodeSection().code(offset);
|
||||
code[0] = jsbytecode(op);
|
||||
MOZ_ASSERT(-1 <= jump->offset && jump->offset < offset);
|
||||
jump->push(this->code(0), offset);
|
||||
updateDepth(offset);
|
||||
jump->push(bytecodeSection().code(0), offset);
|
||||
bytecodeSection().updateDepth(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -425,11 +433,12 @@ bool BytecodeEmitter::emitBackwardJump(JSOp op, JumpTarget target,
|
|||
}
|
||||
|
||||
void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) {
|
||||
MOZ_ASSERT(-1 <= jump.offset && jump.offset <= offset());
|
||||
MOZ_ASSERT(0 <= target.offset && target.offset <= offset());
|
||||
MOZ_ASSERT_IF(jump.offset != -1 && target.offset + 4 <= offset(),
|
||||
BytecodeIsJumpTarget(JSOp(*code(target.offset))));
|
||||
jump.patchAll(code(0), target);
|
||||
MOZ_ASSERT(-1 <= jump.offset && jump.offset <= bytecodeSection().offset());
|
||||
MOZ_ASSERT(0 <= target.offset && target.offset <= bytecodeSection().offset());
|
||||
MOZ_ASSERT_IF(
|
||||
jump.offset != -1 && target.offset + 4 <= bytecodeSection().offset(),
|
||||
BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset))));
|
||||
jump.patchAll(bytecodeSection().code(0), target);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) {
|
||||
|
@ -459,7 +468,7 @@ bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) {
|
|||
}
|
||||
|
||||
bool BytecodeEmitter::emitDupAt(unsigned slotFromTop) {
|
||||
MOZ_ASSERT(slotFromTop < unsigned(stackDepth));
|
||||
MOZ_ASSERT(slotFromTop < unsigned(bytecodeSection().stackDepth()));
|
||||
|
||||
if (slotFromTop == 0) {
|
||||
return emit1(JSOP_DUP);
|
||||
|
@ -475,7 +484,7 @@ bool BytecodeEmitter::emitDupAt(unsigned slotFromTop) {
|
|||
return false;
|
||||
}
|
||||
|
||||
jsbytecode* pc = code(off);
|
||||
jsbytecode* pc = bytecodeSection().code(off);
|
||||
SET_UINT24(pc, slotFromTop);
|
||||
return true;
|
||||
}
|
||||
|
@ -516,14 +525,14 @@ bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
|
|||
|
||||
ErrorReporter* er = &parser->errorReporter();
|
||||
bool onThisLine;
|
||||
if (!er->isOnThisLine(offset, currentLine(), &onThisLine)) {
|
||||
if (!er->isOnThisLine(offset, bytecodeSection().currentLine(), &onThisLine)) {
|
||||
er->errorNoOffset(JSMSG_OUT_OF_MEMORY);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!onThisLine) {
|
||||
unsigned line = er->lineAt(offset);
|
||||
unsigned delta = line - currentLine();
|
||||
unsigned delta = line - bytecodeSection().currentLine();
|
||||
|
||||
/*
|
||||
* Encode any change in the current source line number by using
|
||||
|
@ -536,7 +545,7 @@ bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
|
|||
* unsigned delta_ wrap to a very large number, which triggers a
|
||||
* SRC_SETLINE.
|
||||
*/
|
||||
setCurrentLine(line);
|
||||
bytecodeSection().setCurrentLine(line);
|
||||
if (delta >= LengthOfSetLine(line)) {
|
||||
if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(line))) {
|
||||
return false;
|
||||
|
@ -549,7 +558,7 @@ bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
|
|||
} while (--delta != 0);
|
||||
}
|
||||
|
||||
updateSeparatorPosition();
|
||||
bytecodeSection().updateSeparatorPositionIfPresent();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -566,7 +575,8 @@ bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) {
|
|||
}
|
||||
|
||||
uint32_t columnIndex = parser->errorReporter().columnAt(offset);
|
||||
ptrdiff_t colspan = ptrdiff_t(columnIndex) - ptrdiff_t(lastColumn_);
|
||||
ptrdiff_t colspan =
|
||||
ptrdiff_t(columnIndex) - ptrdiff_t(bytecodeSection().lastColumn());
|
||||
if (colspan != 0) {
|
||||
// If the column span is so large that we can't store it, then just
|
||||
// discard this information. This can happen with minimized or otherwise
|
||||
|
@ -579,20 +589,12 @@ bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) {
|
|||
if (!newSrcNote2(SRC_COLSPAN, SN_COLSPAN_TO_OFFSET(colspan))) {
|
||||
return false;
|
||||
}
|
||||
lastColumn_ = columnIndex;
|
||||
updateSeparatorPosition();
|
||||
bytecodeSection().setLastColumn(columnIndex);
|
||||
bytecodeSection().updateSeparatorPositionIfPresent();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Updates the last separator position, if present */
|
||||
void BytecodeEmitter::updateSeparatorPosition() {
|
||||
if (!inPrologue() && lastSeparatorOffet_ == code().length()) {
|
||||
lastSeparatorLine_ = currentLine_;
|
||||
lastSeparatorColumn_ = lastColumn_;
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<uint32_t> BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) {
|
||||
if (!nextpn) {
|
||||
return Nothing();
|
||||
|
@ -626,7 +628,7 @@ bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) {
|
|||
if (!emitN(op, 4, &off)) {
|
||||
return false;
|
||||
}
|
||||
SET_UINT32(code(off), operand);
|
||||
SET_UINT32(bytecodeSection().code(off), operand);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -663,17 +665,18 @@ class NonLocalExitControl {
|
|||
public:
|
||||
NonLocalExitControl(BytecodeEmitter* bce, Kind kind)
|
||||
: bce_(bce),
|
||||
savedScopeNoteIndex_(bce->scopeNoteList.length()),
|
||||
savedDepth_(bce->stackDepth),
|
||||
savedScopeNoteIndex_(bce->bytecodeSection().scopeNoteList().length()),
|
||||
savedDepth_(bce->bytecodeSection().stackDepth()),
|
||||
openScopeNoteIndex_(bce->innermostEmitterScope()->noteIndex()),
|
||||
kind_(kind) {}
|
||||
|
||||
~NonLocalExitControl() {
|
||||
for (uint32_t n = savedScopeNoteIndex_; n < bce_->scopeNoteList.length();
|
||||
n++) {
|
||||
bce_->scopeNoteList.recordEnd(n, bce_->offset());
|
||||
for (uint32_t n = savedScopeNoteIndex_;
|
||||
n < bce_->bytecodeSection().scopeNoteList().length(); n++) {
|
||||
bce_->bytecodeSection().scopeNoteList().recordEnd(
|
||||
n, bce_->bytecodeSection().offset());
|
||||
}
|
||||
bce_->stackDepth = savedDepth_;
|
||||
bce_->bytecodeSection().setStackDepth(savedDepth_);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool prepareForNonLocalJump(NestableControl* target);
|
||||
|
@ -695,11 +698,12 @@ bool NonLocalExitControl::leaveScope(EmitterScope* es) {
|
|||
if (es->enclosingInFrame()) {
|
||||
enclosingScopeIndex = es->enclosingInFrame()->index();
|
||||
}
|
||||
if (!bce_->scopeNoteList.append(enclosingScopeIndex, bce_->offset(),
|
||||
openScopeNoteIndex_)) {
|
||||
if (!bce_->bytecodeSection().scopeNoteList().append(
|
||||
enclosingScopeIndex, bce_->bytecodeSection().offset(),
|
||||
openScopeNoteIndex_)) {
|
||||
return false;
|
||||
}
|
||||
openScopeNoteIndex_ = bce_->scopeNoteList.length() - 1;
|
||||
openScopeNoteIndex_ = bce_->bytecodeSection().scopeNoteList().length() - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -838,7 +842,7 @@ bool NonLocalExitControl::prepareForNonLocalJump(NestableControl* target) {
|
|||
}
|
||||
|
||||
// Close FOR_OF_ITERCLOSE trynotes.
|
||||
ptrdiff_t end = bce_->offset();
|
||||
ptrdiff_t end = bce_->bytecodeSection().offset();
|
||||
for (ptrdiff_t start : forOfIterCloseScopeStarts) {
|
||||
if (!bce_->addTryNote(JSTRY_FOR_OF_ITERCLOSE, 0, start, end)) {
|
||||
return false;
|
||||
|
@ -884,10 +888,10 @@ bool BytecodeEmitter::emitIndex32(JSOp op, uint32_t index) {
|
|||
return false;
|
||||
}
|
||||
|
||||
jsbytecode* code = this->code(offset);
|
||||
jsbytecode* code = bytecodeSection().code(offset);
|
||||
code[0] = jsbytecode(op);
|
||||
SET_UINT32_INDEX(code, index);
|
||||
updateDepth(offset);
|
||||
bytecodeSection().updateDepth(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -902,10 +906,10 @@ bool BytecodeEmitter::emitIndexOp(JSOp op, uint32_t index) {
|
|||
return false;
|
||||
}
|
||||
|
||||
jsbytecode* code = this->code(offset);
|
||||
jsbytecode* code = bytecodeSection().code(offset);
|
||||
code[0] = jsbytecode(op);
|
||||
SET_UINT32_INDEX(code, index);
|
||||
updateDepth(offset);
|
||||
bytecodeSection().updateDepth(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -940,24 +944,24 @@ bool BytecodeEmitter::emitAtomOp(uint32_t atomIndex, JSOp op) {
|
|||
|
||||
bool BytecodeEmitter::emitInternedScopeOp(uint32_t index, JSOp op) {
|
||||
MOZ_ASSERT(JOF_OPTYPE(op) == JOF_SCOPE);
|
||||
MOZ_ASSERT(index < scopeList.length());
|
||||
MOZ_ASSERT(index < perScriptData().scopeList().length());
|
||||
return emitIndex32(op, index);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitInternedObjectOp(uint32_t index, JSOp op) {
|
||||
MOZ_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT);
|
||||
MOZ_ASSERT(index < objectList.length);
|
||||
MOZ_ASSERT(index < perScriptData().objectList().length);
|
||||
return emitIndex32(op, index);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitObjectOp(ObjectBox* objbox, JSOp op) {
|
||||
return emitInternedObjectOp(objectList.add(objbox), op);
|
||||
return emitInternedObjectOp(perScriptData().objectList().add(objbox), op);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitObjectPairOp(ObjectBox* objbox1, ObjectBox* objbox2,
|
||||
JSOp op) {
|
||||
uint32_t index = objectList.add(objbox1);
|
||||
objectList.add(objbox2);
|
||||
uint32_t index = perScriptData().objectList().add(objbox1);
|
||||
perScriptData().objectList().add(objbox2);
|
||||
return emitInternedObjectOp(index, op);
|
||||
}
|
||||
|
||||
|
@ -974,7 +978,7 @@ bool BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot) {
|
|||
return false;
|
||||
}
|
||||
|
||||
SET_LOCALNO(code(off), slot);
|
||||
SET_LOCALNO(bytecodeSection().code(off), slot);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -985,7 +989,7 @@ bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) {
|
|||
return false;
|
||||
}
|
||||
|
||||
SET_ARGNO(code(off), slot);
|
||||
SET_ARGNO(bytecodeSection().code(off), slot);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1000,7 +1004,7 @@ bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) {
|
|||
return false;
|
||||
}
|
||||
|
||||
jsbytecode* pc = code(off);
|
||||
jsbytecode* pc = bytecodeSection().code(off);
|
||||
SET_ENVCOORD_HOPS(pc, ec.hops());
|
||||
pc += ENVCOORD_HOPS_LEN;
|
||||
SET_ENVCOORD_SLOT(pc, ec.slot());
|
||||
|
@ -1680,13 +1684,13 @@ bool BytecodeEmitter::emitNewInit() {
|
|||
return false;
|
||||
}
|
||||
|
||||
jsbytecode* code = this->code(offset);
|
||||
jsbytecode* code = bytecodeSection().code(offset);
|
||||
code[0] = JSOP_NEWINIT;
|
||||
code[1] = 0;
|
||||
code[2] = 0;
|
||||
code[3] = 0;
|
||||
code[4] = 0;
|
||||
updateDepth(offset);
|
||||
bytecodeSection().updateDepth(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1716,7 +1720,7 @@ bool BytecodeEmitter::iteratorResultShape(unsigned* shape) {
|
|||
return false;
|
||||
}
|
||||
|
||||
*shape = objectList.add(objbox);
|
||||
*shape = perScriptData().objectList().add(objbox);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2017,10 +2021,10 @@ bool BytecodeEmitter::emitDouble(double d) {
|
|||
return false;
|
||||
}
|
||||
|
||||
jsbytecode* code = this->code(offset);
|
||||
jsbytecode* code = bytecodeSection().code(offset);
|
||||
code[0] = jsbytecode(JSOP_DOUBLE);
|
||||
SET_INLINE_VALUE(code, DoubleValue(d));
|
||||
updateDepth(offset);
|
||||
bytecodeSection().updateDepth(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2047,13 +2051,13 @@ bool BytecodeEmitter::emitNumberOp(double dval) {
|
|||
if (!emitN(JSOP_UINT24, 3, &off)) {
|
||||
return false;
|
||||
}
|
||||
SET_UINT24(code(off), u);
|
||||
SET_UINT24(bytecodeSection().code(off), u);
|
||||
} else {
|
||||
ptrdiff_t off;
|
||||
if (!emitN(JSOP_INT32, 4, &off)) {
|
||||
return false;
|
||||
}
|
||||
SET_INT32(code(off), ival);
|
||||
SET_INT32(bytecodeSection().code(off), ival);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -2254,13 +2258,13 @@ bool BytecodeEmitter::allocateResumeIndex(ptrdiff_t offset,
|
|||
"resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies "
|
||||
"on this when loading resume entries from BaselineScript");
|
||||
|
||||
*resumeIndex = resumeOffsetList.length();
|
||||
*resumeIndex = bytecodeSection().resumeOffsetList().length();
|
||||
if (*resumeIndex > MaxResumeIndex) {
|
||||
reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES);
|
||||
return false;
|
||||
}
|
||||
|
||||
return resumeOffsetList.append(offset);
|
||||
return bytecodeSection().resumeOffsetList().append(offset);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::allocateResumeIndexRange(mozilla::Span<ptrdiff_t> offsets,
|
||||
|
@ -2293,15 +2297,15 @@ bool BytecodeEmitter::emitYieldOp(JSOp op) {
|
|||
}
|
||||
|
||||
if (op == JSOP_INITIALYIELD || op == JSOP_YIELD) {
|
||||
numYields++;
|
||||
bytecodeSection().addNumYields();
|
||||
}
|
||||
|
||||
uint32_t resumeIndex;
|
||||
if (!allocateResumeIndex(offset(), &resumeIndex)) {
|
||||
if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SET_RESUMEINDEX(code(off), resumeIndex);
|
||||
SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
|
||||
|
||||
return emit1(JSOP_DEBUGAFTERYIELD);
|
||||
}
|
||||
|
@ -2569,7 +2573,7 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int depth = stackDepth;
|
||||
int depth = bytecodeSection().stackDepth();
|
||||
#endif
|
||||
|
||||
switch (target->getKind()) {
|
||||
|
@ -2647,7 +2651,7 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
|
|||
MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind");
|
||||
}
|
||||
|
||||
MOZ_ASSERT(stackDepth == depth + int(*emitted));
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() == depth + int(*emitted));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2810,7 +2814,7 @@ bool BytecodeEmitter::emitIteratorNext(
|
|||
"can run user-modifiable iteration code");
|
||||
|
||||
// [stack] ... NEXT ITER
|
||||
MOZ_ASSERT(this->stackDepth >= 2);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() >= 2);
|
||||
|
||||
if (!emitCall(JSOP_CALL, 0, callSourceCoordOffset)) {
|
||||
// [stack] ... RESULT
|
||||
|
@ -2833,7 +2837,7 @@ bool BytecodeEmitter::emitIteratorNext(
|
|||
|
||||
bool BytecodeEmitter::emitPushNotUndefinedOrNull() {
|
||||
// [stack] V
|
||||
MOZ_ASSERT(this->stackDepth > 0);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() > 0);
|
||||
|
||||
if (!emit1(JSOP_DUP)) {
|
||||
// [stack] V V
|
||||
|
@ -3081,7 +3085,7 @@ bool BytecodeEmitter::emitIteratorCloseInScope(
|
|||
template <typename InnerEmitter>
|
||||
bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth,
|
||||
InnerEmitter emitter) {
|
||||
MOZ_ASSERT(this->stackDepth >= iterDepth);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() >= iterDepth);
|
||||
|
||||
// Pad a nop at the beginning of the bytecode covered by the trynote so
|
||||
// that when unwinding environments, we may unwind to the scope
|
||||
|
@ -3092,11 +3096,11 @@ bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth,
|
|||
return false;
|
||||
}
|
||||
|
||||
ptrdiff_t start = offset();
|
||||
ptrdiff_t start = bytecodeSection().offset();
|
||||
if (!emitter(this)) {
|
||||
return false;
|
||||
}
|
||||
ptrdiff_t end = offset();
|
||||
ptrdiff_t end = bytecodeSection().offset();
|
||||
if (start != end) {
|
||||
return addTryNote(JSTRY_DESTRUCTURING, iterDepth, start, end);
|
||||
}
|
||||
|
@ -3202,7 +3206,7 @@ bool BytecodeEmitter::emitInitializer(ParseNode* initializer,
|
|||
bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
|
||||
DestructuringFlavor flav) {
|
||||
MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr));
|
||||
MOZ_ASSERT(this->stackDepth != 0);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() != 0);
|
||||
|
||||
// Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
|
||||
//
|
||||
|
@ -3326,7 +3330,7 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
|
|||
// JSTRY_DESTRUCTURING expects the iterator and the done value
|
||||
// to be the second to top and the top of the stack, respectively.
|
||||
// IteratorClose is called upon exception only if done is false.
|
||||
int32_t tryNoteDepth = stackDepth;
|
||||
int32_t tryNoteDepth = bytecodeSection().stackDepth();
|
||||
|
||||
for (ParseNode* member : pattern->contents()) {
|
||||
bool isFirst = member == pattern->head();
|
||||
|
@ -3635,7 +3639,7 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
|
|||
MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr));
|
||||
|
||||
// [stack] ... RHS
|
||||
MOZ_ASSERT(this->stackDepth > 0);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() > 0);
|
||||
|
||||
if (!emit1(JSOP_CHECKOBJCOERCIBLE)) {
|
||||
// [stack] ... RHS
|
||||
|
@ -3815,7 +3819,7 @@ bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) {
|
|||
MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr));
|
||||
MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::Spread));
|
||||
|
||||
ptrdiff_t offset = this->offset();
|
||||
ptrdiff_t offset = bytecodeSection().offset();
|
||||
if (!emitNewInit()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -4690,11 +4694,11 @@ MOZ_MUST_USE bool BytecodeEmitter::emitGoSub(JumpList* jump) {
|
|||
}
|
||||
|
||||
uint32_t resumeIndex;
|
||||
if (!allocateResumeIndex(offset(), &resumeIndex)) {
|
||||
if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SET_RESUMEINDEX(code(off), resumeIndex);
|
||||
SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4899,7 +4903,7 @@ bool BytecodeEmitter::emitWith(BinaryNode* withNode) {
|
|||
}
|
||||
|
||||
bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) {
|
||||
DebugOnly<int32_t> depth = this->stackDepth;
|
||||
DebugOnly<int32_t> depth = bytecodeSection().stackDepth();
|
||||
|
||||
uint32_t argc;
|
||||
if (option == CopyOption::Filtered) {
|
||||
|
@ -4954,15 +4958,15 @@ bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) {
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(depth - int(argc) == this->stackDepth);
|
||||
MOZ_ASSERT(depth - int(argc) == bytecodeSection().stackDepth());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitBigIntOp(BigInt* bigint) {
|
||||
if (!numberList.append(BigIntValue(bigint))) {
|
||||
if (!perScriptData().numberList().append(BigIntValue(bigint))) {
|
||||
return false;
|
||||
}
|
||||
return emitIndex32(JSOP_BIGINT, numberList.length() - 1);
|
||||
return emitIndex32(JSOP_BIGINT, perScriptData().numberList().length() - 1);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitIterator() {
|
||||
|
@ -5145,11 +5149,11 @@ bool BytecodeEmitter::emitSpread(bool allowSelfHosted) {
|
|||
// when we reach this point on the loop backedge (if spreading produces at
|
||||
// least one value), we've additionally pushed a RESULT iteration value.
|
||||
// Increment manually to reflect this.
|
||||
this->stackDepth++;
|
||||
bytecodeSection().setStackDepth(bytecodeSection().stackDepth() + 1);
|
||||
|
||||
{
|
||||
#ifdef DEBUG
|
||||
auto loopDepth = this->stackDepth;
|
||||
auto loopDepth = bytecodeSection().stackDepth();
|
||||
#endif
|
||||
|
||||
// Emit code to assign result.value to the iteration variable.
|
||||
|
@ -5162,7 +5166,7 @@ bool BytecodeEmitter::emitSpread(bool allowSelfHosted) {
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(this->stackDepth == loopDepth - 1);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() == loopDepth - 1);
|
||||
|
||||
// Spread operations can't contain |continue|, so don't bother setting loop
|
||||
// and enclosing "update" offsets, as we do with for-loops.
|
||||
|
@ -5199,7 +5203,7 @@ bool BytecodeEmitter::emitSpread(bool allowSelfHosted) {
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(this->stackDepth == loopDepth);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() == loopDepth);
|
||||
}
|
||||
|
||||
// Let Ion know where the closing jump of this loop is.
|
||||
|
@ -5212,8 +5216,8 @@ bool BytecodeEmitter::emitSpread(bool allowSelfHosted) {
|
|||
MOZ_ASSERT(loopInfo.breaks.offset == -1);
|
||||
MOZ_ASSERT(loopInfo.continues.offset == -1);
|
||||
|
||||
if (!addTryNote(JSTRY_FOR_OF, stackDepth, loopInfo.headOffset(),
|
||||
loopInfo.breakTargetOffset())) {
|
||||
if (!addTryNote(JSTRY_FOR_OF, bytecodeSection().stackDepth(),
|
||||
loopInfo.headOffset(), loopInfo.breakTargetOffset())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5234,7 +5238,7 @@ bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
|
|||
MOZ_ASSERT(forHead->isKind(ParseNodeKind::ForIn) ||
|
||||
forHead->isKind(ParseNodeKind::ForOf));
|
||||
|
||||
MOZ_ASSERT(this->stackDepth >= 1,
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() >= 1,
|
||||
"must have a per-iteration value for initializing");
|
||||
|
||||
ParseNode* target = forHead->kid1();
|
||||
|
@ -5282,14 +5286,14 @@ bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
|
|||
// iteration value *before* initializing. Thus the initializing
|
||||
// value may be buried under a bind-specific value on the stack.
|
||||
// Swap it to the top of the stack.
|
||||
MOZ_ASSERT(stackDepth >= 2);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() >= 2);
|
||||
if (!emit1(JSOP_SWAP)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// In cases of emitting a frame slot or environment slot,
|
||||
// nothing needs be done.
|
||||
MOZ_ASSERT(stackDepth >= 1);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() >= 1);
|
||||
}
|
||||
if (!noe.emitAssignment()) {
|
||||
return false;
|
||||
|
@ -5967,7 +5971,7 @@ bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) {
|
|||
* In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
|
||||
* extra JSOP_RETRVAL after the fixups.
|
||||
*/
|
||||
ptrdiff_t top = offset();
|
||||
ptrdiff_t top = bytecodeSection().offset();
|
||||
|
||||
bool needsFinalYield =
|
||||
sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
|
||||
|
@ -6028,12 +6032,13 @@ bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) {
|
|||
return false;
|
||||
}
|
||||
} else if (isDerivedClassConstructor) {
|
||||
MOZ_ASSERT(code()[top] == JSOP_SETRVAL);
|
||||
MOZ_ASSERT(bytecodeSection().code()[top] == JSOP_SETRVAL);
|
||||
if (!emit1(JSOP_RETRVAL)) {
|
||||
return false;
|
||||
}
|
||||
} else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) != offset()) {
|
||||
code()[top] = JSOP_SETRVAL;
|
||||
} else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) !=
|
||||
bytecodeSection().offset()) {
|
||||
bytecodeSection().code()[top] = JSOP_SETRVAL;
|
||||
if (!emit1(JSOP_RETRVAL)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -6213,7 +6218,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
|
|||
}
|
||||
|
||||
int32_t savedDepthTemp;
|
||||
int32_t startDepth = stackDepth;
|
||||
int32_t startDepth = bytecodeSection().stackDepth();
|
||||
MOZ_ASSERT(startDepth >= 3);
|
||||
|
||||
TryEmitter tryCatch(this, TryEmitter::Kind::TryCatchFinally,
|
||||
|
@ -6245,7 +6250,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(this->stackDepth == startDepth);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
|
||||
|
||||
// Step 7.a.vi.
|
||||
// Step 7.b.ii.7.
|
||||
|
@ -6278,7 +6283,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(stackDepth == startDepth);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
|
||||
|
||||
if (!emit1(JSOP_EXCEPTION)) {
|
||||
// [stack] NEXT ITER RESULT EXCEPTION
|
||||
|
@ -6297,7 +6302,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
|
|||
return false;
|
||||
}
|
||||
|
||||
savedDepthTemp = stackDepth;
|
||||
savedDepthTemp = bytecodeSection().stackDepth();
|
||||
InternalIfEmitter ifThrowMethodIsNotDefined(this);
|
||||
if (!emitPushNotUndefinedOrNull()) {
|
||||
// [stack] NEXT ITER RESULT EXCEPTION ITER THROW
|
||||
|
@ -6348,7 +6353,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
|
|||
// [stack] NEXT ITER RESULT
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(this->stackDepth == startDepth);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
|
||||
|
||||
JumpList checkResult;
|
||||
// Note that there is no GOSUB to the finally block here. If the iterator has
|
||||
|
@ -6359,7 +6364,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
|
|||
return false;
|
||||
}
|
||||
|
||||
stackDepth = savedDepthTemp;
|
||||
bytecodeSection().setStackDepth(savedDepthTemp);
|
||||
if (!ifThrowMethodIsNotDefined.emitElse()) {
|
||||
// [stack] NEXT ITER RESULT EXCEPTION ITER THROW
|
||||
return false;
|
||||
|
@ -6384,12 +6389,12 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
|
|||
return false;
|
||||
}
|
||||
|
||||
stackDepth = savedDepthTemp;
|
||||
bytecodeSection().setStackDepth(savedDepthTemp);
|
||||
if (!ifThrowMethodIsNotDefined.emitEnd()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
stackDepth = startDepth;
|
||||
bytecodeSection().setStackDepth(startDepth);
|
||||
if (!tryCatch.emitFinally()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -6516,7 +6521,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
|
|||
// [stack] NEXT ITER OLDRESULT FTYPE FVALUE
|
||||
return false;
|
||||
}
|
||||
savedDepthTemp = this->stackDepth;
|
||||
savedDepthTemp = bytecodeSection().stackDepth();
|
||||
if (!ifReturnDone.emitElse()) {
|
||||
// [stack] NEXT ITER OLDRESULT FTYPE FVALUE RESULT
|
||||
return false;
|
||||
|
@ -6538,7 +6543,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
this->stackDepth = savedDepthTemp;
|
||||
bytecodeSection().setStackDepth(savedDepthTemp);
|
||||
if (!ifReturnDone.emitEnd()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -6613,7 +6618,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
|
|||
// [stack] NEXT ITER RESULT
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(this->stackDepth == startDepth);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
|
||||
|
||||
// Steps 7.a.iv-v.
|
||||
// Steps 7.b.ii.5-6.
|
||||
|
@ -6658,7 +6663,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(this->stackDepth == startDepth - 2);
|
||||
MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth - 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -6707,7 +6712,7 @@ bool BytecodeEmitter::emitExpressionStatement(UnaryNode* exprStmt) {
|
|||
if (innermostNestableControl &&
|
||||
innermostNestableControl->is<LabelControl>() &&
|
||||
innermostNestableControl->as<LabelControl>().startOffset() >=
|
||||
offset()) {
|
||||
bytecodeSection().offset()) {
|
||||
useful = true;
|
||||
}
|
||||
}
|
||||
|
@ -8182,8 +8187,8 @@ bool BytecodeEmitter::replaceNewInitWithNewObject(JSObject* obj,
|
|||
JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
|
||||
"newinit and newobject must have equal length to edit in-place");
|
||||
|
||||
uint32_t index = objectList.add(objbox);
|
||||
jsbytecode* code = this->code(offset);
|
||||
uint32_t index = perScriptData().objectList().add(objbox);
|
||||
jsbytecode* code = bytecodeSection().code(offset);
|
||||
|
||||
MOZ_ASSERT(code[0] == JSOP_NEWINIT);
|
||||
code[0] = JSOP_NEWOBJECT;
|
||||
|
@ -9233,7 +9238,8 @@ bool BytecodeEmitter::emitTree(
|
|||
break;
|
||||
|
||||
case ParseNodeKind::RegExpExpr:
|
||||
if (!emitRegExp(objectList.add(pn->as<RegExpLiteral>().objbox()))) {
|
||||
if (!emitRegExp(perScriptData().objectList().add(
|
||||
pn->as<RegExpLiteral>().objbox()))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -9334,11 +9340,13 @@ static bool AllocSrcNote(JSContext* cx, SrcNotesVector& notes,
|
|||
bool BytecodeEmitter::addTryNote(JSTryNoteKind kind, uint32_t stackDepth,
|
||||
size_t start, size_t end) {
|
||||
MOZ_ASSERT(!inPrologue());
|
||||
return tryNoteList.append(kind, stackDepth, start, end);
|
||||
return bytecodeSection().tryNoteList().append(kind, stackDepth, start, end);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) {
|
||||
SrcNotesVector& notes = this->notes();
|
||||
// Prologue shouldn't have source notes.
|
||||
MOZ_ASSERT(!inPrologue());
|
||||
SrcNotesVector& notes = bytecodeSection().notes();
|
||||
unsigned index;
|
||||
if (!AllocSrcNote(cx, notes, &index)) {
|
||||
return false;
|
||||
|
@ -9348,9 +9356,9 @@ bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) {
|
|||
* Compute delta from the last annotated bytecode's offset. If it's too
|
||||
* big to fit in sn, allocate one or more xdelta notes and reset sn.
|
||||
*/
|
||||
ptrdiff_t offset = this->offset();
|
||||
ptrdiff_t delta = offset - lastNoteOffset();
|
||||
lastNoteOffset_ = offset;
|
||||
ptrdiff_t offset = bytecodeSection().offset();
|
||||
ptrdiff_t delta = offset - bytecodeSection().lastNoteOffset();
|
||||
bytecodeSection().setLastNoteOffset(offset);
|
||||
if (delta >= SN_DELTA_LIMIT) {
|
||||
do {
|
||||
ptrdiff_t xdelta = Min(delta, SN_XDELTA_MASK);
|
||||
|
@ -9420,7 +9428,7 @@ bool BytecodeEmitter::setSrcNoteOffset(unsigned index, unsigned which,
|
|||
return false;
|
||||
}
|
||||
|
||||
SrcNotesVector& notes = this->notes();
|
||||
SrcNotesVector& notes = bytecodeSection().notes();
|
||||
|
||||
/* Find the offset numbered which (i.e., skip exactly which offsets). */
|
||||
jssrcnote* sn = ¬es[index];
|
||||
|
@ -9458,10 +9466,10 @@ bool BytecodeEmitter::setSrcNoteOffset(unsigned index, unsigned which,
|
|||
}
|
||||
|
||||
void BytecodeEmitter::copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes) {
|
||||
unsigned count = notes_.length();
|
||||
unsigned count = bytecodeSection().notes().length();
|
||||
// nsrcnotes includes SN_MAKE_TERMINATOR in addition to the srcnotes.
|
||||
MOZ_ASSERT(nsrcnotes == count + 1);
|
||||
PodCopy(destination, notes_.begin(), count);
|
||||
PodCopy(destination, bytecodeSection().notes().begin(), count);
|
||||
SN_MAKE_TERMINATOR(&destination[count]);
|
||||
}
|
||||
|
||||
|
|
|
@ -124,29 +124,249 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
Rooted<LazyScript*> lazyScript;
|
||||
|
||||
private:
|
||||
BytecodeVector code_; /* bytecode */
|
||||
SrcNotesVector notes_; /* source notes, see below */
|
||||
// Bytecode and all data directly associated with specific opcode/index inside
|
||||
// bytecode is stored in this class.
|
||||
class BytecodeSection {
|
||||
public:
|
||||
BytecodeSection(JSContext* cx, uint32_t lineNum);
|
||||
|
||||
// Code offset for last source note
|
||||
ptrdiff_t lastNoteOffset_ = 0;
|
||||
// ---- Bytecode ----
|
||||
|
||||
// Line number for srcnotes.
|
||||
//
|
||||
// WARNING: If this becomes out of sync with already-emitted srcnotes,
|
||||
// we can get undefined behavior.
|
||||
uint32_t currentLine_ = 0;
|
||||
BytecodeVector& code() { return code_; }
|
||||
const BytecodeVector& code() const { return code_; }
|
||||
|
||||
// Zero-based column index on currentLine of last SRC_COLSPAN-annotated
|
||||
// opcode.
|
||||
//
|
||||
// WARNING: If this becomes out of sync with already-emitted srcnotes,
|
||||
// we can get undefined behavior.
|
||||
uint32_t lastColumn_ = 0;
|
||||
jsbytecode* code(ptrdiff_t offset) { return code_.begin() + offset; }
|
||||
ptrdiff_t offset() const { return code_.end() - code_.begin(); }
|
||||
|
||||
uint32_t lastSeparatorOffet_ = 0;
|
||||
uint32_t lastSeparatorLine_ = 0;
|
||||
uint32_t lastSeparatorColumn_ = 0;
|
||||
// ---- Source notes ----
|
||||
|
||||
SrcNotesVector& notes() { return notes_; }
|
||||
const SrcNotesVector& notes() const { return notes_; }
|
||||
|
||||
ptrdiff_t lastNoteOffset() const { return lastNoteOffset_; }
|
||||
void setLastNoteOffset(ptrdiff_t offset) { lastNoteOffset_ = offset; }
|
||||
|
||||
// ---- Jump ----
|
||||
|
||||
ptrdiff_t lastTargetOffset() const { return lastTarget_.offset; }
|
||||
void setLastTargetOffset(ptrdiff_t offset) { lastTarget_.offset = offset; }
|
||||
|
||||
// Check if the last emitted opcode is a jump target.
|
||||
bool lastOpcodeIsJumpTarget() const {
|
||||
return offset() - lastTarget_.offset == ptrdiff_t(JSOP_JUMPTARGET_LENGTH);
|
||||
}
|
||||
|
||||
// JumpTarget should not be part of the emitted statement, as they can be
|
||||
// aliased by multiple statements. If we included the jump target as part of
|
||||
// the statement we might have issues where the enclosing statement might
|
||||
// not contain all the opcodes of the enclosed statements.
|
||||
ptrdiff_t lastNonJumpTargetOffset() const {
|
||||
return lastOpcodeIsJumpTarget() ? lastTarget_.offset : offset();
|
||||
}
|
||||
|
||||
// ---- Stack ----
|
||||
|
||||
int32_t stackDepth() const { return stackDepth_; }
|
||||
void setStackDepth(int32_t depth) { stackDepth_ = depth; }
|
||||
|
||||
uint32_t maxStackDepth() const { return maxStackDepth_; }
|
||||
|
||||
void updateDepth(ptrdiff_t target);
|
||||
|
||||
// ---- Try notes ----
|
||||
|
||||
CGTryNoteList& tryNoteList() { return tryNoteList_; };
|
||||
const CGTryNoteList& tryNoteList() const { return tryNoteList_; };
|
||||
|
||||
// ---- Scope ----
|
||||
|
||||
CGScopeNoteList& scopeNoteList() { return scopeNoteList_; };
|
||||
const CGScopeNoteList& scopeNoteList() const { return scopeNoteList_; };
|
||||
|
||||
// ---- Generator ----
|
||||
|
||||
CGResumeOffsetList& resumeOffsetList() { return resumeOffsetList_; }
|
||||
const CGResumeOffsetList& resumeOffsetList() const {
|
||||
return resumeOffsetList_;
|
||||
}
|
||||
|
||||
uint32_t numYields() const { return numYields_; }
|
||||
void addNumYields() { numYields_++; }
|
||||
|
||||
// ---- Line and column ----
|
||||
|
||||
uint32_t currentLine() const { return currentLine_; }
|
||||
uint32_t lastColumn() const { return lastColumn_; }
|
||||
void setCurrentLine(uint32_t line) {
|
||||
currentLine_ = line;
|
||||
lastColumn_ = 0;
|
||||
}
|
||||
void setLastColumn(uint32_t column) { lastColumn_ = column; }
|
||||
|
||||
void updateSeparatorPosition() {
|
||||
lastSeparatorOffet_ = code().length();
|
||||
lastSeparatorLine_ = currentLine_;
|
||||
lastSeparatorColumn_ = lastColumn_;
|
||||
}
|
||||
|
||||
void updateSeparatorPositionIfPresent() {
|
||||
if (lastSeparatorOffet_ == code().length()) {
|
||||
lastSeparatorLine_ = currentLine_;
|
||||
lastSeparatorColumn_ = lastColumn_;
|
||||
}
|
||||
}
|
||||
|
||||
bool isDuplicateLocation() const {
|
||||
return lastSeparatorLine_ == currentLine_ &&
|
||||
lastSeparatorColumn_ == lastColumn_;
|
||||
}
|
||||
|
||||
// ---- JIT ----
|
||||
|
||||
size_t numICEntries() const { return numICEntries_; }
|
||||
void addNumICEntries() { numICEntries_++; }
|
||||
void setNumICEntries(size_t entries) { numICEntries_ = entries; }
|
||||
|
||||
uint16_t typesetCount() const { return typesetCount_; }
|
||||
void addTypesetCount() { typesetCount_++; }
|
||||
|
||||
private:
|
||||
// ---- Bytecode ----
|
||||
|
||||
// Bytecode.
|
||||
BytecodeVector code_;
|
||||
|
||||
// ---- Source notes ----
|
||||
|
||||
// Source notes
|
||||
SrcNotesVector notes_;
|
||||
|
||||
// Code offset for last source note
|
||||
ptrdiff_t lastNoteOffset_ = 0;
|
||||
|
||||
// ---- Jump ----
|
||||
|
||||
// Last jump target emitted.
|
||||
JumpTarget lastTarget_ = {-1 - ptrdiff_t(JSOP_JUMPTARGET_LENGTH)};
|
||||
|
||||
// ---- Stack ----
|
||||
|
||||
// Maximum number of expression stack slots so far.
|
||||
uint32_t maxStackDepth_ = 0;
|
||||
|
||||
// Current stack depth in script frame.
|
||||
int32_t stackDepth_ = 0;
|
||||
|
||||
// ---- Try notes ----
|
||||
|
||||
// List of emitted try notes.
|
||||
CGTryNoteList tryNoteList_;
|
||||
|
||||
// ---- Scope ----
|
||||
|
||||
// List of emitted block scope notes.
|
||||
CGScopeNoteList scopeNoteList_;
|
||||
|
||||
// ---- Generator ----
|
||||
|
||||
// Certain ops (yield, await, gosub) have an entry in the script's
|
||||
// resumeOffsets list. This can be used to map from the op's resumeIndex to
|
||||
// the bytecode offset of the next pc. This indirection makes it easy to
|
||||
// resume in the JIT (because BaselineScript stores a resumeIndex => native
|
||||
// code array).
|
||||
CGResumeOffsetList resumeOffsetList_;
|
||||
|
||||
// Number of yield instructions emitted. Does not include JSOP_AWAIT.
|
||||
uint32_t numYields_ = 0;
|
||||
|
||||
// ---- Line and column ----
|
||||
|
||||
// Line number for srcnotes.
|
||||
//
|
||||
// WARNING: If this becomes out of sync with already-emitted srcnotes,
|
||||
// we can get undefined behavior.
|
||||
uint32_t currentLine_;
|
||||
|
||||
// Zero-based column index on currentLine_ of last SRC_COLSPAN-annotated
|
||||
// opcode.
|
||||
//
|
||||
// WARNING: If this becomes out of sync with already-emitted srcnotes,
|
||||
// we can get undefined behavior.
|
||||
uint32_t lastColumn_ = 0;
|
||||
|
||||
// The offset, line and column numbers of the last opcode for the
|
||||
// breakpoint for step execution.
|
||||
uint32_t lastSeparatorOffet_ = 0;
|
||||
uint32_t lastSeparatorLine_ = 0;
|
||||
uint32_t lastSeparatorColumn_ = 0;
|
||||
|
||||
// ---- JIT ----
|
||||
|
||||
// Number of JOF_IC opcodes emitted.
|
||||
size_t numICEntries_ = 0;
|
||||
|
||||
// Number of JOF_TYPESET opcodes generated.
|
||||
uint16_t typesetCount_ = 0;
|
||||
};
|
||||
|
||||
BytecodeSection bytecodeSection_;
|
||||
|
||||
public:
|
||||
BytecodeSection& bytecodeSection() { return bytecodeSection_; }
|
||||
const BytecodeSection& bytecodeSection() const { return bytecodeSection_; }
|
||||
|
||||
private:
|
||||
// Data that is not directly associated with specific opcode/index inside
|
||||
// bytecode, but referred from bytecode is stored in this class.
|
||||
class PerScriptData {
|
||||
public:
|
||||
explicit PerScriptData(JSContext* cx);
|
||||
|
||||
MOZ_MUST_USE bool init(JSContext* cx);
|
||||
|
||||
// ---- Scope ----
|
||||
|
||||
CGScopeList& scopeList() { return scopeList_; }
|
||||
const CGScopeList& scopeList() const { return scopeList_; }
|
||||
|
||||
// ---- Literals ----
|
||||
|
||||
CGNumberList& numberList() { return numberList_; }
|
||||
const CGNumberList& numberList() const { return numberList_; }
|
||||
|
||||
CGObjectList& objectList() { return objectList_; }
|
||||
const CGObjectList& objectList() const { return objectList_; }
|
||||
|
||||
PooledMapPtr<AtomIndexMap>& atomIndices() { return atomIndices_; }
|
||||
const PooledMapPtr<AtomIndexMap>& atomIndices() const {
|
||||
return atomIndices_;
|
||||
}
|
||||
|
||||
private:
|
||||
// ---- Scope ----
|
||||
|
||||
// List of emitted scopes.
|
||||
CGScopeList scopeList_;
|
||||
|
||||
// ---- Literals ----
|
||||
|
||||
// List of double and bigint values used by script.
|
||||
CGNumberList numberList_;
|
||||
|
||||
// List of emitted objects.
|
||||
CGObjectList objectList_;
|
||||
|
||||
// Map from atom to index.
|
||||
PooledMapPtr<AtomIndexMap> atomIndices_;
|
||||
};
|
||||
|
||||
PerScriptData perScriptData_;
|
||||
|
||||
public:
|
||||
PerScriptData& perScriptData() { return perScriptData_; }
|
||||
const PerScriptData& perScriptData() const { return perScriptData_; }
|
||||
|
||||
private:
|
||||
// switchToMain sets this to the bytecode offset of the main section.
|
||||
mozilla::Maybe<uint32_t> mainOffset_ = {};
|
||||
|
||||
|
@ -154,22 +374,14 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
const FieldInitializers fieldInitializers_;
|
||||
|
||||
public:
|
||||
// Last jump target emitted.
|
||||
JumpTarget lastTarget = {-1 - ptrdiff_t(JSOP_JUMPTARGET_LENGTH)};
|
||||
|
||||
// Private storage for parser wrapper. DO NOT REFERENCE INTERNALLY. May not be
|
||||
// initialized. Use |parser| instead.
|
||||
mozilla::Maybe<EitherParser> ep_ = {};
|
||||
BCEParserHandle* parser = nullptr;
|
||||
|
||||
PooledMapPtr<AtomIndexMap> atomIndices; /* literals indexed for mapping */
|
||||
unsigned firstLine = 0; /* first line, for JSScript::initFromEmitter */
|
||||
|
||||
uint32_t maxFixedSlots = 0; /* maximum number of fixed frame slots so far */
|
||||
uint32_t maxStackDepth =
|
||||
0; /* maximum number of expression stack slots so far */
|
||||
|
||||
int32_t stackDepth = 0; /* current stack depth in script frame */
|
||||
|
||||
uint32_t bodyScopeIndex =
|
||||
UINT32_MAX; /* index into scopeList of the body scope */
|
||||
|
@ -195,28 +407,6 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
return innermostEmitterScope_;
|
||||
}
|
||||
|
||||
CGNumberList numberList; /* double and bigint values used by script */
|
||||
CGObjectList objectList; /* list of emitted objects */
|
||||
CGScopeList scopeList; /* list of emitted scopes */
|
||||
CGTryNoteList tryNoteList; /* list of emitted try notes */
|
||||
CGScopeNoteList scopeNoteList; /* list of emitted block scope notes */
|
||||
|
||||
// Certain ops (yield, await, gosub) have an entry in the script's
|
||||
// resumeOffsets list. This can be used to map from the op's resumeIndex to
|
||||
// the bytecode offset of the next pc. This indirection makes it easy to
|
||||
// resume in the JIT (because BaselineScript stores a resumeIndex => native
|
||||
// code array).
|
||||
CGResumeOffsetList resumeOffsetList;
|
||||
|
||||
// Number of JOF_IC opcodes emitted.
|
||||
size_t numICEntries = 0;
|
||||
|
||||
// Number of yield instructions emitted. Does not include JSOP_AWAIT.
|
||||
uint32_t numYields = 0;
|
||||
|
||||
// Number of JOF_TYPESET opcodes generated.
|
||||
uint16_t typesetCount = 0;
|
||||
|
||||
// Script contains singleton initializer JSOP_OBJECT.
|
||||
bool hasSingletons = false;
|
||||
|
||||
|
@ -360,24 +550,26 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
varEmitterScope = emitterScope;
|
||||
}
|
||||
|
||||
Scope* outermostScope() const { return scopeList.vector[0]; }
|
||||
Scope* outermostScope() const {
|
||||
return perScriptData().scopeList().vector[0];
|
||||
}
|
||||
Scope* innermostScope() const;
|
||||
Scope* bodyScope() const {
|
||||
MOZ_ASSERT(bodyScopeIndex < scopeList.length());
|
||||
return scopeList.vector[bodyScopeIndex];
|
||||
MOZ_ASSERT(bodyScopeIndex < perScriptData().scopeList().length());
|
||||
return perScriptData().scopeList().vector[bodyScopeIndex];
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE
|
||||
MOZ_MUST_USE bool makeAtomIndex(JSAtom* atom, uint32_t* indexp) {
|
||||
MOZ_ASSERT(atomIndices);
|
||||
AtomIndexMap::AddPtr p = atomIndices->lookupForAdd(atom);
|
||||
MOZ_ASSERT(perScriptData().atomIndices());
|
||||
AtomIndexMap::AddPtr p = perScriptData().atomIndices()->lookupForAdd(atom);
|
||||
if (p) {
|
||||
*indexp = p->value();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t index = atomIndices->count();
|
||||
if (!atomIndices->add(p, atom, index)) {
|
||||
uint32_t index = perScriptData().atomIndices()->count();
|
||||
if (!perScriptData().atomIndices()->add(p, atom, index)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
@ -400,45 +592,13 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
|
||||
void tellDebuggerAboutCompiledScript(JSContext* cx);
|
||||
|
||||
BytecodeVector& code() { return code_; }
|
||||
const BytecodeVector& code() const { return code_; }
|
||||
|
||||
jsbytecode* code(ptrdiff_t offset) { return code_.begin() + offset; }
|
||||
ptrdiff_t offset() const { return code_.end() - code_.begin(); }
|
||||
|
||||
uint32_t mainOffset() const { return *mainOffset_; }
|
||||
|
||||
bool inPrologue() const { return mainOffset_.isNothing(); }
|
||||
|
||||
void switchToMain() {
|
||||
MOZ_ASSERT(inPrologue());
|
||||
mainOffset_.emplace(code_.length());
|
||||
}
|
||||
|
||||
SrcNotesVector& notes() {
|
||||
// Prologue shouldn't have source notes.
|
||||
MOZ_ASSERT(!inPrologue());
|
||||
return notes_;
|
||||
}
|
||||
ptrdiff_t lastNoteOffset() const { return lastNoteOffset_; }
|
||||
unsigned currentLine() const { return currentLine_; }
|
||||
|
||||
void setCurrentLine(uint32_t line) {
|
||||
currentLine_ = line;
|
||||
lastColumn_ = 0;
|
||||
}
|
||||
|
||||
// Check if the last emitted opcode is a jump target.
|
||||
bool lastOpcodeIsJumpTarget() const {
|
||||
return offset() - lastTarget.offset == ptrdiff_t(JSOP_JUMPTARGET_LENGTH);
|
||||
}
|
||||
|
||||
// JumpTarget should not be part of the emitted statement, as they can be
|
||||
// aliased by multiple statements. If we included the jump target as part of
|
||||
// the statement we might have issues where the enclosing statement might
|
||||
// not contain all the opcodes of the enclosed statements.
|
||||
ptrdiff_t lastNonJumpTargetOffset() const {
|
||||
return lastOpcodeIsJumpTarget() ? lastTarget.offset : offset();
|
||||
mainOffset_.emplace(bytecodeSection().code().length());
|
||||
}
|
||||
|
||||
void setFunctionBodyEndPos(uint32_t pos) {
|
||||
|
@ -509,12 +669,10 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
MOZ_MUST_USE bool emitFunctionScript(FunctionNode* funNode,
|
||||
TopLevelFunction isTopLevel);
|
||||
|
||||
void updateDepth(ptrdiff_t target);
|
||||
MOZ_MUST_USE bool markStepBreakpoint();
|
||||
MOZ_MUST_USE bool markSimpleBreakpoint();
|
||||
MOZ_MUST_USE bool updateLineNumberNotes(uint32_t offset);
|
||||
MOZ_MUST_USE bool updateSourceCoordNotes(uint32_t offset);
|
||||
void updateSeparatorPosition();
|
||||
|
||||
JSOp strictifySetNameOp(JSOp op);
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ bool CForEmitter::emitBody(Cond cond, const Maybe<uint32_t>& bodyPos) {
|
|||
return false;
|
||||
}
|
||||
|
||||
biasedTop_ = bce_->offset();
|
||||
biasedTop_ = bce_->bytecodeSection().offset();
|
||||
|
||||
if (cond_ == Cond::Present) {
|
||||
// Goto the loop condition, which branches back to iterate.
|
||||
|
@ -163,11 +163,11 @@ bool CForEmitter::emitCond(const Maybe<uint32_t>& forPos,
|
|||
// Restore the absolute line number for source note readers.
|
||||
if (endPos) {
|
||||
uint32_t lineNum = bce_->parser->errorReporter().lineAt(*endPos);
|
||||
if (bce_->currentLine() != lineNum) {
|
||||
if (bce_->bytecodeSection().currentLine() != lineNum) {
|
||||
if (!bce_->newSrcNote2(SRC_SETLINE, ptrdiff_t(lineNum))) {
|
||||
return false;
|
||||
}
|
||||
bce_->setCurrentLine(lineNum);
|
||||
bce_->bytecodeSection().setCurrentLine(lineNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ bool CForEmitter::emitCond(const Maybe<uint32_t>& forPos,
|
|||
tdzCache_.reset();
|
||||
}
|
||||
|
||||
condOffset_ = bce_->offset();
|
||||
condOffset_ = bce_->bytecodeSection().offset();
|
||||
|
||||
if (cond_ == Cond::Present) {
|
||||
if (!loopInfo_->emitLoopEntry(bce_, condPos)) {
|
||||
|
@ -228,7 +228,8 @@ bool CForEmitter::emitEnd() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
if (!bce_->addTryNote(JSTRY_LOOP, bce_->bytecodeSection().stackDepth(),
|
||||
loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset())) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -75,7 +75,8 @@ bool DoWhileEmitter::emitEnd() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
if (!bce_->addTryNote(JSTRY_LOOP, bce_->bytecodeSection().stackDepth(),
|
||||
loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset())) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -342,8 +342,8 @@ bool EmitterScope::internScope(BytecodeEmitter* bce, ScopeCreator createScope) {
|
|||
return false;
|
||||
}
|
||||
hasEnvironment_ = scope->hasEnvironment();
|
||||
scopeIndex_ = bce->scopeList.length();
|
||||
return bce->scopeList.append(scope);
|
||||
scopeIndex_ = bce->perScriptData().scopeList().length();
|
||||
return bce->perScriptData().scopeList().append(scope);
|
||||
}
|
||||
|
||||
template <typename ScopeCreator>
|
||||
|
@ -351,18 +351,18 @@ bool EmitterScope::internBodyScope(BytecodeEmitter* bce,
|
|||
ScopeCreator createScope) {
|
||||
MOZ_ASSERT(bce->bodyScopeIndex == UINT32_MAX,
|
||||
"There can be only one body scope");
|
||||
bce->bodyScopeIndex = bce->scopeList.length();
|
||||
bce->bodyScopeIndex = bce->perScriptData().scopeList().length();
|
||||
return internScope(bce, createScope);
|
||||
}
|
||||
|
||||
bool EmitterScope::appendScopeNote(BytecodeEmitter* bce) {
|
||||
MOZ_ASSERT(ScopeKindIsInBody(scope(bce)->kind()) && enclosingInFrame(),
|
||||
"Scope notes are not needed for body-level scopes.");
|
||||
noteIndex_ = bce->scopeNoteList.length();
|
||||
return bce->scopeNoteList.append(index(), bce->offset(),
|
||||
enclosingInFrame()
|
||||
? enclosingInFrame()->noteIndex()
|
||||
: ScopeNote::NoScopeNoteIndex);
|
||||
noteIndex_ = bce->bytecodeSection().scopeNoteList().length();
|
||||
return bce->bytecodeSection().scopeNoteList().append(
|
||||
index(), bce->bytecodeSection().offset(),
|
||||
enclosingInFrame() ? enclosingInFrame()->noteIndex()
|
||||
: ScopeNote::NoScopeNoteIndex);
|
||||
}
|
||||
|
||||
bool EmitterScope::deadZoneFrameSlotRange(BytecodeEmitter* bce,
|
||||
|
@ -1057,9 +1057,10 @@ bool EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal) {
|
|||
if (ScopeKindIsInBody(kind)) {
|
||||
// The extra function var scope is never popped once it's pushed,
|
||||
// so its scope note extends until the end of any possible code.
|
||||
uint32_t offset =
|
||||
kind == ScopeKind::FunctionBodyVar ? UINT32_MAX : bce->offset();
|
||||
bce->scopeNoteList.recordEnd(noteIndex_, offset);
|
||||
uint32_t offset = kind == ScopeKind::FunctionBodyVar
|
||||
? UINT32_MAX
|
||||
: bce->bytecodeSection().offset();
|
||||
bce->bytecodeSection().scopeNoteList().recordEnd(noteIndex_, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1067,7 +1068,7 @@ bool EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal) {
|
|||
}
|
||||
|
||||
Scope* EmitterScope::scope(const BytecodeEmitter* bce) const {
|
||||
return bce->scopeList.vector[index()];
|
||||
return bce->perScriptData().scopeList().vector[index()];
|
||||
}
|
||||
|
||||
NameLocation EmitterScope::lookup(BytecodeEmitter* bce, JSAtom* name) {
|
||||
|
|
|
@ -29,7 +29,7 @@ bool ExpressionStatementEmitter::prepareForExpr(
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
depth_ = bce_->stackDepth;
|
||||
depth_ = bce_->bytecodeSection().stackDepth();
|
||||
state_ = State::Expr;
|
||||
#endif
|
||||
return true;
|
||||
|
@ -37,7 +37,7 @@ bool ExpressionStatementEmitter::prepareForExpr(
|
|||
|
||||
bool ExpressionStatementEmitter::emitEnd() {
|
||||
MOZ_ASSERT(state_ == State::Expr);
|
||||
MOZ_ASSERT(bce_->stackDepth == depth_ + 1);
|
||||
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_ + 1);
|
||||
|
||||
// [stack] VAL
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ bool ForInEmitter::emitInitialize() {
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
loopDepth_ = bce_->stackDepth;
|
||||
loopDepth_ = bce_->bytecodeSection().stackDepth();
|
||||
#endif
|
||||
MOZ_ASSERT(loopDepth_ >= 2);
|
||||
|
||||
|
@ -112,7 +112,7 @@ bool ForInEmitter::emitInitialize() {
|
|||
bool ForInEmitter::emitBody() {
|
||||
MOZ_ASSERT(state_ == State::Initialize);
|
||||
|
||||
MOZ_ASSERT(bce_->stackDepth == loopDepth_,
|
||||
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_,
|
||||
"iterator and iterval must be left on the stack");
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -124,7 +124,7 @@ bool ForInEmitter::emitBody() {
|
|||
bool ForInEmitter::emitEnd(const Maybe<uint32_t>& forPos) {
|
||||
MOZ_ASSERT(state_ == State::Body);
|
||||
|
||||
loopInfo_->setContinueTarget(bce_->offset());
|
||||
loopInfo_->setContinueTarget(bce_->bytecodeSection().offset());
|
||||
|
||||
if (forPos) {
|
||||
// Make sure this code is attributed to the "for".
|
||||
|
@ -171,8 +171,9 @@ bool ForInEmitter::emitEnd(const Maybe<uint32_t>& forPos) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!bce_->addTryNote(JSTRY_FOR_IN, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
bce_->offset())) {
|
||||
if (!bce_->addTryNote(JSTRY_FOR_IN, bce_->bytecodeSection().stackDepth(),
|
||||
loopInfo_->headOffset(),
|
||||
bce_->bytecodeSection().offset())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ bool ForOfEmitter::emitInitialize(const Maybe<uint32_t>& forPos) {
|
|||
}
|
||||
}
|
||||
|
||||
int32_t iterDepth = bce_->stackDepth;
|
||||
int32_t iterDepth = bce_->bytecodeSection().stackDepth();
|
||||
|
||||
// For-of loops have the iterator next method, the iterator itself, and
|
||||
// the result.value on the stack.
|
||||
|
@ -111,7 +111,7 @@ bool ForOfEmitter::emitInitialize(const Maybe<uint32_t>& forPos) {
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
loopDepth_ = bce_->stackDepth;
|
||||
loopDepth_ = bce_->bytecodeSection().stackDepth();
|
||||
#endif
|
||||
|
||||
// Make sure this code is attributed to the "for".
|
||||
|
@ -195,7 +195,7 @@ bool ForOfEmitter::emitInitialize(const Maybe<uint32_t>& forPos) {
|
|||
bool ForOfEmitter::emitBody() {
|
||||
MOZ_ASSERT(state_ == State::Initialize);
|
||||
|
||||
MOZ_ASSERT(bce_->stackDepth == loopDepth_,
|
||||
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_,
|
||||
"the stack must be balanced around the initializing "
|
||||
"operation");
|
||||
|
||||
|
@ -218,14 +218,14 @@ bool ForOfEmitter::emitBody() {
|
|||
bool ForOfEmitter::emitEnd(const Maybe<uint32_t>& iteratedPos) {
|
||||
MOZ_ASSERT(state_ == State::Body);
|
||||
|
||||
MOZ_ASSERT(bce_->stackDepth == loopDepth_,
|
||||
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_,
|
||||
"the stack must be balanced around the for-of body");
|
||||
|
||||
if (!loopInfo_->emitEndCodeNeedingIteratorClose(bce_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
loopInfo_->setContinueTarget(bce_->offset());
|
||||
loopInfo_->setContinueTarget(bce_->bytecodeSection().offset());
|
||||
|
||||
// We use the iterated value's position to attribute JSOP_LOOPENTRY,
|
||||
// which corresponds to the iteration protocol.
|
||||
|
@ -244,7 +244,7 @@ bool ForOfEmitter::emitEnd(const Maybe<uint32_t>& iteratedPos) {
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(bce_->stackDepth == loopDepth_);
|
||||
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_);
|
||||
|
||||
// Let Ion know where the closing jump of this loop is.
|
||||
if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::ForOf::BackJumpOffset,
|
||||
|
@ -256,7 +256,8 @@ bool ForOfEmitter::emitEnd(const Maybe<uint32_t>& iteratedPos) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!bce_->addTryNote(JSTRY_FOR_OF, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
if (!bce_->addTryNote(JSTRY_FOR_OF, bce_->bytecodeSection().stackDepth(),
|
||||
loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset())) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ bool ForOfLoopControl::emitBeginCodeNeedingIteratorClose(BytecodeEmitter* bce) {
|
|||
}
|
||||
|
||||
MOZ_ASSERT(numYieldsAtBeginCodeNeedingIterClose_ == UINT32_MAX);
|
||||
numYieldsAtBeginCodeNeedingIterClose_ = bce->numYields;
|
||||
numYieldsAtBeginCodeNeedingIterClose_ = bce->bytecodeSection().numYields();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ bool ForOfLoopControl::emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) {
|
|||
// [stack] ITER ... EXCEPTION
|
||||
return false;
|
||||
}
|
||||
unsigned slotFromTop = bce->stackDepth - iterDepth_;
|
||||
unsigned slotFromTop = bce->bytecodeSection().stackDepth() - iterDepth_;
|
||||
if (!bce->emitDupAt(slotFromTop)) {
|
||||
// [stack] ITER ... EXCEPTION ITER
|
||||
return false;
|
||||
|
@ -69,7 +69,8 @@ bool ForOfLoopControl::emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) {
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(slotFromTop == unsigned(bce->stackDepth - iterDepth_));
|
||||
MOZ_ASSERT(slotFromTop ==
|
||||
unsigned(bce->bytecodeSection().stackDepth() - iterDepth_));
|
||||
if (!bce->emitDupAt(slotFromTop)) {
|
||||
// [stack] ITER ... EXCEPTION ITER
|
||||
return false;
|
||||
|
@ -92,7 +93,7 @@ bool ForOfLoopControl::emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) {
|
|||
// If any yields were emitted, then this for-of loop is inside a star
|
||||
// generator and must handle the case of Generator.return. Like in
|
||||
// yield*, it is handled with a finally block.
|
||||
uint32_t numYieldsEmitted = bce->numYields;
|
||||
uint32_t numYieldsEmitted = bce->bytecodeSection().numYields();
|
||||
if (numYieldsEmitted > numYieldsAtBeginCodeNeedingIterClose_) {
|
||||
if (!tryCatch_->emitFinally()) {
|
||||
return false;
|
||||
|
@ -135,12 +136,12 @@ bool ForOfLoopControl::emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) {
|
|||
bool ForOfLoopControl::emitIteratorCloseInInnermostScopeWithTryNote(
|
||||
BytecodeEmitter* bce,
|
||||
CompletionKind completionKind /* = CompletionKind::Normal */) {
|
||||
ptrdiff_t start = bce->offset();
|
||||
ptrdiff_t start = bce->bytecodeSection().offset();
|
||||
if (!emitIteratorCloseInScope(bce, *bce->innermostEmitterScope(),
|
||||
completionKind)) {
|
||||
return false;
|
||||
}
|
||||
ptrdiff_t end = bce->offset();
|
||||
ptrdiff_t end = bce->bytecodeSection().offset();
|
||||
return bce->addTryNote(JSTRY_FOR_OF_ITERCLOSE, 0, start, end);
|
||||
}
|
||||
|
||||
|
@ -193,7 +194,7 @@ bool ForOfLoopControl::emitPrepareForNonLocalJumpFromScope(
|
|||
return false;
|
||||
}
|
||||
|
||||
*tryNoteStart = bce->offset();
|
||||
*tryNoteStart = bce->bytecodeSection().offset();
|
||||
if (!emitIteratorCloseInScope(bce, currentScope, CompletionKind::Normal)) {
|
||||
// [stack] UNDEF
|
||||
return false;
|
||||
|
|
|
@ -220,7 +220,7 @@ bool FunctionEmitter::emitAsmJSModule() {
|
|||
|
||||
bool FunctionEmitter::emitFunction() {
|
||||
// Make the function object a literal in the outer script's pool.
|
||||
unsigned index = bce_->objectList.add(funbox_);
|
||||
unsigned index = bce_->perScriptData().objectList().add(funbox_);
|
||||
|
||||
// [stack]
|
||||
|
||||
|
|
|
@ -41,10 +41,10 @@ bool BranchEmitterBase::emitThenInternal(SrcNoteType type) {
|
|||
// To restore stack depth in else part, save depth of the then part.
|
||||
#ifdef DEBUG
|
||||
// If DEBUG, this is also necessary to calculate |pushed_|.
|
||||
thenDepth_ = bce_->stackDepth;
|
||||
thenDepth_ = bce_->bytecodeSection().stackDepth();
|
||||
#else
|
||||
if (type == SRC_COND || type == SRC_IF_ELSE) {
|
||||
thenDepth_ = bce_->stackDepth;
|
||||
thenDepth_ = bce_->bytecodeSection().stackDepth();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -59,10 +59,10 @@ bool BranchEmitterBase::emitThenInternal(SrcNoteType type) {
|
|||
void BranchEmitterBase::calculateOrCheckPushed() {
|
||||
#ifdef DEBUG
|
||||
if (!calculatedPushed_) {
|
||||
pushed_ = bce_->stackDepth - thenDepth_;
|
||||
pushed_ = bce_->bytecodeSection().stackDepth() - thenDepth_;
|
||||
calculatedPushed_ = true;
|
||||
} else {
|
||||
MOZ_ASSERT(pushed_ == bce_->stackDepth - thenDepth_);
|
||||
MOZ_ASSERT(pushed_ == bce_->bytecodeSection().stackDepth() - thenDepth_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ bool BranchEmitterBase::emitElseInternal() {
|
|||
jumpAroundThen_ = JumpList();
|
||||
|
||||
// Restore stack depth of the then part.
|
||||
bce_->stackDepth = thenDepth_;
|
||||
bce_->bytecodeSection().setStackDepth(thenDepth_);
|
||||
|
||||
// Enclose else-branch with TDZCheckCache.
|
||||
if (kind_ == Kind::MayContainLexicalAccessInBranch) {
|
||||
|
|
|
@ -27,7 +27,7 @@ bool LabelEmitter::emitLabel(JSAtom* name) {
|
|||
return false;
|
||||
}
|
||||
|
||||
controlInfo_.emplace(bce_, name, bce_->offset());
|
||||
controlInfo_.emplace(bce_, name, bce_->bytecodeSection().offset());
|
||||
|
||||
#ifdef DEBUG
|
||||
state_ = State::Label;
|
||||
|
@ -39,8 +39,8 @@ bool LabelEmitter::emitEnd() {
|
|||
MOZ_ASSERT(state_ == State::Label);
|
||||
|
||||
// Patch the JSOP_LABEL offset.
|
||||
jsbytecode* labelpc = bce_->code(top_);
|
||||
int32_t offset = bce_->lastNonJumpTargetOffset() - top_;
|
||||
jsbytecode* labelpc = bce_->bytecodeSection().code(top_);
|
||||
int32_t offset = bce_->bytecodeSection().lastNonJumpTargetOffset() - top_;
|
||||
MOZ_ASSERT(*labelpc == JSOP_LABEL);
|
||||
SET_CODE_OFFSET(labelpc, offset);
|
||||
|
||||
|
|
|
@ -412,7 +412,7 @@ bool ObjectEmitter::emitObject(size_t propertyCount) {
|
|||
// Emit code for {p:a, '%q':b, 2:c} that is equivalent to constructing
|
||||
// a new object and defining (in source order) each property on the object
|
||||
// (or mutating the object's [[Prototype]], in the case of __proto__).
|
||||
top_ = bce_->offset();
|
||||
top_ = bce_->bytecodeSection().offset();
|
||||
if (!bce_->emitNewInit()) {
|
||||
// [stack] OBJ
|
||||
return false;
|
||||
|
|
|
@ -151,7 +151,7 @@ bool SwitchEmitter::emitCond() {
|
|||
|
||||
// After entering the scope if necessary, push the switch control.
|
||||
controlInfo_.emplace(bce_, StatementKind::Switch);
|
||||
top_ = bce_->offset();
|
||||
top_ = bce_->bytecodeSection().offset();
|
||||
|
||||
if (!caseOffsets_.resize(caseCount_)) {
|
||||
ReportOutOfMemory(bce_->cx);
|
||||
|
@ -164,7 +164,7 @@ bool SwitchEmitter::emitCond() {
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(top_ == bce_->offset());
|
||||
MOZ_ASSERT(top_ == bce_->bytecodeSection().offset());
|
||||
if (!bce_->emitN(JSOP_CONDSWITCH, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ bool SwitchEmitter::emitTable(const TableGenerator& tableGen) {
|
|||
|
||||
// After entering the scope if necessary, push the switch control.
|
||||
controlInfo_.emplace(bce_, StatementKind::Switch);
|
||||
top_ = bce_->offset();
|
||||
top_ = bce_->bytecodeSection().offset();
|
||||
|
||||
// The note has one offset that tells total switch code length.
|
||||
if (!bce_->newSrcNote2(SRC_TABLESWITCH, 0, ¬eIndex_)) {
|
||||
|
@ -193,14 +193,14 @@ bool SwitchEmitter::emitTable(const TableGenerator& tableGen) {
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(top_ == bce_->offset());
|
||||
MOZ_ASSERT(top_ == bce_->bytecodeSection().offset());
|
||||
if (!bce_->emitN(JSOP_TABLESWITCH,
|
||||
JSOP_TABLESWITCH_LENGTH - sizeof(jsbytecode))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip default offset.
|
||||
jsbytecode* pc = bce_->code(top_ + JUMP_OFFSET_LEN);
|
||||
jsbytecode* pc = bce_->bytecodeSection().code(top_ + JUMP_OFFSET_LEN);
|
||||
|
||||
// Fill in switch bounds, which we know fit in 16-bit offsets.
|
||||
SET_JUMP_OFFSET(pc, tableGen.low());
|
||||
|
@ -223,9 +223,9 @@ bool SwitchEmitter::emitCaseOrDefaultJump(uint32_t caseIndex, bool isDefault) {
|
|||
if (caseIndex > 0) {
|
||||
// Link the last JSOP_CASE's SRC_NEXTCASE to current JSOP_CASE for the
|
||||
// benefit of IonBuilder.
|
||||
if (!bce_->setSrcNoteOffset(caseNoteIndex_,
|
||||
SrcNote::NextCase::NextCaseOffset,
|
||||
bce_->offset() - lastCaseOffset_)) {
|
||||
if (!bce_->setSrcNoteOffset(
|
||||
caseNoteIndex_, SrcNote::NextCase::NextCaseOffset,
|
||||
bce_->bytecodeSection().offset() - lastCaseOffset_)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -243,11 +243,12 @@ bool SwitchEmitter::emitCaseOrDefaultJump(uint32_t caseIndex, bool isDefault) {
|
|||
|
||||
if (caseIndex == 0) {
|
||||
// Switch note's second offset is to first JSOP_CASE.
|
||||
unsigned noteCount = bce_->notes().length();
|
||||
unsigned noteCount = bce_->bytecodeSection().notes().length();
|
||||
if (!bce_->setSrcNoteOffset(noteIndex_, 1, lastCaseOffset_ - top_)) {
|
||||
return false;
|
||||
}
|
||||
unsigned noteCountDelta = bce_->notes().length() - noteCount;
|
||||
unsigned noteCountDelta =
|
||||
bce_->bytecodeSection().notes().length() - noteCount;
|
||||
if (noteCountDelta != 0) {
|
||||
caseNoteIndex_ += noteCountDelta;
|
||||
}
|
||||
|
@ -398,7 +399,7 @@ bool SwitchEmitter::emitEnd() {
|
|||
defaultJumpTargetOffset_);
|
||||
} else {
|
||||
// Fill in the default jump target.
|
||||
pc = bce_->code(top_);
|
||||
pc = bce_->bytecodeSection().code(top_);
|
||||
SET_JUMP_OFFSET(pc, defaultJumpTargetOffset_.offset - top_);
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
}
|
||||
|
@ -408,8 +409,9 @@ bool SwitchEmitter::emitEnd() {
|
|||
static_assert(unsigned(SrcNote::TableSwitch::EndOffset) ==
|
||||
unsigned(SrcNote::CondSwitch::EndOffset),
|
||||
"{TableSwitch,CondSwitch}::EndOffset should be same");
|
||||
if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::TableSwitch::EndOffset,
|
||||
bce_->lastNonJumpTargetOffset() - top_)) {
|
||||
if (!bce_->setSrcNoteOffset(
|
||||
noteIndex_, SrcNote::TableSwitch::EndOffset,
|
||||
bce_->bytecodeSection().lastNonJumpTargetOffset() - top_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ bool TryEmitter::emitTry() {
|
|||
// For that we store in a try note associated with the catch or
|
||||
// finally block the stack depth upon the try entry. The interpreter
|
||||
// uses this depth to properly unwind the stack and the scope chain.
|
||||
depth_ = bce_->stackDepth;
|
||||
depth_ = bce_->bytecodeSection().stackDepth();
|
||||
|
||||
// Record the try location, then emit the try block.
|
||||
if (!bce_->newSrcNote(SRC_TRY, ¬eIndex_)) {
|
||||
|
@ -62,7 +62,7 @@ bool TryEmitter::emitTry() {
|
|||
if (!bce_->emit1(JSOP_TRY)) {
|
||||
return false;
|
||||
}
|
||||
tryStart_ = bce_->offset();
|
||||
tryStart_ = bce_->bytecodeSection().offset();
|
||||
|
||||
#ifdef DEBUG
|
||||
state_ = State::Try;
|
||||
|
@ -72,7 +72,7 @@ bool TryEmitter::emitTry() {
|
|||
|
||||
bool TryEmitter::emitTryEnd() {
|
||||
MOZ_ASSERT(state_ == State::Try);
|
||||
MOZ_ASSERT(depth_ == bce_->stackDepth);
|
||||
MOZ_ASSERT(depth_ == bce_->bytecodeSection().stackDepth());
|
||||
|
||||
// GOSUB to finally, if present.
|
||||
if (hasFinally() && controlInfo_) {
|
||||
|
@ -82,8 +82,9 @@ bool TryEmitter::emitTryEnd() {
|
|||
}
|
||||
|
||||
// Source note points to the jump at the end of the try block.
|
||||
if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::Try::EndOfTryJumpOffset,
|
||||
bce_->offset() - tryStart_ + JSOP_TRY_LENGTH)) {
|
||||
if (!bce_->setSrcNoteOffset(
|
||||
noteIndex_, SrcNote::Try::EndOfTryJumpOffset,
|
||||
bce_->bytecodeSection().offset() - tryStart_ + JSOP_TRY_LENGTH)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,7 @@ bool TryEmitter::emitCatch() {
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(bce_->stackDepth == depth_);
|
||||
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
|
||||
|
||||
if (controlKind_ == ControlKind::Syntactic) {
|
||||
// Clear the frame's return value that might have been set by the
|
||||
|
@ -138,7 +139,7 @@ bool TryEmitter::emitCatchEnd() {
|
|||
if (!bce_->emitGoSub(&controlInfo_->gosubs)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(bce_->stackDepth == depth_);
|
||||
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
|
||||
|
||||
// Jump over the finally block.
|
||||
if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_)) {
|
||||
|
@ -177,7 +178,7 @@ bool TryEmitter::emitFinally(
|
|||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(bce_->stackDepth == depth_);
|
||||
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
|
||||
|
||||
if (!bce_->emitJumpTarget(&finallyStart_)) {
|
||||
return false;
|
||||
|
@ -253,7 +254,7 @@ bool TryEmitter::emitEnd() {
|
|||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(bce_->stackDepth == depth_);
|
||||
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
|
||||
|
||||
// ReconstructPCStack needs a NOP here to mark the end of the last
|
||||
// catch block.
|
||||
|
|
|
@ -100,7 +100,8 @@ bool WhileEmitter::emitEnd() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
if (!bce_->addTryNote(JSTRY_LOOP, bce_->bytecodeSection().stackDepth(),
|
||||
loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset())) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "gc/Allocator.h"
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
#include "gc/GCInternals.h"
|
||||
#include "gc/GCTrace.h"
|
||||
|
@ -22,6 +23,9 @@
|
|||
#include "gc/PrivateIterators-inl.h"
|
||||
#include "vm/JSObject-inl.h"
|
||||
|
||||
using mozilla::TimeDuration;
|
||||
using mozilla::TimeStamp;
|
||||
|
||||
using namespace js;
|
||||
using namespace gc;
|
||||
|
||||
|
@ -268,19 +272,16 @@ T* GCRuntime::tryNewTenuredThing(JSContext* cx, AllocKind kind,
|
|||
// chunks available it may also allocate new memory directly.
|
||||
t = reinterpret_cast<T*>(refillFreeListFromAnyThread(cx, kind));
|
||||
|
||||
if (MOZ_UNLIKELY(!t && allowGC)) {
|
||||
if (!cx->helperThread()) {
|
||||
// We have no memory available for a new chunk; perform an
|
||||
// all-compartments, non-incremental, shrinking GC and wait for
|
||||
// sweeping to finish.
|
||||
JS::PrepareForFullGC(cx);
|
||||
cx->runtime()->gc.gc(GC_SHRINK, JS::GCReason::LAST_DITCH);
|
||||
cx->runtime()->gc.waitBackgroundSweepOrAllocEnd();
|
||||
|
||||
if (MOZ_UNLIKELY(!t)) {
|
||||
if (allowGC) {
|
||||
cx->runtime()->gc.attemptLastDitchGC(cx);
|
||||
t = tryNewTenuredThing<T, NoGC>(cx, kind, thingSize);
|
||||
}
|
||||
if (!t) {
|
||||
ReportOutOfMemory(cx);
|
||||
if (allowGC) {
|
||||
ReportOutOfMemory(cx);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,6 +295,28 @@ T* GCRuntime::tryNewTenuredThing(JSContext* cx, AllocKind kind,
|
|||
return t;
|
||||
}
|
||||
|
||||
void GCRuntime::attemptLastDitchGC(JSContext* cx) {
|
||||
// Either there was no memory available for a new chunk or the heap hit its
|
||||
// size limit. Try to perform an all-compartments, non-incremental, shrinking
|
||||
// GC and wait for it to finish.
|
||||
|
||||
if (cx->helperThread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lastLastDitchTime.IsNull() &&
|
||||
TimeStamp::Now() - lastLastDitchTime <= tunables.minLastDitchGCPeriod()) {
|
||||
return;
|
||||
}
|
||||
|
||||
JS::PrepareForFullGC(cx);
|
||||
gc(GC_SHRINK, JS::GCReason::LAST_DITCH);
|
||||
waitBackgroundAllocEnd();
|
||||
waitBackgroundFreeEnd();
|
||||
|
||||
lastLastDitchTime = mozilla::TimeStamp::Now();
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
bool GCRuntime::checkAllocatorState(JSContext* cx, AllocKind kind) {
|
||||
if (allowGC) {
|
||||
|
|
|
@ -364,6 +364,9 @@ static const float PretenureThreshold = 0.6f;
|
|||
/* JSGC_PRETENURE_GROUP_THRESHOLD */
|
||||
static const float PretenureGroupThreshold = 3000;
|
||||
|
||||
/* JSGC_MIN_LAST_DITCH_GC_PERIOD */
|
||||
static const TimeDuration MinLastDitchGCPeriod = TimeDuration::FromSeconds(60);
|
||||
|
||||
} // namespace TuningDefaults
|
||||
} // namespace gc
|
||||
} // namespace js
|
||||
|
@ -1521,6 +1524,9 @@ bool GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value,
|
|||
}
|
||||
pretenureGroupThreshold_ = value;
|
||||
break;
|
||||
case JSGC_MIN_LAST_DITCH_GC_PERIOD:
|
||||
minLastDitchGCPeriod_ = TimeDuration::FromSeconds(value);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unknown GC parameter.");
|
||||
}
|
||||
|
@ -1613,7 +1619,8 @@ GCSchedulingTunables::GCSchedulingTunables()
|
|||
nurseryFreeThresholdForIdleCollectionFraction_(
|
||||
TuningDefaults::NurseryFreeThresholdForIdleCollectionFraction),
|
||||
pretenureThreshold_(TuningDefaults::PretenureThreshold),
|
||||
pretenureGroupThreshold_(TuningDefaults::PretenureGroupThreshold) {}
|
||||
pretenureGroupThreshold_(TuningDefaults::PretenureGroupThreshold),
|
||||
minLastDitchGCPeriod_(TuningDefaults::MinLastDitchGCPeriod) {}
|
||||
|
||||
void GCRuntime::resetParameter(JSGCParamKey key, AutoLockGC& lock) {
|
||||
switch (key) {
|
||||
|
@ -1708,6 +1715,9 @@ void GCSchedulingTunables::resetParameter(JSGCParamKey key,
|
|||
case JSGC_PRETENURE_GROUP_THRESHOLD:
|
||||
pretenureGroupThreshold_ = TuningDefaults::PretenureGroupThreshold;
|
||||
break;
|
||||
case JSGC_MIN_LAST_DITCH_GC_PERIOD:
|
||||
minLastDitchGCPeriod_ = TuningDefaults::MinLastDitchGCPeriod;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unknown GC parameter.");
|
||||
}
|
||||
|
@ -1783,6 +1793,8 @@ uint32_t GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock) {
|
|||
return uint32_t(tunables.pretenureThreshold() * 100);
|
||||
case JSGC_PRETENURE_GROUP_THRESHOLD:
|
||||
return tunables.pretenureGroupThreshold();
|
||||
case JSGC_MIN_LAST_DITCH_GC_PERIOD:
|
||||
return tunables.minLastDitchGCPeriod().ToSeconds();
|
||||
default:
|
||||
MOZ_CRASH("Unknown parameter key");
|
||||
}
|
||||
|
|
|
@ -310,8 +310,7 @@ class GCRuntime {
|
|||
bool isForegroundSweeping() const { return state() == State::Sweep; }
|
||||
bool isBackgroundSweeping() { return sweepTask.isRunning(); }
|
||||
void waitBackgroundSweepEnd();
|
||||
void waitBackgroundSweepOrAllocEnd() {
|
||||
waitBackgroundSweepEnd();
|
||||
void waitBackgroundAllocEnd() {
|
||||
allocTask.cancelAndWait();
|
||||
}
|
||||
void waitBackgroundFreeEnd();
|
||||
|
@ -535,6 +534,7 @@ class GCRuntime {
|
|||
AllocKind thingKind);
|
||||
static TenuredCell* refillFreeListFromHelperThread(JSContext* cx,
|
||||
AllocKind thingKind);
|
||||
void attemptLastDitchGC(JSContext* cx);
|
||||
|
||||
/*
|
||||
* Return the list of chunks that can be released outside the GC lock.
|
||||
|
@ -1045,6 +1045,8 @@ class GCRuntime {
|
|||
minorGC(reason, gcstats::PhaseKind::EVICT_NURSERY);
|
||||
}
|
||||
|
||||
mozilla::TimeStamp lastLastDitchTime;
|
||||
|
||||
friend class MarkingValidator;
|
||||
friend class AutoEnterIteration;
|
||||
};
|
||||
|
|
|
@ -456,6 +456,14 @@ class GCSchedulingTunables {
|
|||
*/
|
||||
UnprotectedData<uint32_t> pretenureGroupThreshold_;
|
||||
|
||||
/*
|
||||
* JSGC_MIN_LAST_DITCH_GC_PERIOD
|
||||
*
|
||||
* Last ditch GC is skipped if allocation failure occurs less than this many
|
||||
* seconds from the previous one.
|
||||
*/
|
||||
MainThreadData<mozilla::TimeDuration> minLastDitchGCPeriod_;
|
||||
|
||||
public:
|
||||
GCSchedulingTunables();
|
||||
|
||||
|
@ -502,6 +510,10 @@ class GCSchedulingTunables {
|
|||
float pretenureThreshold() const { return pretenureThreshold_; }
|
||||
uint32_t pretenureGroupThreshold() const { return pretenureGroupThreshold_; }
|
||||
|
||||
mozilla::TimeDuration minLastDitchGCPeriod() const {
|
||||
return minLastDitchGCPeriod_;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool setParameter(JSGCParamKey key, uint32_t value,
|
||||
const AutoLockGC& lock);
|
||||
void resetParameter(JSGCParamKey key, const AutoLockGC& lock);
|
||||
|
|
|
@ -789,8 +789,14 @@ bool js::gc::CheckWeakMapEntryMarking(const WeakMapBase* map, Cell* key,
|
|||
}
|
||||
|
||||
CellColor keyColor = GetCellColor(key);
|
||||
CellColor valueColor =
|
||||
valueZone->isGCMarking() ? GetCellColor(value) : CellColor::Black;
|
||||
|
||||
// Values belonging to other runtimes or in uncollected zones are treated as
|
||||
// black.
|
||||
CellColor valueColor = CellColor::Black;
|
||||
if (value->runtimeFromAnyThread() == zone->runtimeFromAnyThread() &&
|
||||
valueZone->isGCMarking()) {
|
||||
valueColor = GetCellColor(value);
|
||||
}
|
||||
|
||||
if (valueColor < Min(mapColor, keyColor)) {
|
||||
fprintf(stderr, "WeakMap value is less marked than map and key\n");
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
// Test that we don't repeatedly trigger last-ditch GCs.
|
||||
|
||||
function allocUntilFail() {
|
||||
gc();
|
||||
let initGCNumber = gcparam("gcNumber");
|
||||
let error;
|
||||
try {
|
||||
let a = [];
|
||||
while (true) {
|
||||
a.push(Symbol()); // Symbols are tenured.
|
||||
}
|
||||
} catch(err) {
|
||||
error = err;
|
||||
}
|
||||
let finalGCNumber = gcparam("gcNumber");
|
||||
gc();
|
||||
assertEq(error, "out of memory");
|
||||
return finalGCNumber - initGCNumber;
|
||||
}
|
||||
|
||||
// Turn of any zeal which will disrupt GC number checks.
|
||||
gczeal(0);
|
||||
|
||||
// Set a small heap limit.
|
||||
gcparam("maxBytes", 1024 * 1024);
|
||||
|
||||
// Set the time limit for skipping last ditch GCs to 5 seconds.
|
||||
gcparam("minLastDitchGCPeriod", 5);
|
||||
assertEq(gcparam("minLastDitchGCPeriod"), 5);
|
||||
|
||||
// Allocate up to the heap limit. This triggers a last ditch GC.
|
||||
let gcCount = allocUntilFail();
|
||||
assertEq(gcCount, 1)
|
||||
|
||||
// Allocate up to the limit again. The second time we fail without
|
||||
// triggering a GC.
|
||||
gcCount = allocUntilFail();
|
||||
assertEq(gcCount, 0)
|
||||
|
||||
// Wait for time limit to expire.
|
||||
sleep(6);
|
||||
|
||||
// Check we trigger a GC again.
|
||||
gcCount = allocUntilFail();
|
||||
assertEq(gcCount, 1)
|
|
@ -0,0 +1,11 @@
|
|||
// |jit-test| skip-if: helperThreadCount() === 0
|
||||
gczeal(0);
|
||||
evalInWorker(`
|
||||
var sym4 = Symbol.match;
|
||||
function basicSweeping() {};
|
||||
var wm1 = new WeakMap();
|
||||
wm1.set(basicSweeping, sym4);
|
||||
startgc(100000, 'shrinking');
|
||||
`);
|
||||
gczeal(2);
|
||||
var d1 = newGlobal({});
|
|
@ -39,6 +39,8 @@ class ProgressBar(object):
|
|||
self.limit_digits = int(math.ceil(math.log10(self.limit)))
|
||||
# datetime: The start time.
|
||||
self.t0 = datetime.now()
|
||||
# datetime: Optional, the last time update() ran.
|
||||
self.last_update_time = None
|
||||
|
||||
# Compute the width of the counters and build the format string.
|
||||
self.counters_width = 1 # [
|
||||
|
@ -79,7 +81,8 @@ class ProgressBar(object):
|
|||
sys.stdout.write(bar + '|')
|
||||
|
||||
# Update the bar.
|
||||
dt = datetime.now() - self.t0
|
||||
now = datetime.now()
|
||||
dt = now - self.t0
|
||||
dt = dt.seconds + dt.microseconds * 1e-6
|
||||
sys.stdout.write('{:6.1f}s'.format(dt))
|
||||
Terminal.clear_right()
|
||||
|
@ -87,9 +90,13 @@ class ProgressBar(object):
|
|||
# Force redisplay, since we didn't write a \n.
|
||||
sys.stdout.flush()
|
||||
|
||||
self.last_update_time = now
|
||||
|
||||
def poke(self):
|
||||
if not self.prior:
|
||||
return
|
||||
if datetime.now() - self.last_update_time < self.update_granularity():
|
||||
return
|
||||
self.update(*self.prior)
|
||||
|
||||
def finish(self, complete=True):
|
||||
|
|
|
@ -508,9 +508,10 @@ JS_PUBLIC_API bool JS::CloneAndExecuteScript(JSContext* cx,
|
|||
return ExecuteScript(cx, envChain, script, rval.address());
|
||||
}
|
||||
|
||||
template <typename Unit>
|
||||
static bool Evaluate(JSContext* cx, ScopeKind scopeKind, HandleObject env,
|
||||
const ReadOnlyCompileOptions& optionsArg,
|
||||
SourceText<char16_t>& srcBuf, MutableHandleValue rval) {
|
||||
SourceText<Unit>& srcBuf, MutableHandleValue rval) {
|
||||
CompileOptions options(cx, optionsArg);
|
||||
MOZ_ASSERT(!cx->zone()->isAtomsZone());
|
||||
AssertHeapIsIdle();
|
||||
|
@ -548,14 +549,8 @@ static bool Evaluate(JSContext* cx, HandleObjectVector envChain,
|
|||
extern JS_PUBLIC_API bool JS::EvaluateUtf8(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options, const char* bytes,
|
||||
size_t length, MutableHandle<Value> rval) {
|
||||
auto chars = UniqueTwoByteChars(
|
||||
UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get());
|
||||
if (!chars) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceText<char16_t> srcBuf;
|
||||
if (!srcBuf.init(cx, std::move(chars), length)) {
|
||||
SourceText<Utf8Unit> srcBuf;
|
||||
if (!srcBuf.init(cx, bytes, length, SourceOwnership::Borrowed)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -594,7 +589,19 @@ JS_PUBLIC_API bool JS::EvaluateUtf8Path(
|
|||
CompileOptions options(cx, optionsArg);
|
||||
options.setFileAndLine(filename, 1);
|
||||
|
||||
return EvaluateUtf8(cx, options,
|
||||
reinterpret_cast<const char*>(buffer.begin()),
|
||||
buffer.length(), rval);
|
||||
auto contents = reinterpret_cast<const char*>(buffer.begin());
|
||||
size_t length = buffer.length();
|
||||
auto chars = UniqueTwoByteChars(
|
||||
UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(contents, length), &length)
|
||||
.get());
|
||||
if (!chars) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceText<char16_t> srcBuf;
|
||||
if (!srcBuf.init(cx, std::move(chars), length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Evaluate(cx, options, srcBuf, rval);
|
||||
}
|
||||
|
|
|
@ -3238,12 +3238,12 @@ PrivateScriptData* PrivateScriptData::new_(JSContext* cx, uint32_t nscopes,
|
|||
|
||||
/* static */ bool PrivateScriptData::InitFromEmitter(
|
||||
JSContext* cx, js::HandleScript script, frontend::BytecodeEmitter* bce) {
|
||||
uint32_t nscopes = bce->scopeList.length();
|
||||
uint32_t nconsts = bce->numberList.length();
|
||||
uint32_t nobjects = bce->objectList.length;
|
||||
uint32_t ntrynotes = bce->tryNoteList.length();
|
||||
uint32_t nscopenotes = bce->scopeNoteList.length();
|
||||
uint32_t nresumeoffsets = bce->resumeOffsetList.length();
|
||||
uint32_t nscopes = bce->perScriptData().scopeList().length();
|
||||
uint32_t nconsts = bce->perScriptData().numberList().length();
|
||||
uint32_t nobjects = bce->perScriptData().objectList().length;
|
||||
uint32_t ntrynotes = bce->bytecodeSection().tryNoteList().length();
|
||||
uint32_t nscopenotes = bce->bytecodeSection().scopeNoteList().length();
|
||||
uint32_t nresumeoffsets = bce->bytecodeSection().resumeOffsetList().length();
|
||||
|
||||
// Create and initialize PrivateScriptData
|
||||
if (!JSScript::createPrivateScriptData(cx, script, nscopes, nconsts, nobjects,
|
||||
|
@ -3254,22 +3254,22 @@ PrivateScriptData* PrivateScriptData::new_(JSContext* cx, uint32_t nscopes,
|
|||
|
||||
js::PrivateScriptData* data = script->data_;
|
||||
if (nscopes) {
|
||||
bce->scopeList.finish(data->scopes());
|
||||
bce->perScriptData().scopeList().finish(data->scopes());
|
||||
}
|
||||
if (nconsts) {
|
||||
bce->numberList.finish(data->consts());
|
||||
bce->perScriptData().numberList().finish(data->consts());
|
||||
}
|
||||
if (nobjects) {
|
||||
bce->objectList.finish(data->objects());
|
||||
bce->perScriptData().objectList().finish(data->objects());
|
||||
}
|
||||
if (ntrynotes) {
|
||||
bce->tryNoteList.finish(data->tryNotes());
|
||||
bce->bytecodeSection().tryNoteList().finish(data->tryNotes());
|
||||
}
|
||||
if (nscopenotes) {
|
||||
bce->scopeNoteList.finish(data->scopeNotes());
|
||||
bce->bytecodeSection().scopeNoteList().finish(data->scopeNotes());
|
||||
}
|
||||
if (nresumeoffsets) {
|
||||
bce->resumeOffsetList.finish(data->resumeOffsets());
|
||||
bce->bytecodeSection().resumeOffsetList().finish(data->resumeOffsets());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -3565,11 +3565,12 @@ bool JSScript::fullyInitFromEmitter(JSContext* cx, HandleScript script,
|
|||
mozilla::MakeScopeExit([&] { script->freeScriptData(); });
|
||||
|
||||
/* The counts of indexed things must be checked during code generation. */
|
||||
MOZ_ASSERT(bce->atomIndices->count() <= INDEX_LIMIT);
|
||||
MOZ_ASSERT(bce->objectList.length <= INDEX_LIMIT);
|
||||
MOZ_ASSERT(bce->perScriptData().atomIndices()->count() <= INDEX_LIMIT);
|
||||
MOZ_ASSERT(bce->perScriptData().objectList().length <= INDEX_LIMIT);
|
||||
|
||||
uint64_t nslots =
|
||||
bce->maxFixedSlots + static_cast<uint64_t>(bce->maxStackDepth);
|
||||
bce->maxFixedSlots +
|
||||
static_cast<uint64_t>(bce->bytecodeSection().maxStackDepth());
|
||||
if (nslots > UINT32_MAX) {
|
||||
bce->reportError(nullptr, JSMSG_NEED_DIET, js_script_str);
|
||||
return false;
|
||||
|
@ -3581,7 +3582,7 @@ bool JSScript::fullyInitFromEmitter(JSContext* cx, HandleScript script,
|
|||
script->nfixed_ = bce->maxFixedSlots;
|
||||
script->nslots_ = nslots;
|
||||
script->bodyScopeIndex_ = bce->bodyScopeIndex;
|
||||
script->numBytecodeTypeSets_ = bce->typesetCount;
|
||||
script->numBytecodeTypeSets_ = bce->bytecodeSection().typesetCount();
|
||||
|
||||
// Initialize script flags from BytecodeEmitter
|
||||
script->setFlag(ImmutableFlags::Strict, bce->sc->strict());
|
||||
|
@ -3628,7 +3629,7 @@ bool JSScript::fullyInitFromEmitter(JSContext* cx, HandleScript script,
|
|||
// Part of the parse result – the scope containing each inner function – must
|
||||
// be stored in the inner function itself. Do this now that compilation is
|
||||
// complete and can no longer fail.
|
||||
bce->objectList.finishInnerFunctions();
|
||||
bce->perScriptData().objectList().finishInnerFunctions();
|
||||
|
||||
#ifdef JS_STRUCTURED_SPEW
|
||||
// We want this to happen after line number initialization to allow filtering
|
||||
|
@ -4522,12 +4523,12 @@ bool JSScript::hasBreakpointsAt(jsbytecode* pc) {
|
|||
|
||||
/* static */ bool SharedScriptData::InitFromEmitter(
|
||||
JSContext* cx, js::HandleScript script, frontend::BytecodeEmitter* bce) {
|
||||
uint32_t natoms = bce->atomIndices->count();
|
||||
uint32_t codeLength = bce->code().length();
|
||||
uint32_t natoms = bce->perScriptData().atomIndices()->count();
|
||||
uint32_t codeLength = bce->bytecodeSection().code().length();
|
||||
|
||||
// The + 1 is to account for the final SN_MAKE_TERMINATOR that is appended
|
||||
// when the notes are copied to their final destination by copySrcNotes.
|
||||
uint32_t noteLength = bce->notes().length() + 1;
|
||||
uint32_t noteLength = bce->bytecodeSection().notes().length() + 1;
|
||||
|
||||
// Create and initialize SharedScriptData
|
||||
if (!script->createSharedScriptData(cx, codeLength, noteLength, natoms)) {
|
||||
|
@ -4537,9 +4538,9 @@ bool JSScript::hasBreakpointsAt(jsbytecode* pc) {
|
|||
js::SharedScriptData* data = script->scriptData_;
|
||||
|
||||
// Initialize trailing arrays
|
||||
std::copy_n(bce->code().begin(), codeLength, data->code());
|
||||
std::copy_n(bce->bytecodeSection().code().begin(), codeLength, data->code());
|
||||
bce->copySrcNotes(data->notes(), noteLength);
|
||||
InitAtomMap(*bce->atomIndices, data->atoms());
|
||||
InitAtomMap(*bce->perScriptData().atomIndices(), data->atoms());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ UNIFIED_SOURCES += [
|
|||
'Utf8.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_BUILD_APP'] not in ('memory', 'tools/crashreporter', 'tools/update-packaging'):
|
||||
if CONFIG['MOZ_BUILD_APP'] not in ('memory', 'tools/crashreporter'):
|
||||
# RecordReplay.cpp uses files from js/
|
||||
UNIFIED_SOURCES += [
|
||||
'RecordReplay.cpp',
|
||||
|
|
|
@ -18,5 +18,4 @@ if CONFIG['HOST_OS_ARCH'] == 'WINNT':
|
|||
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/mozapps/update/updater',
|
||||
'/toolkit/mozapps/update/updater/bspatch',
|
||||
]
|
||||
|
|
|
@ -37,9 +37,6 @@ only-for-build-platforms:
|
|||
- win64-aarch64-devedition-nightly/opt
|
||||
|
||||
job-template:
|
||||
worker-type: 'aws-provisioner-v1/gecko-{level}-b-linux'
|
||||
worker:
|
||||
docker-image: {"in-tree": "debian7-amd64-build"}
|
||||
mozharness:
|
||||
config:
|
||||
by-build-platform:
|
||||
|
@ -80,7 +77,3 @@ job-template:
|
|||
macosx64\b.*: [mar, dmg]
|
||||
win32\b.*: [mar, installer]
|
||||
win64\b.*: [mar, installer]
|
||||
fetches:
|
||||
toolchain:
|
||||
- linux64-mar-tools
|
||||
- linux64-upx
|
||||
|
|
|
@ -25,10 +25,7 @@ only-for-build-platforms:
|
|||
- win64-devedition-nightly/opt
|
||||
|
||||
job-template:
|
||||
worker-type: 'aws-provisioner-v1/gecko-{level}-b-win2012'
|
||||
mozharness:
|
||||
use-magic-mh-args: false
|
||||
use-caches: false
|
||||
config:
|
||||
by-build-platform:
|
||||
win32\b.*:
|
||||
|
|
|
@ -47,9 +47,6 @@ only-for-build-platforms:
|
|||
- win64-asan-reporter-nightly/opt
|
||||
|
||||
job-template:
|
||||
worker-type: 'aws-provisioner-v1/gecko-{level}-b-linux'
|
||||
worker:
|
||||
docker-image: {"in-tree": "debian7-amd64-build"}
|
||||
mozharness:
|
||||
config:
|
||||
by-build-platform:
|
||||
|
@ -90,7 +87,3 @@ job-template:
|
|||
macosx64\b.*: [mar, dmg]
|
||||
win32\b.*: [mar, installer]
|
||||
win64\b.*: [mar, installer]
|
||||
fetches:
|
||||
toolchain:
|
||||
- linux64-mar-tools
|
||||
- linux64-upx
|
||||
|
|
|
@ -10,6 +10,14 @@ job-defaults:
|
|||
docker-image: {in-tree: mingw32-build}
|
||||
max-run-time: 3600
|
||||
|
||||
linux64-upx:
|
||||
description: "UPX build for MinGW32 Cross Compile"
|
||||
treeherder:
|
||||
symbol: TMW(upx)
|
||||
run:
|
||||
script: build-upx.sh
|
||||
toolchain-artifact: public/build/upx.tar.xz
|
||||
|
||||
linux64-wine:
|
||||
description: "Wine build for MinGW32 Cross Compile"
|
||||
treeherder:
|
||||
|
|
|
@ -70,23 +70,6 @@ linux64-libdmg:
|
|||
script: build-libdmg-hfsplus.sh
|
||||
toolchain-artifact: public/build/dmg.tar.xz
|
||||
|
||||
linux64-mar-tools:
|
||||
description: "mar-tools toolchain build"
|
||||
treeherder:
|
||||
symbol: TL(mar-tools)
|
||||
toolchains:
|
||||
- linux64-clang-7
|
||||
- linux64-binutils
|
||||
run:
|
||||
script: build-mar-tools.sh
|
||||
sparse-profile: null
|
||||
toolchain-artifact: public/build/mar-tools.tar.xz
|
||||
resources:
|
||||
- modules/libmar/
|
||||
- other-licenses/nsis/Contrib/CityHash/cityhash/
|
||||
- other-licenses/bsdiff/
|
||||
- toolkit/mozapps/update/updater/bspatch/
|
||||
|
||||
linux64-tup:
|
||||
description: "tup toolchain build"
|
||||
treeherder:
|
||||
|
@ -104,15 +87,6 @@ linux64-tup:
|
|||
toolchains:
|
||||
- linux64-gcc-6
|
||||
|
||||
linux64-upx:
|
||||
description: "UPX build"
|
||||
treeherder:
|
||||
symbol: TL(upx)
|
||||
tier: 1
|
||||
run:
|
||||
script: build-upx.sh
|
||||
toolchain-artifact: public/build/upx.tar.xz
|
||||
|
||||
linux64-custom-v8:
|
||||
description: "Custom v8 build"
|
||||
treeherder:
|
||||
|
|
|
@ -44,7 +44,6 @@ RUN apt-get update && \
|
|||
gawk \
|
||||
gcc-multilib \
|
||||
gnupg \
|
||||
libucl1 \
|
||||
p7zip-full \
|
||||
procps \
|
||||
python-pip \
|
||||
|
|
|
@ -24,7 +24,7 @@ RUN apt-get update && \
|
|||
gawk \
|
||||
g++-multilib \
|
||||
gnupg \
|
||||
libucl1 \
|
||||
libucl-dev \
|
||||
patch \
|
||||
p7zip-full \
|
||||
scons \
|
||||
|
|
|
@ -29,7 +29,6 @@ RUN apt-get update && \
|
|||
libcurl4-openssl-dev \
|
||||
libssl-dev \
|
||||
libtool \
|
||||
libucl-dev \
|
||||
ninja-build \
|
||||
p7zip-full \
|
||||
procps \
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -x -e -v
|
||||
|
||||
# This script is for building mar and mbsdiff
|
||||
|
||||
WORKSPACE=$HOME/workspace
|
||||
UPLOAD_DIR=$HOME/artifacts
|
||||
COMPRESS_EXT=xz
|
||||
|
||||
cd $WORKSPACE/build/src
|
||||
|
||||
. taskcluster/scripts/misc/tooltool-download.sh
|
||||
|
||||
export MOZ_OBJDIR=obj-mar
|
||||
|
||||
echo ac_add_options --enable-project=tools/update-packaging > .mozconfig
|
||||
|
||||
TOOLCHAINS="binutils clang"
|
||||
|
||||
for t in $TOOLCHAINS; do
|
||||
PATH="$WORKSPACE/build/src/$t/bin:$PATH"
|
||||
done
|
||||
|
||||
./mach build -v
|
||||
|
||||
mkdir mar-tools
|
||||
cp $MOZ_OBJDIR/dist/host/bin/{mar,mbsdiff} mar-tools/
|
||||
|
||||
tar -acf mar-tools.tar.$COMPRESS_EXT mar-tools/
|
||||
mkdir -p $UPLOAD_DIR
|
||||
cp mar-tools.tar.$COMPRESS_EXT $UPLOAD_DIR
|
|
@ -12,8 +12,7 @@ cd $WORKSPACE
|
|||
|
||||
git clone -n https://github.com/upx/upx.git upx-clone
|
||||
cd upx-clone
|
||||
# https://github.com/upx/upx/releases/tag/v3.95
|
||||
git checkout 7a3637ff5a800b8bcbad20ae7f668d8c8449b014 # Asserts integrity of the clone (right?)
|
||||
git checkout d31947e1f016e87f24f88b944439bbee892f0429 # Asserts integrity of the clone (right?)
|
||||
git submodule update --init --recursive
|
||||
cd src
|
||||
make -j$(nproc)
|
||||
|
|
|
@ -17,10 +17,10 @@ from taskgraph.util.schema import (
|
|||
resolve_keyed_by,
|
||||
)
|
||||
from taskgraph.util.taskcluster import get_artifact_prefix
|
||||
from taskgraph.util.platforms import archive_format, architecture
|
||||
from taskgraph.util.platforms import archive_format, executable_extension, architecture
|
||||
from taskgraph.util.workertypes import worker_type_implementation
|
||||
from taskgraph.transforms.job import job_description_schema
|
||||
from voluptuous import Required, Optional, Extra
|
||||
from voluptuous import Required, Optional
|
||||
|
||||
|
||||
packaging_description_schema = schema.extend({
|
||||
|
@ -30,9 +30,6 @@ packaging_description_schema = schema.extend({
|
|||
# unique label to describe this repackaging task
|
||||
Optional('label'): basestring,
|
||||
|
||||
Optional('worker-type'): basestring,
|
||||
Optional('worker'): object,
|
||||
|
||||
# treeherder is allowed here to override any defaults we use for repackaging. See
|
||||
# taskcluster/taskgraph/transforms/task.py for the schema details, and the
|
||||
# below transforms for defaults of various values.
|
||||
|
@ -59,7 +56,6 @@ packaging_description_schema = schema.extend({
|
|||
|
||||
# All l10n jobs use mozharness
|
||||
Required('mozharness'): {
|
||||
Extra: object,
|
||||
# Config files passed to the mozharness script
|
||||
Required('config'): optionally_keyed_by('build-platform', [basestring]),
|
||||
|
||||
|
@ -80,7 +76,7 @@ packaging_description_schema = schema.extend({
|
|||
# from mozharness.
|
||||
# - `inputs` are passed as long-options, with the filename prefixed by
|
||||
# `MOZ_FETCH_DIR`. The filename is interpolated by taskgraph
|
||||
# (`{archive_format}`).
|
||||
# (`{archive_format}`, `{executable_extension}`).
|
||||
# - `output` is passed to `--output`, with the filename prefixed by the output
|
||||
# directory.
|
||||
PACKAGE_FORMATS = {
|
||||
|
@ -91,7 +87,7 @@ PACKAGE_FORMATS = {
|
|||
],
|
||||
'inputs': {
|
||||
'input': 'target{archive_format}',
|
||||
'mar': 'mar-tools/mar',
|
||||
'mar': 'mar{executable_extension}',
|
||||
},
|
||||
'output': "target.complete.mar",
|
||||
},
|
||||
|
@ -102,7 +98,7 @@ PACKAGE_FORMATS = {
|
|||
],
|
||||
'inputs': {
|
||||
'input': 'target{archive_format}',
|
||||
'mar': 'mar',
|
||||
'mar': 'mar{executable_extension}',
|
||||
},
|
||||
'output': "target.bz2.complete.mar",
|
||||
},
|
||||
|
@ -209,6 +205,10 @@ def make_job_description(config, jobs):
|
|||
# repackage-signing can end up with multiple deps...
|
||||
raise NotImplementedError(
|
||||
"Can't repackage a signing task with multiple dependencies")
|
||||
signing_dependencies = dep_job.dependencies
|
||||
# This is so we get the build task in our dependencies to
|
||||
# have better beetmover support.
|
||||
dependencies.update(signing_dependencies)
|
||||
|
||||
attributes = copy_attributes_from_dependent_job(dep_job)
|
||||
attributes['repackage_type'] = 'repackage'
|
||||
|
@ -230,6 +230,7 @@ def make_job_description(config, jobs):
|
|||
if config.kind == 'repackage-msi':
|
||||
treeherder['symbol'] = 'MSI({})'.format(locale or 'N')
|
||||
|
||||
build_task = None
|
||||
signing_task = None
|
||||
repackage_signing_task = None
|
||||
for dependency in dependencies.keys():
|
||||
|
@ -237,12 +238,21 @@ def make_job_description(config, jobs):
|
|||
repackage_signing_task = dependency
|
||||
elif 'signing' in dependency:
|
||||
signing_task = dependency
|
||||
else:
|
||||
build_task = dependency
|
||||
|
||||
_fetch_subst_locale = 'en-US'
|
||||
if locale:
|
||||
# XXXCallek: todo: rewrite dependency finding
|
||||
# Use string splice to strip out 'nightly-l10n-' .. '-<chunk>/opt'
|
||||
# We need this additional dependency to support finding the mar binary
|
||||
# Which is needed in order to generate a new complete.mar
|
||||
dependencies['build'] = "build-{}/opt".format(
|
||||
dependencies[build_task][13:dependencies[build_task].rfind('-')])
|
||||
build_task = 'build'
|
||||
_fetch_subst_locale = locale
|
||||
|
||||
worker_type = job['worker-type']
|
||||
level = config.params['level']
|
||||
build_platform = attributes['build_platform']
|
||||
|
||||
use_stub = attributes.get('stub-installer')
|
||||
|
@ -256,6 +266,7 @@ def make_job_description(config, jobs):
|
|||
command = copy.deepcopy(PACKAGE_FORMATS[format])
|
||||
substs = {
|
||||
'archive_format': archive_format(build_platform),
|
||||
'executable_extension': executable_extension(build_platform),
|
||||
'_locale': _fetch_subst_locale,
|
||||
'architecture': architecture(build_platform),
|
||||
'version_display': config.params['version'],
|
||||
|
@ -287,18 +298,32 @@ def make_job_description(config, jobs):
|
|||
},
|
||||
})
|
||||
|
||||
worker = job.get('worker', {})
|
||||
worker.update({
|
||||
worker = {
|
||||
'chain-of-trust': True,
|
||||
'max-run-time': 7200 if build_platform.startswith('win') else 3600,
|
||||
# Don't add generic artifact directory.
|
||||
'skip-artifacts': True,
|
||||
})
|
||||
}
|
||||
|
||||
if locale:
|
||||
# Make sure we specify the locale-specific upload dir
|
||||
worker.setdefault('env', {}).update(LOCALE=locale)
|
||||
|
||||
if build_platform.startswith('win'):
|
||||
worker_type = 'aws-provisioner-v1/gecko-%s-b-win2012' % level
|
||||
run['use-magic-mh-args'] = False
|
||||
run['use-caches'] = False
|
||||
else:
|
||||
if build_platform.startswith(('linux', 'macosx')):
|
||||
worker_type = 'aws-provisioner-v1/gecko-%s-b-linux' % level
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
'Unsupported build_platform: "{}"'.format(build_platform)
|
||||
)
|
||||
|
||||
run['tooltool-downloads'] = 'internal'
|
||||
worker['docker-image'] = {"in-tree": "debian7-amd64-build"}
|
||||
|
||||
worker['artifacts'] = _generate_task_output_files(
|
||||
dep_job, worker_type_implementation(config.graph_config, worker_type),
|
||||
repackage_config=repackage_config,
|
||||
|
@ -326,7 +351,7 @@ def make_job_description(config, jobs):
|
|||
'extra': job.get('extra', {}),
|
||||
'worker': worker,
|
||||
'run': run,
|
||||
'fetches': _generate_download_config(dep_job, build_platform,
|
||||
'fetches': _generate_download_config(dep_job, build_platform, build_task,
|
||||
signing_task, repackage_signing_task,
|
||||
locale=locale,
|
||||
project=config.params["project"],
|
||||
|
@ -343,7 +368,7 @@ def make_job_description(config, jobs):
|
|||
yield task
|
||||
|
||||
|
||||
def _generate_download_config(task, build_platform, signing_task,
|
||||
def _generate_download_config(task, build_platform, build_task, signing_task,
|
||||
repackage_signing_task, locale=None, project=None,
|
||||
existing_fetch=None):
|
||||
locale_path = '{}/'.format(locale) if locale else ''
|
||||
|
@ -365,6 +390,9 @@ def _generate_download_config(task, build_platform, signing_task,
|
|||
'extract': False,
|
||||
},
|
||||
],
|
||||
build_task: [
|
||||
'host/bin/mar',
|
||||
],
|
||||
})
|
||||
elif build_platform.startswith('win'):
|
||||
fetch.update({
|
||||
|
@ -375,6 +403,9 @@ def _generate_download_config(task, build_platform, signing_task,
|
|||
},
|
||||
'{}setup.exe'.format(locale_path),
|
||||
],
|
||||
build_task: [
|
||||
'host/bin/mar.exe',
|
||||
],
|
||||
})
|
||||
|
||||
use_stub = task.attributes.get('stub-installer')
|
||||
|
|
|
@ -167,8 +167,19 @@ def make_job_description(config, jobs):
|
|||
'skip-artifacts': True,
|
||||
}
|
||||
|
||||
worker_type = 'aws-provisioner-v1/gecko-%s-b-linux' % level
|
||||
worker['docker-image'] = {"in-tree": "debian7-amd64-build"}
|
||||
if build_platform.startswith('win'):
|
||||
worker_type = 'aws-provisioner-v1/gecko-%s-b-win2012' % level
|
||||
run['use-magic-mh-args'] = False
|
||||
else:
|
||||
if build_platform.startswith('macosx'):
|
||||
worker_type = 'aws-provisioner-v1/gecko-%s-b-linux' % level
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
'Unsupported build_platform: "{}"'.format(build_platform)
|
||||
)
|
||||
|
||||
run['tooltool-downloads'] = 'internal'
|
||||
worker['docker-image'] = {"in-tree": "debian7-amd64-build"}
|
||||
|
||||
worker['artifacts'] = _generate_task_output_files(
|
||||
dep_job, worker_type_implementation(config.graph_config, worker_type),
|
||||
|
|
|
@ -5,10 +5,10 @@ platform = "win32"
|
|||
config = {
|
||||
"repack_id": os.environ.get("REPACK_ID"),
|
||||
|
||||
# ToolTool
|
||||
"tooltool_manifest_src": 'browser\\config\\tooltool-manifests\\{}\\releng.manifest'.format(platform),
|
||||
'tooltool_url': 'https://tooltool.mozilla-releng.net/',
|
||||
'run_configure': False,
|
||||
'tooltool_cache': os.environ.get('TOOLTOOL_CACHE'),
|
||||
|
||||
'env': {
|
||||
'PATH': "%(abs_input_dir)s/upx/bin:%(PATH)s",
|
||||
}
|
||||
'run_configure': False,
|
||||
}
|
||||
|
|
|
@ -5,9 +5,10 @@ platform = "win32"
|
|||
config = {
|
||||
"locale": os.environ.get("LOCALE"),
|
||||
|
||||
'run_configure': False,
|
||||
# ToolTool
|
||||
"tooltool_manifest_src": 'browser\\config\\tooltool-manifests\\{}\\releng.manifest'.format(platform),
|
||||
'tooltool_url': 'https://tooltool.mozilla-releng.net/',
|
||||
'tooltool_cache': os.environ.get('TOOLTOOL_CACHE'),
|
||||
|
||||
'env': {
|
||||
'PATH': "%(abs_input_dir)s/upx/bin:%(PATH)s",
|
||||
}
|
||||
'run_configure': False,
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@ platform = "win64"
|
|||
config = {
|
||||
"repack_id": os.environ.get("REPACK_ID"),
|
||||
|
||||
# ToolTool
|
||||
"tooltool_manifest_src": 'browser\\config\\tooltool-manifests\\{}\\releng.manifest'.format(platform),
|
||||
'tooltool_url': 'https://tooltool.mozilla-releng.net/',
|
||||
'run_configure': False,
|
||||
'tooltool_cache': os.environ.get('TOOLTOOL_CACHE'),
|
||||
|
||||
'env': {
|
||||
'PATH': "%(abs_input_dir)s/upx/bin:%(PATH)s",
|
||||
}
|
||||
'run_configure': False,
|
||||
}
|
||||
|
|
|
@ -5,9 +5,10 @@ platform = "win64"
|
|||
config = {
|
||||
"locale": os.environ.get("LOCALE"),
|
||||
|
||||
'run_configure': False,
|
||||
# ToolTool
|
||||
"tooltool_manifest_src": 'browser\\config\\tooltool-manifests\\{}\\releng.manifest'.format(platform),
|
||||
'tooltool_url': 'https://tooltool.mozilla-releng.net/',
|
||||
'tooltool_cache': os.environ.get('TOOLTOOL_CACHE'),
|
||||
|
||||
'env': {
|
||||
'PATH': "%(abs_input_dir)s/upx/bin:%(PATH)s",
|
||||
}
|
||||
'run_configure': False,
|
||||
}
|
||||
|
|
|
@ -93,7 +93,6 @@ class Repackage(BaseScript):
|
|||
command=command,
|
||||
cwd=dirs['abs_mozilla_dir'],
|
||||
halt_on_failure=True,
|
||||
env=self.query_env(),
|
||||
)
|
||||
|
||||
def _run_tooltool(self):
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
# 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/.
|
||||
|
||||
DIRS += [
|
||||
'/modules/libmar/src',
|
||||
'/modules/libmar/tool',
|
||||
'/other-licenses/bsdiff',
|
||||
]
|
|
@ -307,6 +307,34 @@ const nsTArray<GfxDriverInfo> &GfxInfo::GetGfxDriverInfo() {
|
|||
GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
|
||||
nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
|
||||
V(13, 15, 100, 1), "FEATURE_FAILURE_OLD_FGLRX", "fglrx 13.15.100.1");
|
||||
|
||||
////////////////////////////////////
|
||||
// FEATURE_WEBRENDER
|
||||
|
||||
// Mesa baseline (chosen arbitrarily as that which ships with
|
||||
// Ubuntu 18.04 LTS).
|
||||
APPEND_TO_DRIVER_BLOCKLIST(
|
||||
OperatingSystem::Linux,
|
||||
(nsAString &)GfxDriverInfo::GetDeviceVendor(VendorMesaAll),
|
||||
GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_WEBRENDER,
|
||||
nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
|
||||
V(18, 2, 8, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA", "Mesa 18.2.8.0");
|
||||
|
||||
// Disable on all NVIDIA devices for now.
|
||||
APPEND_TO_DRIVER_BLOCKLIST(
|
||||
OperatingSystem::Linux,
|
||||
(nsAString &)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
|
||||
GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_WEBRENDER,
|
||||
nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
|
||||
V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_NO_LINUX_NVIDIA", "");
|
||||
|
||||
// Disable on all ATI devices for now.
|
||||
APPEND_TO_DRIVER_BLOCKLIST(
|
||||
OperatingSystem::Linux,
|
||||
(nsAString &)GfxDriverInfo::GetDeviceVendor(VendorATI),
|
||||
GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_WEBRENDER,
|
||||
nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
|
||||
V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_NO_LINUX_ATI", "");
|
||||
}
|
||||
return *sDriverInfo;
|
||||
}
|
||||
|
|
|
@ -1602,9 +1602,9 @@ const nsTArray<GfxDriverInfo>& GfxInfo::GetGfxDriverInfo() {
|
|||
////////////////////////////////////
|
||||
// FEATURE_WEBRENDER
|
||||
|
||||
// We are blocking all non-Nvidia cards in gfxPlatform.cpp where we check
|
||||
// for the WEBRENDER_QUALIFIED feature. However we also want to block some
|
||||
// specific Nvidia cards for being too low-powered, so we do that here.
|
||||
// We are blocking most hardware explicitly in gfxPlatform.cpp where we
|
||||
// check for the WEBRENDER_QUALIFIED feature. However we also want to block
|
||||
// some specific Nvidia cards for being too low-powered, so we do that here.
|
||||
APPEND_TO_DRIVER_BLOCKLIST2(
|
||||
OperatingSystem::Windows10,
|
||||
(nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
|
||||
|
|
Загрузка…
Ссылка в новой задаче